<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>redhat on Digi Hunch</title><link>https://static.digihunch.com/tag/redhat/</link><description>Recent content in redhat on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Tue, 08 Apr 2025 14:41:31 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/redhat/index.xml" rel="self" type="application/rss+xml"/><item><title>Kubernetes Platform as a Service and Red Hat OpenShift</title><link>https://static.digihunch.com/2023/06/kubernetes-paas-and-red-hat-openshift/</link><pubDate>Sun, 25 Jun 2023 11:10:15 -0400</pubDate><guid>https://static.digihunch.com/2023/06/kubernetes-paas-and-red-hat-openshift/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-rosa.webp" alt="Featured image of post Kubernetes Platform as a Service and Red Hat OpenShift" /&gt;&lt;h2 class="wp-block-heading"&gt;The Three-layer model&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Kubernetes is so complex that it becomes a buzz word itself. I categorize the related work into three layers: a cluster layer, a platform layer and an application layer, by their purposes. The three layers are illustrated as below:&lt;/p&gt;&#10;&lt;p class="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="471px" viewBox="-0.5 -0.5 471 161" style="max-width:100%;max-height:161px;"&gt;&lt;defs&gt;&lt;style type="text/css"&gt;@import url(https://fonts.googleapis.com/css?family=Architects+Daughter);&amp;#xa;&lt;/style&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="470" height="160" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/&gt;&lt;rect x="210" y="60" width="130" height="40" fill="#f5f5f5" stroke="#666666" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 80px; margin-left: 211px;"&gt;&lt;div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Kubernetes Platform&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="275" y="84" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Kubernetes Platform&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="210" y="100" width="130" height="40" fill="#f5f5f5" stroke="#666666" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 120px; margin-left: 211px;"&gt;&lt;div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Kubernetes Cluster&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="275" y="124" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Kubernetes Cluster&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="210" y="20" width="130" height="40" fill="#f5f5f5" stroke="#666666" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 40px; margin-left: 211px;"&gt;&lt;div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Application&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="275" y="44" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Application&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 380 60 L 375 60 Q 370 60 370 70 L 370 90 Q 370 100 365 100 L 362.5 100 Q 360 100 365 100 L 367.5 100 Q 370 100 370 110 L 370 130 Q 370 140 375 140 L 380 140" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" transform="translate(370,0)scale(-1,1)translate(-370,0)" pointer-events="all"/&gt;&lt;path d="M 190 100 L 185 100 Q 180 100 180 110 L 180 115 Q 180 120 175 120 L 172.5 120 Q 170 120 175 120 L 177.5 120 Q 180 120 180 130 L 180 135 Q 180 140 185 140 L 190 140" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;rect x="0" y="105" width="170" height="30" fill="none" stroke="none" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 120px; margin-left: 1px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;AKS, EKS, self-built cluster&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="124" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;AKS, EKS, self-built cluster&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="375" y="85" width="85" height="30" fill="none" stroke="none" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 83px; height: 1px; padding-top: 100px; margin-left: 376px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;ROSA, ARO&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="418" y="104" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;ROSA, ARO&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 190 60 L 185 60 Q 180 60 180 70 L 180 75 Q 180 80 175 80 L 172.5 80 Q 170 80 175 80 L 177.5 80 Q 180 80 180 90 L 180 95 Q 180 100 185 100 L 190 100" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/&gt;&lt;rect x="10" y="65" width="160" height="30" fill="none" stroke="none" pointer-events="all"/&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 80px; margin-left: 11px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;OpenShift Container Platform&lt;br /&gt;Self-managed platform&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="90" y="84" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;OpenShift Container Platfo&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Text is not SVG &amp;#8211; cannot display&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Let&amp;#8217;s examine each layer in this model and where the Kubernetes Platform as a Service fits in.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-the-kubernetes-cluster-layer"&gt;The Kubernetes Cluster Layer&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;At the bottom, the Kubernetes Cluster layer is the foundational layer. It focus on using self-hosted VMs or cloud resources to build a functional Kubernetes cluster and worker node groups. A functional cluster includes a highly available control plane, as well as scalable node groups that all communicate with the control plane. Cloud Service Providers like AWS and Azure provides managed Kubernetes service, which takes away the complexity (and flexibility as well) of managing control plane components such as etcd store and API server. The managed services also automatically provisions computing nodes and join them into the cluster. The cluster layer may also involve integration with of CNI and CSI, to ensure Pod-to-Pod communication and available storage classes. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Professionals working at this layer are infrastructure experts who understand networking, storage, as well as how to manage cloud resources or VMs, infrastructure as code. On a daily basis, they deal with VPCs/V-Nets, subnets, EBS/Azure Disk, File storage, EC2/Azure VMs, etc. When the team is doing a bad job at this layer, you might see symptoms like unresponsive cluster API, orphaned worker nodes, or kubectl failing to connect to cluster endpoint.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The tenants (applications) of the Kubernetes platform does not directly interact with this layer. If you decide to switch CSP vendor, this layer requires 100% re-engineering because the managed Kubernetes service by each CSP is different.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;The Kubernetes Platform Layer&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Platform layer sits in the middle. When organization decides to adopt Kubernetes, they often underestimate the efforts required in this layer. This layer works on a functional cluster, without directly interacting with the underlying cloud resources. This layer involves any Kubernetes abstractions that do not creates tangible business value. Rather, this layer is an enabler. It allows the applications to deploy smoothly, evolve quickly, and more importantly, focus on the business.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Teams working on this layer needs to be Kubernetes experts. On a daily basis, they play with common CNCF toolings, such as Prometheus, ArgoCD, Istio, Cilium, Tekton, Open Policy Agent, etc. They are comfortable with Operators, Helm Charts, Ingress, etc. Inside of the Kubernetes cluster, they also manage the foundational services such as Event streaming (e.g. Kafka), PostgreSQL database (e.g. PostgreSQL), software-defined storage (e.g. Ceph), service mesh (e.g. Istio), Authentication (e.g. Keykloak) , etc. These services act as the infrastructure layer to the business workload. If the team is doing a bad job, you would see data loss with database, observability service not populating data, ingress does not process request, etc. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The tenants (application) share services in this layer. If you decide to switch CSP vendor. I estimate 80% of the work at this layer is portable, and 20% requires re-engineering. That is because each CSP offers different external resources, therefor the low level Kubernetes objects in this layer, such as storage classes, load balancers, supported CNIs are different. High level objects such as Kafka remains portable across platforms.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;The Application Layer&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The next layer at the top is application layer. Workloads in this layer are directly linked to the business value. The applications are very diverse. Most of the time, the release team is the main player at this layer. If the organization develops its own application, the software development team also work at this layer. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In terms of knowledge, the members of development team are experts in software engineering, and Software Development Life Cycle (SDLC), etc. On a daily basis, they deal with programming languages, product development, build and release. If they screw up their work, expect business errors, such as orders sent to wrong client, incorrect balance sheet, etc. This team has high visibility in the organization due to its direct link to business value.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This layer of work involves multiple tenants. Each tenant is isolated within their own namespace. When you switch CSP vendor, this layer should be readily portable with minimal effort.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It is also worth noting that, with solid platform and cluster layers, the team working at this layer do not write bespoke code for networking, observability, authentication and authorization, encryption and many other aspects not relevant to the core business. Once deployed, the application services are resilient, scale to demands, and cost efficient. This layer reaps the benefits of Kubernetes. &lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Kubernetes Platform as a Service&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As the Kubernetes dust is still settling, a builder&amp;#8217;s title may not always reflect which layer she or he focuses on. Today it is pretty common for infrastructure engineers to expand their role into the platform layer, or likewise, a software engineer to drill down to the platform layer. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The boundary between platform layer and cluster layer is clear. The cluster layer deals with underlying infrastructure, either in the cloud or on premise. They abstract away the complex infrastructure world from those working with the platform layer. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The boundary between platform layer and application layer is a little tricky to articulate. The application layer focuses on implementing the business logics. The platform layer takes care of the functions that are not part of business logic but essential to the business application. Take an HTTP request for example, application developer should not have to write code to terminate TLS (not part of business logic). They should only write the code to process the HTTP request (business logic). TLS termination is delegated to an Ingress, to be configured by platform builders. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The folks working at the Platform layer needs to interface with both sides. They provide Platform as a Service to the Application teams. However, their work appears mostly invisible in an organization. Their effort is oftentimes underestimated. There are several reasons for that. First, the platform layer does not directly create tangible business value. They are just someone else&amp;#8217;s enabler. Second, their building blocks involve a lot of abstractions by Kubernetes API. Third, the idea of platform engineering is newly emerged. There hasn&amp;#8217;t been a populous recognition of its value.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Red Hat OpenShift Container Platform&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The platform team builds the platform with their choice of open-source tools. For &lt;a href="https://static.digihunch.com/2022/09/build-a-kubernetes-cluster/"&gt;clusters&lt;/a&gt; using OpenShift Kubernetes &lt;a href="https://www.redhat.com/en/technologies/cloud-computing/openshift/kubernetes-engine"&gt;Engine&lt;/a&gt;, Red Hat introduces Open Shift container platform consisting of Red Hat&amp;#8217;s opinionated (but validated) choice of toolings, for example:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;OpenShift Service Mesh: Istio&lt;/li&gt;&#10;&lt;li&gt;OpenShift Streams: Apache Kafka&lt;/li&gt;&#10;&lt;li&gt;OpenShift GitOps: ArgoCD&lt;/li&gt;&#10;&lt;li&gt;OpenShift Container Platform Pipelines: Tekton&lt;/li&gt;&#10;&lt;li&gt;OpenShift Serverless: Knative&lt;/li&gt;&#10;&lt;li&gt;OpenShift Data Foundation: Ceph&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Clients building their clusters with OpenShift Kubernetes Engine may build their own platform with the toolings in the &lt;a href="https://www.redhat.com/en/technologies/cloud-computing/openshift"&gt;OpenShift enterprise Kubernetes container platform&lt;/a&gt;. For more services, check out the &lt;a href="https://docs.openshift.com/container-platform/4.13/welcome/index.html"&gt;documentation&lt;/a&gt; for OpenShift Container Platform. For customers with OpenShift Kubernetes &lt;a href="https://www.redhat.com/en/technologies/cloud-computing/openshift/kubernetes-engine"&gt;Engine&lt;/a&gt;, their options to DIY platform are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Entry-Level: Red Hat OpenShift Kubernetes Engine: Enterprise Kubernetes distribution on RHEL CoreOS&lt;/li&gt;&#10;&lt;li&gt;Mid-Level: Red Hat OpenShift Container Platform (RHOCP):&lt;/li&gt;&#10;&lt;li&gt;Plus-Level: Red Hat OpenShift Platform Plus: RHOCP + advanced cluster management, security, data management essentials, enterprise container registry&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OpenShift runs the business model of Kubernetes PaaS.This is a unique business model that I do not find a matching competitor. Even if you choose to DIY your own platform, the Red Hat&amp;#8217;s choices are still a great reference. The OpenShift enterprise Kubernetes container platform maps perfectly to the platform layer of the three-layer model, aiming to simplify the work in the platform layer.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Managed RedHat OpenShift&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;At first, the OpenShift container platform started as a value add-on to the Kubernetes Engine. Now it&amp;#8217;s a separate product line in their business model. In the mean time, OpenShift partners with major CSPs, to develop the cloud service editions, including:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Red Hat OpenShift on AWS (ROSA)&lt;/li&gt;&#10;&lt;li&gt;Microsoft Azure Red Hat OpenShift (ARO)&lt;/li&gt;&#10;&lt;li&gt;Red Hat OpenShift Dedicated &amp;#8211; on AWS and GCP&lt;/li&gt;&#10;&lt;li&gt;Red Hat OpenShift on IBM Cloud&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;These offerings are managed Kubernetes Platform as a Service in the cloud. Since RedHat is the only player in this model, we can refer to them as managed OpenShift services. In addition to an already-confusing world of Kubernetes platform portfolios, these offerings gives consumers even &lt;a href="https://www.redhat.com/en/technologies/cloud-computing/openshift/openshift-cloud-services"&gt;more options&lt;/a&gt;. On AWS for example, users have the following options:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Managed Platform: OpenShift Dedicated, managed by Red Hat&lt;/li&gt;&#10;&lt;li&gt;Managed Platform: Red Hat OpenShift Service on AWS (ROSA), managed by Red Hat and AWS&lt;/li&gt;&#10;&lt;li&gt;Self-built cluster: OpenShift Container Platform&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://pages.awscloud.com/apn-tv-491.html"&gt;This&lt;/a&gt; video discussed more details about these options, such as support model. It is also worth noting that these options tend to be much pricier than managed clusters such as EKS and AKS.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Since a Managed RedHat Platform makes it easy to deploy, let&amp;#8217;s take ROSA as an example and create a cluster. To enable ROSA in AWS &lt;a href="https://console.aws.amazon.com/rosa/home"&gt;console&lt;/a&gt;, click on &amp;#8220;Getting Started&amp;#8221;. The next page ensures ROSA is enabled and checks other prerequisite such as meeting service quotas and creating ELB service-linked role, as show below:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="912" height="1024" src="https://static.digihunch.com/wp-content/uploads/2023/06/rosa-ui.webp" alt="" class="wp-image-12926" srcset="https://static.digihunch.com/wp-content/uploads/2023/06/rosa-ui.webp 912w, https://static.digihunch.com/wp-content/uploads/2023/06/rosa-ui-267x300.webp 267w, https://static.digihunch.com/wp-content/uploads/2023/06/rosa-ui-768x862.webp 768w" sizes="auto, (max-width: 912px) 100vw, 912px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now, with an AWS account (and ROSA enabled), a RedHat account, and the &lt;a href="https://docs.redhat.com/en/documentation/red_hat_openshift_service_on_aws/4/html/rosa_cli/rosa-get-started-cli"&gt;rosa-cli&lt;/a&gt; utility, we can create a cluster with just a few commands. As a note, be wary of the cost and do not forget to delete the cluster afterwards.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Create a ROSA cluster&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With the following set of commands, we can kick off cluster creation, using STS. We can bring our own VPC, so long as it meets certain &lt;a href="https://docs.openshift.com/rosa/rosa_planning/rosa-sts-aws-prereqs.html#rosa-vpc_rosa-sts-aws-prereqs"&gt;prerequisites&lt;/a&gt;. I use the Terraform template in the &lt;a href="https://github.com/digihunch/vpc-base"&gt;vpc-base&lt;/a&gt; project, to create the underlying VPC. We&amp;#8217;ll need the followings from this template:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;The CIDR range of the VPC: as &lt;a href="https://github.com/digihunch/cloudkube/blob/9d8667c81fc0989e6e48fba9ed5a87ab761d4044/aws_vpc/variables.tf#L3"&gt;input&lt;/a&gt; with a default&lt;/li&gt;&#10;&lt;li&gt;The subnet Ids of the private subnet to place, printed in the &lt;a href="https://github.com/digihunch/cloudkube/blob/9d8667c81fc0989e6e48fba9ed5a87ab761d4044/aws_vpc/output.tf#L18"&gt;output&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The subnets are private subnets, because we want to provision the cluster with private node and private endpoint. When we use rosa CLI, we provide the CIDR and subnet IDs.&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;&lt;span style="color:#75715e"&gt;# start with AWS cli configured to the correct profile&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rosa login &lt;span style="color:#75715e"&gt;# with redhat account and past token&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rosa create account-roles --mode auto -y &lt;span style="color:#75715e"&gt;# this command creates the IAM roles ManagedOpenShift-*-Role, with RedHat account as trust entity&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rosa verify permissions &lt;span style="color:#75715e"&gt;# optional&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rosa verify quota &lt;span style="color:#75715e"&gt;# optional&lt;/span&gt;&#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;export ROSA_CLUSTER_NAME&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;dhc&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OPENSHIFT_VERSION&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4.13.4 &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AWS_ACCOUNT_ID&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;aws sts get-caller-identity --query Account --output text&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AWS_DEFAULT_REGION&lt;span style="color:#f92672"&gt;=&lt;/span&gt;us-east-1&#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;rosa create cluster --sts --private &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --cluster-name $ROSA_CLUSTER_NAME &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --multi-az &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --private-link &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --region $AWS_DEFAULT_REGION &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --version $OPENSHIFT_VERSION &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --enable-autoscaling &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --min-replicas &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --max-replicas &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --compute-machine-type m5.xlarge &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --machine-cidr 147.206.0.0/16 &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --subnet-ids subnet-052852a1fb4d7d2ad,subnet-06d8d40ae39d55c47,subnet-0f67ce08bc588012c&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The CLI will pick up the correct VPC by CIDR, and prompt you to confirm creation of private cluster. After the command kicks off, it will wait for OIDC provider creation, and role creation. Then it uses a Terraform template to create the related resources including VPC. Use this command to check status:&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;rosa list clusters&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rosa describe cluster -c dhc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When the second command displays the state of waiting (Waiting for OIDC configuration), we can create OIDC provider:&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;rosa create operator-roles -c $ROSA_CLUSTER_NAME --mode auto --yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rosa create oidc-provider -c $ROSA_CLUSTER_NAME --mode auto --yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Throughout the process, we can monitor the install log (terraform output) with:&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;rosa logs install -c dhc --watch&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In the log, you might see errors with terminals connecting to the terraform backend, which doesn’t necessarily indicate a cluster creation error. Always check the cluster state until it reports success. &lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Kick the tires &lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Eventually the describe cluster command will show ready state. We can now create an admin user:&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;rosa create admin -c $ROSA_CLUSTER_NAME&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command above prints an &lt;code&gt;oc&lt;/code&gt; command (&lt;a href="https://access.redhat.com/documentation/en-us/openshift_container_platform/4.2/html/cli_tools/openshift-cli-oc"&gt;OpenShift CLI&lt;/a&gt;, equivalent to kubectl) with password to log in. Let&amp;#8217;s examine the cluster with oc. Because it is a private cluster, the endpoint is not available publicly. However, it is accessible from the Bastion host. Use the SSM Session Manager technique from my &lt;a href="https://static.digihunch.com/2023/06/connect-kubectl-to-private-kubernetes-cluster-in-eks-and-aks/"&gt;previous post&lt;/a&gt; to SSH to the Bastion Host, which should have &lt;code&gt;oc&lt;/code&gt; installed. To install &lt;code&gt;oc&lt;/code&gt; yourself, use HomeBrew on Mac. On Linux or Windows, log on to &lt;a href="https://console.redhat.com/openshift/downloads"&gt;OpenShift console&lt;/a&gt;, go to Downloads on the left pannel and find it out under CLI tools.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;code&gt;oc&lt;/code&gt; command may report insecure TLS on the login URL. Wait for a few minutes for the certificate to come off as safe. Once you run the &lt;code&gt;oc&lt;/code&gt; command with password, it should return &amp;#8220;Login successful&amp;#8221; and then we can connect to the cluster:&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;$ oc get node &lt;span style="color:#75715e"&gt;# or kubectl get node&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME STATUS ROLES AGE VERSION&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-135-41.ec2.internal Ready,SchedulingDisabled infra,worker 3m5s v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-155-141.ec2.internal Ready control-plane,master 25m v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-156-81.ec2.internal Ready worker 19m v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-164-21.ec2.internal Ready infra,worker 3m3s v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-179-90.ec2.internal Ready worker 19m v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-191-118.ec2.internal Ready,SchedulingDisabled control-plane,master 26m v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-192-232.ec2.internal Ready worker 19m v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-193-198.ec2.internal Ready infra,worker 3m20s v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ip-147-206-218-114.ec2.internal Ready control-plane,master 26m v1.26.5+7d22122&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;You can use oc the same way you&amp;#8217;d use kubectl. Both works through &lt;a href="https://kubernetes.io/docs/tasks/extend-kubernetes/socks5-proxy-access-api/"&gt;SOCK5 proxy.&lt;/a&gt; In the meantime, log in to the &lt;a href="https://console.redhat.com/openshift"&gt;RedHat console&lt;/a&gt; with your Red Hat credential, you can see the cluster in Ready state as well:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="330" src="https://static.digihunch.com/wp-content/uploads/2023/06/openshift-ui.webp" alt="" class="wp-image-12927" srcset="https://static.digihunch.com/wp-content/uploads/2023/06/openshift-ui.webp 1024w, https://static.digihunch.com/wp-content/uploads/2023/06/openshift-ui-300x97.webp 300w, https://static.digihunch.com/wp-content/uploads/2023/06/openshift-ui-768x248.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;code&gt;rosa create admin&lt;/code&gt; command creates a &lt;code&gt;htpasswd&lt;/code&gt; type (username-password) of identity provider (IdP) with a user named cluster-admin and a preset password. In real life however, we often configure third party IdP with OIDC integration. I&amp;#8217;ll have to leave this to the &lt;a href="https://static.digihunch.com/2023/07/authenticate-kube-apiserver-via-oidc/"&gt;next blog post&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We shall see the nodes as EC2 instances from AWS console as well. Note that there are three roles: control-plane, worker and infra. The &lt;a href="https://docs.openshift.com/container-platform/4.13/nodes/nodes/nodes-nodes-creating-infrastructure-nodes.html"&gt;infra nodes&lt;/a&gt; are for infrastructure services. These services (Ingress Controller, GitOps, Pipeliens) are the ones in the platform player as we discussed above. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are many &lt;a href="https://access.redhat.com/solutions/6347302"&gt;customizations&lt;/a&gt; you can make in this installation process and I&amp;#8217;d have to defer to the &lt;a href="https://docs.openshift.com/rosa/rosa_planning/rosa-sts-aws-prereqs.html"&gt;ROSA documentation&lt;/a&gt;. To clean up, use the following ROSA 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;rosa remove cluster -c dhc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The output also gives you the command to delete operator roles and OIDC provider, for example:&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;rosa delete operator-roles -c 23o4u3j98tqmlbtjo612opb7a4bbim5f --mode auto --yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rosa delete oidc-provider -c 23o4u3j98tqmlbtjo612opb7a4bbim5f --mode auto --yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then we can destroy the VPCs using terraform.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;ROSA with HCP&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Update Oct 2023:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The deployment above provisioned a few nodes for control plane, which add to the overall time to provision a cluster. In Aug 2023, there is a new option Hosted Control Plane (HCP) that came to allow users to provision a hosted control plane. This results in cost savings and shorter time to provision a cluster. &lt;a href="https://docs.aws.amazon.com/ROSA/latest/userguide/rosa-deployment-options.html"&gt;Here&lt;/a&gt; is a table of comparison between the ROSA with HCP and ROSA classic.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Final words&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this post, I discussed the three-layer model and pointed out that platform layer isn&amp;#8217;t as visible as the other two. I also experimented ROSA as a turn-key Kubernetes platform with its opinionated stack of services.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Some misinformed organizations even skip the entire platform layer in their estimate of effort. They build a cluster, ran a hello-world service and assumes they can start putting applications on the Kubernetes cluster. There are also customers who purchased the entire Managed OpenShift platform but only use it as a cluster. Yikes!&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The concept of Kubernetes platform, or generally platform engineering is still spreading. The consulting team that I worked in full-time last year re-branded itself as platform engineering. Marketings are pushing it. Builders are doing it. We&amp;#8217;ll keep an eye, on whether customers are buying it.&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/2023/06/connect-kubectl-to-private-kubernetes-cluster-in-eks-and-aks/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Connect kubectl to private Kubernetes cluster in EKS and AKS&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2023/07/oauth-2-0-and-oidc-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;OAuth 2.0 and OIDC 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Kafka high-level Overview</title><link>https://static.digihunch.com/2020/07/zookeeper-and-kafka-overview/</link><pubDate>Tue, 21 Jul 2020 23:19:00 -0400</pubDate><guid>https://static.digihunch.com/2020/07/zookeeper-and-kafka-overview/</guid><description>&lt;h3 class="wp-block-heading" id="h-zookeeper"&gt;Zookeeper&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;General definition of distributed system: a software system that is composed of &lt;strong&gt;independent &lt;/strong&gt;computing entities linked &lt;strong&gt;together &lt;/strong&gt;by a computer network whose components communicate and coordinate with each other to achieve a common computational goal. Implementing coordination among components of a distributed system is hard. For example, designated master node becomes single point of failure; cluster needs to detect availability of new nodes as it joins cluster.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Zookeeper is designed to &lt;strong&gt;simplify cluster coordination&lt;/strong&gt;. Zookeeper implements key aspects in cluster coordination, such as distributed consensus, group management, presence protocols and leader election. In order to coordinate a cluster, zookeeper itself also runs in its own cluster, called &lt;strong&gt;ensemble&lt;/strong&gt;. Zookeeper exposes a simple but powerful interface of primitives. Applications can be designed on these primitives implemented through ZooKeeper APIs to solve the problems of distributed synchronization, cluster configuration management, group membership, etc.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://zookeeper.apache.org/doc/r3.4.6/images/zkservice.jpg" alt=""/&gt;&lt;figcaption class="wp-element-caption"&gt;Zookeeper Ensemble&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Clients can connect to a Zookeeper service by connecting to any member of the ensemble. The members of the ensemble are aware of each other&amp;#8217;s state. As long as a majority of the nodes are available, the service will be available. &lt;strong&gt;Zookeeper cli (zkCli.sh)&lt;/strong&gt; can be used to connect to Zookeeper server. they can be downloaded from &lt;a href="https://zookeeper.apache.org/releases.html"&gt;here&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Zookeeper is integrated with many other services apart from Kafka, such as Nifi and Hadoop.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-kafka"&gt;&lt;strong&gt;Kafka&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://kafka.apache.org/"&gt;Kafka &lt;/a&gt;is a messaging system that is horizontally scalable, fault tolerant. It can also serve as queue storage system and stream processing system. It is distributed and use Zookeeper for cluster coordination. Each node is called a broker.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://kafka.apache.org/25/images/log_anatomy.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Topics &lt;/strong&gt;in Kafka (think of table in database) is a category or feed name to which messages (records) are published. Topic is broken up into ordered commit logs called partitions. Each partition has an ID. Each message in a partition is assigned an offset. Topics that are created in Kafka are distributed across brokers based on the partition, replication, and other factors. Each partition is replicated across several brokers depending on replication factor. For each partition, Kafka elect one replica as the leader of partition.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Writes to a partition is generally sequential. Reading messages can either be from the beginning, or rewind or skip to any port in partition given an offset value. Data in a topic is retained for a configurable period of time. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A &lt;strong&gt;message &lt;/strong&gt;is a unit of data in Kafka, in the format of key-value pair. A key is used to control the message that is to be written to partitions. Messages with the same keys are always written to the same partition (hash map)&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A &lt;strong&gt;producer &lt;/strong&gt;publishes new message to a topic. Producers do not care which partition the message is written to and will balance messages over every partition of a topic evenly. Directing messages to a partition is done using the message key and a partitioner, this will generate a hash of the key and map it to a partition.&lt;/p&gt;&#10;&lt;figure class="wp-block-image is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://kafka.apache.org/25/images/log_consumer.png" alt="" width="370" height="225"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A &lt;strong&gt;consumer &lt;/strong&gt;is subscribed to one or more topics and read messages sequentially. The consumer keeps track of messages it has consumed by keeping track on the offset of the message. The offset is a bit of metadata (an integer value that continually increases) that kafka adds to each message. Each partition has a unique offset which is stored with the offset of the last consumed message. A consumer can stop and start without losing its current state.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A Kafka &lt;strong&gt;broker &lt;/strong&gt;is designed to operate as part of a cluster. One broker in the cluster also function as the cluster&amp;#8217;s controller, which is responsible for administrative operations such as: assigning partitions to brokers; monitoring for broker failures in cluster. A particular partition is owned by a broker and that broker is called the leader of the partition.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;All consumers and producers operating on that partition must connect to the leader.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Kafka cluster may replicate across cluster using MirrorMaker.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Reference: &lt;strong&gt;Kafka: The Definitive Guide: Real-Time Data and Stream Processing at Scale&lt;/strong&gt;&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://static.digihunch.com/wp-content/uploads/2023/01/kafka-780x1024.jpeg" alt="" class="wp-image-7913" width="207" height="272" srcset="https://static.digihunch.com/wp-content/uploads/2023/01/kafka-780x1024.jpeg 780w, https://static.digihunch.com/wp-content/uploads/2023/01/kafka-229x300.jpeg 229w, https://static.digihunch.com/wp-content/uploads/2023/01/kafka-768x1008.jpeg 768w, https://static.digihunch.com/wp-content/uploads/2023/01/kafka.jpeg 1036w" sizes="auto, (max-width: 207px) 100vw, 207px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt; &lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/07/nfs-network-file-system-and-rpc-remote-procedure-call/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;How RPC and NFS work&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/07/overview-of-virtualization/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Virtualization 1 of 4 – Hypervisor&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Performance Analysis</title><link>https://static.digihunch.com/2020/06/performance-analysis-tools/</link><pubDate>Fri, 19 Jun 2020 16:47:01 -0400</pubDate><guid>https://static.digihunch.com/2020/06/performance-analysis-tools/</guid><description>&lt;h3 class="wp-block-heading" id="h-overview"&gt;Overview&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In 2015, Brendan Gregg posted two great articles&lt;a href="https://netflixtechblog.com/linux-performance-analysis-in-60-000-milliseconds-accc10403c55"&gt; &lt;/a&gt;on Netflix blog: &lt;a href="https://netflixtechblog.com/linux-performance-analysis-in-60-000-milliseconds-accc10403c55"&gt;Linux Performance Analysis in 60 seconds&lt;/a&gt;, and &lt;a href="https://netflixtechblog.com/netflix-at-velocity-2015-linux-performance-tools-51964ddb81cf"&gt;Linux Perfomrance Tools&lt;/a&gt;. They have great value when I was in a urgency to spot performance issues. The articles cover the essential tools for performance troubleshooting, including:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Check out load averages: w or uptime&lt;/li&gt;&#10;&lt;li&gt;Print kernel ring buffer: dmesg -T&lt;/li&gt;&#10;&lt;li&gt;Virtual memory status: vmstat 1&lt;/li&gt;&#10;&lt;li&gt;Multiple processor staticstics: mpstat -P ALL 1&lt;/li&gt;&#10;&lt;li&gt;Task status: pidstat 1&lt;/li&gt;&#10;&lt;li&gt;CPU and I/O status: iostat -xz 1&lt;/li&gt;&#10;&lt;li&gt;Free memory check: free -m&lt;/li&gt;&#10;&lt;li&gt;Network Activity record: sar -n DEV 1&lt;/li&gt;&#10;&lt;li&gt;TCP activity record: sar -n TCP,ETCP 1&lt;/li&gt;&#10;&lt;li&gt;Display processes: top&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We will dive into each of them in the next section.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-basic-troubleshooting"&gt;Basic Troubleshooting&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The command w is equivalent of uptime (which shows uptime since boot) and who (which shows logged-in users). It also displays load average for the last 1 minute, 5 minutes and 15 minutes. The number of load average reflects the overall system load (CPU + disks), and it is further discussed in this &lt;a href="http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html"&gt;post&lt;/a&gt; with a simple take away:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;If the averages are 0.0, then your system is idle.&lt;/li&gt;&#10;&lt;li&gt;If the 1 minute average is higher than the 5 or 15 minute averages, then load is increasing.&lt;/li&gt;&#10;&lt;li&gt;If the 1 minute average is lower than the 5 or 15 minute averages, then load is decreasing.&lt;/li&gt;&#10;&lt;li&gt;If they are higher than your CPU count, then you might have a performance problem (it depends).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When Linux load averages increase, you know you have higher demand for resources (CPUs, disks, and some locks), but you aren&amp;#8217;t sure which. You will need to switch to other metrics. Brendan recommend don&amp;#8217;t spend more than 5 seconds on these numbers.&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;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;dhunch@c7v-ghintapp01 ~&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ w&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 12:14:10 up &lt;span style="color:#ae81ff"&gt;46&lt;/span&gt; days, 16:41, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; users, load average: 2.69, 2.44, 2.29&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dhunch pts/0 w6v-ghas01 24Jun20 3days 0.36s 0.30s ssh c7v-bastion&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dhunch pts/1 202.95.88.111 12:02 2.00s 0.00s 0.00s w&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dhunch pts/4 w6v-ghas01 17Jun20 15days 0.15s 0.07s view readme.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Before moving to more insightful metrics, it is also worth a quick look into the kernel ring buffer with dmesg command (dmesg -T | less +G). This will allow us to capture obvious issues such as oom-killer or TCP request dropping.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The vmstat tool reports the statistics of &lt;strong&gt;virtual memory&lt;/strong&gt;. Servers have a fixed amount of physical memory, but they can run a set of applications that use a much larger amount of virtual memory. Application tend to reserve more memory than they need, and they usually operate on only a subset of their memory. In both cases, the operating system can keep the unused parts of memory on disk, and page it into physical memory only if it is needed. For the most part, this kind of memory management works well. But it doesn&amp;#8217;t always with Java applications due to Java heap. Once a system start swapping &amp;#8211; moving pages of data from main memory to disk, and vice versa, the performance tend to be bad. Systems must be configured so that swapping never occurs.&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;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;dhunch@c7v-ghintapp01 ~&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ vmstat &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; r b swpd free buff cache si so bi bo in cs us sy id wa st&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;239360&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;385928&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;36734692&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;93&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;239360&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;387732&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;36734704&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8017&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8524&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;85&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;239360&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;387608&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;36734904&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;57&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6768&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7680&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;86&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;239360&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;389008&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;36734904&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6366&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7300&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;86&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;239360&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;421728&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;36700144&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8141&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7957&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;86&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;239360&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;421984&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;36702048&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;467&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8994&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8362&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;85&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&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;The tool prints key server statistics each line, with the first line showing the average since boot. Here lists the explanation of some columns:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;r&lt;/strong&gt;: number of processes running on CPU and waiting for a turn. This provides a better signal than load averages for determining CPU saturation, as it does not include I/O. To interpret: an “r” value greater than the CPU count is saturation.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;swpd&lt;/strong&gt;: the amount of virtual memory used. This number should align with the used column for Swap row from free command.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;buff, cache&lt;/strong&gt;: buffer and cache. They should align with the buff/cache column form Mem row from free command.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;free&lt;/strong&gt;: free memory in kilobytes. This number should align with the free column for Mem row from free command. &lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;si, so&lt;/strong&gt;: swap-ins and swap-outs. As mentioned, if these are non-zero, you&amp;#8217;re out of memory.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;bi, bo&lt;/strong&gt;: blocks received from and sent to a blcok device (# of block per second)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;in, cs&lt;/strong&gt;: number of &lt;a href="https://en.wikipedia.org/wiki/Interrupt"&gt;interrupt&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Context_switch"&gt;context switches&lt;/a&gt; per second.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;us, sy, id, wa, st&lt;/strong&gt;: user, system, idle, wait I/O and stolen times. These are breakdowns of CPU time, on average across all CPUs. They should add up to 100% (or close). stolen time is amount of CPU time needed by a guest virtual machine that is not provided by the host. IO wait time is the CPU time waiting for I/O activity. Idle time could be several things: the process may be waiting for something (e.g. a response from database); the process may be blocked by a thread lock; or the process simply has nothing to do. user and system times are CPU times spent on user tasks and kernel tasks, respectively.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Out of these columns, watch for columns r, free, buff, cache, us, sy, id and wa at minimum. The combination of us and sy confirms if CPUs are busy. A constant degree of wa points to a disk bottleneck with too much time spent on pending disk I/O. The sy (kernel time) is necessary for I/O processing but sy stays high (e.g. constantly over 20%), it becomes interesting. Perhaps the kernel is processing I/O inefficiently.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For further per-CPU stats, use mpstat command (-P ALL), to prind CPU time breakdowns per CPU and check for imbalance. A single host CPU can be evidence of a single-threaded application. Here is an example output from a system of 16 CPU cores.&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;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;dhunch@c7v-ghintapp01 ~&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ mpstat -P ALL &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Linux 3.10.0-1062.12.1.el7.x86_64 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;c7v-ghintapp01.digihunch.com&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 08/01/20 _x86_64_ &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; CPU&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;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:23 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 all 13.77 0.00 0.19 0.00 0.00 0.00 0.00 0.00 0.00 86.05&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 2.02 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 97.98&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; 98.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 2.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; 2.02 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 97.98&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; 2.02 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 97.98&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; 2.94 0.00 0.98 0.00 0.00 0.00 0.00 0.00 0.00 96.08&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; 97.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 3.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; 0.99 0.00 0.99 0.00 0.00 0.00 0.00 0.00 0.00 98.02&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; 2.02 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 97.98&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; 1.98 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.02&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;13:47:24 &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;For a per process summary of CPU consumption, use pidstat command. It can be thought of a periodical snapshot of top command, allowing you to watch for patterns. The %CPU column is the total across all CPUs so 5 CPUs have a maximum value of 500.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If vmstate indicates some I/O issue, iostat tool can help us understand block devices, on both the workload applied and the resulting performance. Key columns are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;r/s, w/s, rkB/s, wkB/s&lt;/strong&gt;: delivered reads, writes, read Kbytes, and write Kbytes per second to the device. Use these for workload characterization. A performance problem may simply be due to an excessive load applied.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;await&lt;/strong&gt;: the average wait time for I/O in milliseconds. This is the time that the application suffers, as it includes both time queued and time being serviced. Larger than expected average times can be an indicator of device saturation, or malfunction.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;avgqu-sz&lt;/strong&gt;: the average number of requests issued to device. Values greater than 1 can be evidence of saturation (although devices can typically operate on requests in parallel, especially virtual devices which front multiple back-end disks.)&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;%util&lt;/strong&gt;: device utilization. This is really a busy percent, showing the time each second that the device was doing work. Values greater than 60% typically lead to poor performance (which should be seen in await), although it depends on the device. Values close to 100% usually indicate saturation.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I/O problem may either be inefficiencies in application that issues I/O request, or slowing disk unable to keep up with I/O requests. We review two examples here to illustrate each situation. The first output is 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;% iostat -xm &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;avg-cpu: %user %nice %system %iowait %steal %idle&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 23.45 0.00 37.89 0.10 0.00 38.56&#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; Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sda 0.00 11.60 0.60 24.20 0.02 0.14 13.35 0.15 6.06 5.33 6.08 0.42 1.04&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In the first example, the disk stat loosk up at first glance. The w_await (time to service I/O write) is fairly low at 6.08ms. However, the system is spending 37.89% of its time in the kernel. If all that system time is from the application, it suggest something inefficient is happening. The fact that the system is doing 24.2 writes per second is another clue: that is alot when writing only 0.14 MB per second (MBps). I/O has become a bottleneck, and the next step would be to look into how the application is performing its writes.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The second example output is 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;% iostat -xm &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;avg-cpu: %user %nice %system %iowait %steal %idle&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 35.05 0.00 7.85 47.89 0.00 9.20&#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; Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sda 0.00 0.20 1.00 163.40 0.00 81.09 1010.19 142.74 866.47 97.60 871.17 6.08 100.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In this example, it tells us that processes are spending 47.89% of their time in iowait, and the data to complete the I/O (w_await) is 871ms, the queue size is large, and the disk is writing at 81MB per second. This all points to disk I/O as a problem and that the amount of I/O in the application (or elsewhere in the system) must be reduced.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Bear in mind that poor performing disk I/O isn&amp;#8217;t necessarily an application issue. Many techniques are typically used to perform I/O asynchronously, so that the application doesn&amp;#8217;t block and suffer the latency directly (e.g. read-ahead for reads, and buffering for writes, also refer to &amp;#8220;&lt;a href="https://robertovitillo.com/why-you-should-measure-tail-latencies/"&gt;tail latency&lt;/a&gt;&amp;#8220;). &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that the acceptable utilization metric depends on the configuration of block device. If the storage is a logical disk device fronting many back-end disks (e.g. RAID 0), then 100% utilization may just mean that some I/O is being processed 100% of the time, however, the back-end disks may be far from being saturated, and may even be able to handle more work.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The free command gives the breakdown of memory usage. The right two columns are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;buffers&lt;/strong&gt;: for the buffer cache, used for block device I/O.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;cached&lt;/strong&gt;: for the page cache, used by file systems.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We just want to check that these aren&amp;#8217;t near-zero in size, which can lead to higher disk I/O (confirm using iostat), and worse performance. Linux uses free memory for the caches, but can reclaim it quickly if applications need it. So in a way the cached memory should be included in the free memory column. In this case, it&amp;#8217;s included in the available column. This &lt;a href="https://www.linuxatemyram.com/"&gt;website &lt;/a&gt;has further details.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To check interface stat, nicstat is a great tool but it isn&amp;#8217;t available by default in Linux. Instead we can run sar (-n DEV) to retrieve stats. &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;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;dhunch@c7v-ghintapp01 ~&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ sar -n DEV &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Linux 3.10.0-1062.12.1.el7.x86_64 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;c7v-ghintapp01.digihunch.com&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 08/01/20 _x86_64_ &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; CPU&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;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:51:25 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:51:26 eth0 3089.00 934.00 3815.33 834.61 0.00 0.00 0.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:51:26 lo 464.00 464.00 2289.07 2289.07 0.00 0.00 0.00&#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;16:51:26 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:51:27 eth0 956.00 586.00 826.66 211.34 0.00 0.00 0.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:51:27 lo 213.00 213.00 196.00 196.00 0.00 0.00 0.00&#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;16:51:27 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:51:28 eth0 349.00 181.00 52.32 147.19 0.00 0.00 0.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:51:28 lo 244.00 244.00 81.13 81.13 0.00 0.00 0.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Here rxkB/s/s and txkB/s represents receive and transmission throughput, as a measure of workload. If they reach the limit then the interface is the bottleneck.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On top of interface is the TCP layer, which can be monitored with sar again (-n ECP, ETCP). The key metrics are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;active/s&lt;/strong&gt;: number of locally-initiated (e.g. via connect()) TCP connections per second&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;passive/s&lt;/strong&gt;: number of remotely-initiated (e.g. via accept()) TCP connections per second&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;retrans/s&lt;/strong&gt;: number of TCP retransmits per second&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The active and passive counts are often useful as a rough measure of server load. It might help to think of active as outbound, and passive as inbound, but this isn&amp;#8217;t strictly true (e.g. consider a localhost to localhost connection). Retransmits are a sign of network or server issue; it may be an unreliable network (e.g. public Internet), or it may be due to a server being overloaded and dropping packets.&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;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;dhunch@c7v-ghintapp01 ~&lt;span style="color:#f92672"&gt;]&lt;/span&gt;$ sar -n TCP,ETCP &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Linux 3.10.0-1062.12.1.el7.x86_64 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;c7v-ghintapp01.digihunch.com&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 08/01/20 _x86_64_ &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; CPU&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;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:52:29 active/s passive/s iseg/s oseg/s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:52:30 0.00 1.00 28.00 35.00&#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;16:52:29 atmptf/s estres/s retrans/s isegerr/s orsts/s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:52:30 0.00 0.00 0.00 0.00 0.00&#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;16:52:30 active/s passive/s iseg/s oseg/s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:52:31 8.00 8.00 200.00 317.00&#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;16:52:30 atmptf/s estres/s retrans/s isegerr/s orsts/s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;16:52:31 0.00 1.00 1.00 0.00 3.00&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Last but not least is our favourite command top, which includes many of the metrics covered in previous tools. The downside to top is it is harder to see patterns over time, which may be more clear in tools like vmstat and pidstat, both of which produce rolling output.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Several tools introduced here involves sar, which is a great monitoring tool on its own that we need to be familiar with.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-system-activity-report-sar"&gt;System Activity Report (SAR)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Further to the basic tools, the sar command is very helpful as it stores historical stat every 10 minutes. Sar keeps 18 types of reports, all stored in /var/log/sa/. When viewing the report file, you may pipe the result to less command so it only prints header once. For example, if you would like to print CPU report for the 2nd of the month:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# sar -u -f /var/log/sa/sar02 | less&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If you check NFS client statistics for the 31st&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; # sar -n NFS -f /var/log/sa/sar31&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If you need to check network server statistics for today&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# sar -n NFS -f /var/log/sa/sar31&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Below are all types of reports:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;-u CPU utilization&lt;/li&gt;&#10;&lt;li&gt;-w task creation and system switching activity&lt;/li&gt;&#10;&lt;li&gt;-W swapping statistics&lt;/li&gt;&#10;&lt;li&gt;-B report paging&lt;/li&gt;&#10;&lt;li&gt;-b report I/O and transfer rate statistics&lt;/li&gt;&#10;&lt;li&gt;-R report memory statistics&lt;/li&gt;&#10;&lt;li&gt;-r memory utilization&lt;/li&gt;&#10;&lt;li&gt;-S swap space utilization&lt;/li&gt;&#10;&lt;li&gt;-H huge pages utilization statistics&lt;/li&gt;&#10;&lt;li&gt;-v inode&lt;/li&gt;&#10;&lt;li&gt;-q queue length and load average&lt;/li&gt;&#10;&lt;li&gt;-y TTY device activity&lt;/li&gt;&#10;&lt;li&gt;-d activity for each block device&lt;/li&gt;&#10;&lt;li&gt;-n network statistics, DEV (per interface)&lt;/li&gt;&#10;&lt;li&gt;-n network statistics, EDEV (error per interface)&lt;/li&gt;&#10;&lt;li&gt;-n network statistics, NFS (NFS client)&lt;/li&gt;&#10;&lt;li&gt;-n network statistics, NFSD (NFS server)&lt;/li&gt;&#10;&lt;li&gt;-n network statistics, SOCK (socket usage)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-berkeley-packet-filter-bpf-compiler-collection-bcc-tools"&gt;Berkeley Packet Filter (BPF) Compiler Collection (bcc) tools&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For advanced, low-level performance troubleshooting, the BCC tools provide a suite of tools. Here we only cover the installation of it.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In CentOS, install bcc-tools package with yum. When you try to run a command, such as cachestat, if you come across this error:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-bash: cachestat: command not found&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then you will need to add its path to default:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;export PATH=$PATH:/usr/share/bcc/tools&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Now if you run into this error:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chdir(/lib/modules/3.10.0-1062.12.1.el7.x86_64/build): No such file or directory&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Traceback (most recent call last):&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The file listed is a symbolic link, and if it is missing, you just need to install kernel-headers that matches the kernel version:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum install kernel-headers&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then you may use tools in /usr/share/bcc/tools. For example, cachestat help you display page cache hit ratio; gethostlatency shows DNS resolution latency; tcpconnect prints out active tcp connections (made via connect system call):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[root@dhunch ~]# /usr/share/bcc/tools/tcpconnect -t -P 8080 | gawk &amp;#39;{ print strftime(&amp;#34;%F %T  &amp;#34;), $0 }&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-06-13 00:16:57   TIME(s)  PID    COMM         IP SADDR            DADDR            DPORT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-06-13 02:16:57   0.000    15241  QNetworkAcce 4  10.100.22.21    10.101.84.10    8080&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-06-13 02:16:57   0.064    15241  QNetworkAcce 4  10.100.22.21    10.101.84.10    8080&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-06-13 02:16:57   0.438    15241  QNetworkAcce 4  10.100.22.21    10.101.84.10    8080&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command above outputs a&amp;nbsp;time and pid stamped log line every time&amp;nbsp;a TCP connection is made to port 8080; tcpaccept traces passive tcp connections (via accept system call). These tools are not as intrusive as tcpdump.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It is beyond the purpose of this article to get into details of each tool in the BFP suite. The tools are covered in detail in books &amp;#8220;&lt;a href="https://amzn.to/3fEWNkq"&gt;BPF Performance Tools&lt;/a&gt;&amp;#8221; and &amp;#8220;Linux Observability with BPF&amp;#8221;.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/06/network-analyzer-capture-filter-and-display-filter/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Capture filter and Display filter in Network Analyzer&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/06/iterate-through-cassandra-table-with-datastax-python-driver/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;DataStax Python Driver&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Balloon steals memory from virtual machines</title><link>https://static.digihunch.com/2020/05/understanding-where-the-memory-goes-on-linux-vm/</link><pubDate>Thu, 07 May 2020 19:49:00 -0400</pubDate><guid>https://static.digihunch.com/2020/05/understanding-where-the-memory-goes-on-linux-vm/</guid><description>&lt;p class="wp-block-paragraph"&gt;This article is my experience with memory balloon on virtual machine.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I came across an ElasticSearch server (ESXi guest with 32GB physical memory) where the main process keeps dying of OOM. Even worse, after the OOM event, the free memory left is about 10G and Elastic Search cannot start because its JVM is set with -Xms16g in /etc/elasticsearch/jvm.options. So I need to address the OutOfMemory error.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To understand what triggered OOM, we can use dmesg or just check /var/log/message, where the memory snapshot by OOM killer is displayed during the kernel panic:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: kworker/7:1 invoked oom-killer: gfp_mask=0x200d2, order=0, oom_score_adj=0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: kworker/7:1 cpuset=/ mems_allowed=0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: CPU: 7 PID: 13968 Comm: kworker/7:1 Kdump: loaded Not tainted 3.10.0-957.1.3.el7.x86_64 #1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 12/12/2018&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Workqueue: events_freezable vmballoon_work [vmw_balloon]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Call Trace:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa2961e41&amp;gt;] dump_stack+0x19/0x1b&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa295c86a&amp;gt;] dump_header+0x90/0x229&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa2301052&amp;gt;] ? ktime_get_ts64+0x52/0xf0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23581ef&amp;gt;] ? delayacct_end+0x8f/0xb0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23ba4e4&amp;gt;] oom_kill_process+0x254/0x3d0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23b9f8d&amp;gt;] ? oom_unkillable_task+0xcd/0x120&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23ba036&amp;gt;] ? find_lock_task_mm+0x56/0xc0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23bad26&amp;gt;] out_of_memory+0x4b6/0x4f0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa295d36e&amp;gt;] __alloc_pages_slowpath+0x5d6/0x724&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23c1105&amp;gt;] __alloc_pages_nodemask+0x405/0x420&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa240df68&amp;gt;] alloc_pages_current+0x98/0x110&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffc05f1f84&amp;gt;] vmballoon_work+0x454/0x6ff [vmw_balloon]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa22b9d4f&amp;gt;] process_one_work+0x17f/0x440&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa22bade6&amp;gt;] worker_thread+0x126/0x3c0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa22bacc0&amp;gt;] ? manage_workers.isra.25+0x2a0/0x2a0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa22c1c31&amp;gt;] kthread+0xd1/0xe0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa22c1b60&amp;gt;] ? insert_kthread_work+0x40/0x40&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa2974c37&amp;gt;] ret_from_fork_nospec_begin+0x21/0x21&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa22c1b60&amp;gt;] ? insert_kthread_work+0x40/0x40&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Mem-Info:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: active_anon:3649243 inactive_anon:439380 isolated_anon:0#012 active_file:480 inactive_file:693 isolated_file:0#012 unevictable:0 dirty:2 writeback:0 unstable:0#012 slab_reclaimable:77845 slab_unreclaimable:10219#012 mapped:10086 shmem:9596 pagetables:16727 bounce:0#012 free:50116 free_pcp:238 free_cma:0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA free:15892kB min:32kB low:40kB high:48kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15992kB managed:15908kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:16kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: lowmem_reserve[]: 0 2829 31993 31993&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA32 free:122768kB min:5972kB low:7464kB high:8956kB active_anon:471052kB inactive_anon:471040kB active_file:232kB inactive_file:460kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:3129216kB managed:2897760kB mlocked:0kB dirty:0kB writeback:0kB mapped:584kB shmem:300kB slab_reclaimable:23908kB slab_unreclaimable:3872kB kernel_stack:656kB pagetables:6440kB unstable:0kB bounce:0kB free_pcp:288kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:214 all_unreclaimable? no&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: lowmem_reserve[]: 0 0 29163 29163&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 Normal free:61804kB min:61576kB low:76968kB high:92364kB active_anon:14125920kB inactive_anon:1286480kB active_file:1688kB inactive_file:2312kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:30408704kB managed:29866500kB mlocked:0kB dirty:8kB writeback:0kB mapped:39760kB shmem:38084kB slab_reclaimable:287472kB slab_unreclaimable:36988kB kernel_stack:5680kB pagetables:60468kB unstable:0kB bounce:0kB free_pcp:804kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:698 all_unreclaimable? no&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: lowmem_reserve[]: 0 0 0 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA: 1*4kB (U) 0*8kB 1*16kB (U) 0*32kB 2*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15892kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA32: 407*4kB (UEM) 506*8kB (UEM) 431*16kB (UM) 364*32kB (M) 272*64kB (UM) 179*128kB (UM) 99*256kB (UM) 35*512kB (M) 11*1024kB (M) 2*2048kB (M) 0*4096kB = 123164kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 Normal: 15576*4kB (UM) 39*8kB (UM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 62616kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 44652 total pagecache pages&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 34162 pages in swap cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Swap cache stats: add 10884045, delete 10845872, find 3294122/3678936&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Free swap = 0kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Total swap = 2097148kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 8388478 pages RAM&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 0 pages HighMem/MovableOnly&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 193436 pages reserved&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 3164] 0 3164 47420 12996 100 6314 0 systemd-journal&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 3192] 0 3192 11158 2 24 174 -1000 systemd-udevd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 3198] 0 3198 66023 0 31 117 0 lvmetad&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6051] 0 6051 15511 20 29 138 -1000 auditd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6073] 81 6073 14557 83 32 88 -900 dbus-daemon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6075] 32 6075 18412 16 39 166 0 rpcbind&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6076] 0 6076 50404 0 37 171 0 gssproxy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6077] 0 6077 5422 50 15 41 0 irqbalance&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6078] 0 6078 118943 155 85 362 0 NetworkManager&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6086] 0 6086 6594 47 18 41 0 systemd-logind&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6087] 0 6087 24892 0 42 402 0 VGAuthService&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6088] 0 6088 56746 113 58 246 0 vmtoolsd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6089] 999 6089 153086 130 61 1787 0 polkitd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6129] 38 6129 11817 39 27 140 0 ntpd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6464] 0 6464 56962 132 62 970 0 snmpd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6468] 0 6468 97733 4770 100 482 0 rsyslogd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6470] 0 6470 470477 6332 100 781 0 sh-metricbeat&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6472] 0 6472 250084 2279 72 2367 0 sh-filebeat&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6483] 0 6483 28189 26 57 231 -1000 sshd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6485] 0 6485 143455 107 97 2667 0 tuned&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6569] 0 6569 76290 625 41 188 0 avagent.bin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6574] 29 6574 12239 1 27 254 0 rpc.statd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6601] 0 6601 31572 30 18 129 0 crond&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6609] 0 6609 27523 1 10 32 0 agetty&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 7451] 494 7451 315970 36412 364 8550 0 node&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [11272] 0 11272 39154 0 80 336 0 sshd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [11277] 0 11277 28885 2 12 112 0 bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [16070] 495 16070 47122631 3994129 15027 457539 0 java&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [16264] 495 16264 18032 0 31 162 0 controller&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Out of memory: Kill process 16070 (java) score 512 or sacrifice child&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Killed process 16264 (controller) total-vm:72128kB, anon-rss:0kB, file-rss:0kB, shmem-rss:0kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: java invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: java cpuset=/ mems_allowed=0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: CPU: 2 PID: 16265 Comm: java Kdump: loaded Not tainted 3.10.0-957.1.3.el7.x86_64 #1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 12/12/2018&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Call Trace:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa2961e41&amp;gt;] dump_stack+0x19/0x1b&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa295c86a&amp;gt;] dump_header+0x90/0x229&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa2301052&amp;gt;] ? ktime_get_ts64+0x52/0xf0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23581ef&amp;gt;] ? delayacct_end+0x8f/0xb0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23ba4e4&amp;gt;] oom_kill_process+0x254/0x3d0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23b9f8d&amp;gt;] ? oom_unkillable_task+0xcd/0x120&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23ba036&amp;gt;] ? find_lock_task_mm+0x56/0xc0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23bad26&amp;gt;] out_of_memory+0x4b6/0x4f0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa295d36e&amp;gt;] __alloc_pages_slowpath+0x5d6/0x724&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23c1105&amp;gt;] __alloc_pages_nodemask+0x405/0x420&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa240df68&amp;gt;] alloc_pages_current+0x98/0x110&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23b6347&amp;gt;] __page_cache_alloc+0x97/0xb0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23b8fa8&amp;gt;] filemap_fault+0x298/0x490&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffc0484d0e&amp;gt;] __xfs_filemap_fault+0x7e/0x1d0 [xfs]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa22c2dc0&amp;gt;] ? wake_bit_function+0x40/0x40&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffc0484f0c&amp;gt;] xfs_filemap_fault+0x2c/0x30 [xfs]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23e444a&amp;gt;] __do_fault.isra.59+0x8a/0x100&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23e49fc&amp;gt;] do_read_fault.isra.61+0x4c/0x1b0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23e93a4&amp;gt;] handle_pte_fault+0x2f4/0xd10&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa23ebedd&amp;gt;] handle_mm_fault+0x39d/0x9b0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa296f5e3&amp;gt;] __do_page_fault+0x203/0x500&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa296f915&amp;gt;] do_page_fault+0x35/0x90&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [&amp;amp;lt;ffffffffa296b758&amp;gt;] page_fault+0x28/0x30&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Mem-Info:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: active_anon:3607073 inactive_anon:480522 isolated_anon:0#012 active_file:8 inactive_file:0 isolated_file:0#012 unevictable:0 dirty:0 writeback:1 unstable:0#012 slab_reclaimable:75170 slab_unreclaimable:10131#012 mapped:2070 shmem:9592 pagetables:16696 bounce:0#012 free:50006 free_pcp:72 free_cma:0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA free:15892kB min:32kB low:40kB high:48kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15992kB managed:15908kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:16kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: lowmem_reserve[]: 0 2829 31993 31993&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA32 free:122560kB min:5972kB low:7464kB high:8956kB active_anon:471000kB inactive_anon:471076kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:3129216kB managed:2897760kB mlocked:0kB dirty:0kB writeback:0kB mapped:292kB shmem:288kB slab_reclaimable:22832kB slab_unreclaimable:3752kB kernel_stack:672kB pagetables:6408kB unstable:0kB bounce:0kB free_pcp:272kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:215 all_unreclaimable? yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: lowmem_reserve[]: 0 0 29163 29163&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 Normal free:61572kB min:61576kB low:76968kB high:92364kB active_anon:13957292kB inactive_anon:1451012kB active_file:32kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:30408704kB managed:29866500kB mlocked:0kB dirty:0kB writeback:4kB mapped:7988kB shmem:38080kB slab_reclaimable:277848kB slab_unreclaimable:36756kB kernel_stack:5664kB pagetables:60376kB unstable:0kB bounce:0kB free_pcp:16kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:500 all_unreclaimable? yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: lowmem_reserve[]: 0 0 0 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA: 1*4kB (U) 0*8kB 1*16kB (U) 0*32kB 2*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15892kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 DMA32: 393*4kB (UEM) 490*8kB (UEM) 453*16kB (EM) 369*32kB (UEM) 269*64kB (M) 180*128kB (M) 98*256kB (M) 35*512kB (M) 12*1024kB (UM) 1*2048kB (M) 0*4096kB = 122148kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 Normal: 15440*4kB (UM) 1*8kB (U) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 61768kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 42975 total pagecache pages&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 33308 pages in swap cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Swap cache stats: add 10884233, delete 10846914, find 3294127/3678944&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Free swap = 0kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Total swap = 2097148kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 8388478 pages RAM&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 0 pages HighMem/MovableOnly&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: 193436 pages reserved&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 3164] 0 3164 47420 4016 100 6314 0 systemd-journal&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 3192] 0 3192 11158 2 24 174 -1000 systemd-udevd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 3198] 0 3198 66023 0 31 117 0 lvmetad&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6051] 0 6051 15511 20 29 138 -1000 auditd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6073] 81 6073 14557 78 32 88 -900 dbus-daemon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6075] 32 6075 18412 16 39 166 0 rpcbind&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6076] 0 6076 50404 0 37 171 0 gssproxy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6077] 0 6077 5422 46 15 41 0 irqbalance&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6078] 0 6078 118943 155 85 362 0 NetworkManager&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6086] 0 6086 6594 42 18 41 0 systemd-logind&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6087] 0 6087 24892 0 42 402 0 VGAuthService&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6088] 0 6088 56746 91 58 246 0 vmtoolsd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6089] 999 6089 153086 130 61 1787 0 polkitd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6129] 38 6129 11817 36 27 140 0 ntpd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6464] 0 6464 56962 130 62 970 0 snmpd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6468] 0 6468 97733 1215 100 485 0 rsyslogd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6470] 0 6470 470477 6230 100 781 0 sh-metricbeat&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6472] 0 6472 250084 2279 72 2367 0 sh-filebeat&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6483] 0 6483 28189 26 57 231 -1000 sshd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6485] 0 6485 143455 107 97 2667 0 tuned&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6569] 0 6569 76290 625 41 188 0 avagent.bin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6574] 29 6574 12239 1 27 254 0 rpc.statd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6601] 0 6601 31572 27 18 129 0 crond&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 6609] 0 6609 27523 1 10 32 0 agetty&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [ 7451] 494 7451 315970 36412 364 8550 0 node&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [11272] 0 11272 39154 0 80 336 0 sshd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [11277] 0 11277 28885 2 12 112 0 bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: [16070] 495 16070 47122631 3993992 15027 457699 0 java&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Out of memory: Kill process 16291 (java) score 512 or sacrifice child&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:15 elastichost kernel: Killed process 16070 (java) total-vm:188490524kB, anon-rss:15975968kB, file-rss:0kB, shmem-rss:0kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:16 elastichost systemd: elasticsearch.service: main process exited, code=killed, status=9/KILL&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:16 elastichost systemd: Unit elasticsearch.service entered failed state.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Apr 26 04:18:16 elastichost systemd: elasticsearch.service failed.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The line &amp;#8220;Free swap = 0kB&amp;#8221; suggest the trigger of OOM is out of swap. So does ElasticSearch contribute to the swap shortage?&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;ElasticSearch was the main process on the VM and I noticed that the OS did not &lt;a href="https://static.digihunch.com/2018/04/centos-remove-swap-safely/"&gt;disable swap&lt;/a&gt;, which does not align with the&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.3/setup-configuration-memory.html"&gt; best practice&lt;/a&gt; from ElasticSearch community. In order to find out whether Elastic Search is pushed to use swap, we can get the process ID:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pidof java&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;ElasticSearch happens to be the only Java based process and the PID is 2283, the following command shows the swap usage by this process:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat /proc/2283/status | grep VmSwap&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If it shows a non-zero value, then ElasticSearch is using swap and you should expect some performance issues. We definitely should &lt;a href="https://static.digihunch.com/2018/04/centos-remove-swap-safely/"&gt;disable swap&lt;/a&gt; on ElasticSearch but does that solve the problem? Probably not because we didn&amp;#8217;t address what caused the memory pressure in the first place. Disabling swap most likely makes ElastciSearch last longer before something else such as shortage of available memory triggers OOM. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In search for the source of memory shortage, I checked the result of free command and the top command. The free command (-mh) shows the following:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total used free shared buff/cache available&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mem: 31G 20G 10G 117M 243M 10G&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Swap: 2.0G 249M 1.8G&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;I tried to follow my example from a &lt;a href="https://static.digihunch.com/2020/04/how-memory-usage-adds-up-in-linux/"&gt;previous post &lt;/a&gt;to make sense of the memory reads. When I monitor process with top and watch for RSS column, I cannot identify a single process that even takes more than a few hundred megabytes. I&amp;#8217;ve downloaded a tool smem from epel repo, and the result of &amp;#8220;smem -kt&amp;#8221; suggest that the total RSS is about 372.2M:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1778" height="206" src="https://static.digihunch.com/wp-content/uploads/2020/05/image.png" alt="" class="wp-image-979"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;So there is about 19.6GB of memory usage unaccounted for. There is something that takes this much memory in the VM and haunting round even after OOM killer! &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Inspired by &lt;a href="https://unix.stackexchange.com/questions/259659/high-memory-usage-but-no-process-is-using-it"&gt;this&lt;/a&gt; post, I was able to identify the culprit, that is the memory balloon. We don&amp;#8217;t have access to the host but from the Guest OS, we can tell by vmware-toolbox-cmd (need to install yum package open-vm-tools):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vmware-toolbox-cmd stat balloon&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The result displays a whopping 20807 MB as &lt;a href="https://en.wikipedia.org/wiki/Memory_ballooning"&gt;memory balloon&lt;/a&gt;! &lt;a href="https://techdocs.broadcom.com/us/en/vmware-cis/vsphere/vsphere/6-5/vsphere-resource-management-6-5/administering-memory-resources/memory-reclamation/memory-balloon-driver.html"&gt;This&lt;/a&gt; needs to be sent to PaaS vendor for investigation but it is likely a result of memory over-allocation/over-commitment at host level, as well as the setup where the memory of guest is not reserved. Looking at the original log snippet, the line with &amp;#8220;events_freezable vmballoon_work&amp;#8221; is also an indicator of balloon causing the OOM.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hypervisor needs memory ballooning to reclaim memory from guest. Since the guest OS does not expect the amount of physical memory to change, hypervisor has to maintain the illusion that the guest has its fixed amount of physical memory. The hypervisor first computes the amount of memory that needs to reclaim, then it leverage some low-level mechanism such as a balloon driver (a pseudo-device driver) installed on guest. The driver communicates with hypervisor and is told to allocate or de-allocate memory. If the driver is told to allocate memory to host, it tells the guest OS to pin the allocated pages into physical memory so they are locked and the physical memory available to guest OS is decreased. All these low level mechanisms explains why it is hard to account for memory consumption based on process running in Guest OS.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Memory balloon is a dynamic process and the hypervisor adjusts the size of balloon. However, the hypervisor, the guest OS and the application process (ElasticSearch in this case) may enter a nuance interaction:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;The hypervisor reclaims memory from guest OS (ballooning);&lt;/li&gt;&#10;&lt;li&gt;Guest OS panicked with OOM exception;&lt;/li&gt;&#10;&lt;li&gt;OOM picks a process to kill, based on oom_score. Unfortunately, the true culprit (balloon) is not visible to guest OS, hence exempted from being considered to kill.&lt;/li&gt;&#10;&lt;li&gt;By killing the application process (usually the main application for VM), a fair chunk of guest memory is freed up;&lt;/li&gt;&#10;&lt;li&gt;the balloon then became more aggressive on the guest as seeing more memory becomes &amp;#8220;available&amp;#8221;;&lt;/li&gt;&#10;&lt;li&gt;the application on guest then does not have minimum memory on guest OS to start;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;How to solve this problem? There are several things to consider. On the hypervisor, keep the entire or part of the guest memory reserved for start of application. Tune the OOM scoring so the non-critical application get killed. Implement application daemon, etc.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/04/cassandra-data-model-as-opposed-to-relational-database/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Cassandra data model (as opposed to relational model)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/05/revamp-ansible-directory-for-scalability-1-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Ansible at scale 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>How memory usage adds up in Linux</title><link>https://static.digihunch.com/2020/04/how-memory-usage-adds-up-in-linux/</link><pubDate>Sun, 19 Apr 2020 21:12:56 -0400</pubDate><guid>https://static.digihunch.com/2020/04/how-memory-usage-adds-up-in-linux/</guid><description>&lt;p class="wp-block-paragraph"&gt;There are too many metrics that describes some aspects about memory in Linux. This posting will make sense of those common metrics in Linux, CentOS as an example.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The most fundamental command is free and my favourite switch is -h for human readable reads. You can use -m, -k, -b for different units. The result looks like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total used free shared buff/cache available&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mem: 32780168 16832160 3200408 101356 12747600 15399528&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Swap: 2097148 2055148 42000&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Swap is essentially disk space and many application such as Cassandra, ElasticSearch recommend disabling swap as best practice and they do not want disk speed to drag the performance of memory. Many suggest that swap is not needed in today&amp;#8217;s era at all given the amount of memory for cheap. This is &lt;a href="https://askubuntu.com/questions/291378/do-we-still-need-swap-partitions-on-servers"&gt;debatable&lt;/a&gt;. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With the row for Mem, the four columns should add up to the total, as suggested in the chart below. &lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="http://blog.yufeng.info/wp-content/uploads/2013/01/free1.jpg" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;total = free + used + shared + buff/cache &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The four columns from free command output are supposed to always add up to the physical memory size. This command simplifies things quite a bit and each of these values are actually taken from certain lines in /proc/meminfo:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e7f5fe"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Metric from free command&lt;/td&gt;&lt;td&gt;Metric in /proc/meminfo&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;total&lt;/td&gt;&lt;td&gt;MemTotal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;used&lt;/td&gt;&lt;td&gt;??&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;free&lt;/td&gt;&lt;td&gt;MemFree&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;shared&lt;/td&gt;&lt;td&gt;Shmem&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;buff/cache&lt;/td&gt;&lt;td&gt;Cached + Slab&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;available&lt;/td&gt;&lt;td&gt;MemAvailable&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The buffer and cache (and even swap) can be freed by &lt;a href="https://www.tecmint.com/clear-ram-memory-cache-buffer-and-swap-space-on-linux/"&gt;command&lt;/a&gt;. The value of used doesn&amp;#8217;t seem to come from anwhere in /proc/meminfo, but it should be calculable from the memory used per process, which can be seen from top command.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the result of top command, the column RSS (resident set size) is from the VmRSS value in /proc/&amp;lt;pid&amp;gt;/status, it is the actual physical memory consumed by the process. This value is originally from the second read in /proc/&amp;lt;pid&amp;gt;/statm, which represents the number of pages. For example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[ghunch@centos ~]$ cat /proc/6495/status | grep VmRSS ; cat /proc/6495/statm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;VmRSS:&#9;20852916 kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;49829626 5213229 1212275 1 0 5773980 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[ghunch@centos ~]$ getconf PAGE_SIZE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4096&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Linux default page size is 4096 or 4K, so in the result from above, 5213229 x 4kB = 20852916 kB, which is the size of memory taken by process ID 6459. Therefore if we go through all processes and add up the VmRSS, we should get (close to) the used memory?&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;But wait a second, we have not account for slab info (memory used by kernel) yet, which is displayed in /proc/slabinfo. To calculate the total size taken by slab, we use &amp;lt;num_objs&amp;gt; and &amp;lt;objsize&amp;gt; columns from /proc/slabinfo.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apart from that there is &lt;a href="https://en.wikipedia.org/wiki/Page_table"&gt;page table&lt;/a&gt;, the table that stores the mapping between virtual address and physical address, is stored in the physical memory as well and the size is specified in the PageTables entry in /proc/meminfo. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now our equation becomes:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Used Memory = (RSS for all processes) + (all objects in slab) + (page table)&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We can use the following script to calculate the used memory and compare it with free command output.&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;&lt;span style="color:#75715e"&gt;#/bin/bash&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; PROC in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;ls /proc/|grep &lt;span style="color:#e6db74"&gt;&amp;#34;^[0-9]&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; -f /proc/$PROC/statm &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TEP&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;cat /proc/$PROC/statm | awk &lt;span style="color:#e6db74"&gt;&amp;#39;{print ($2)}&amp;#39;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RSS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;expr $RSS + $TEP&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;RSS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;expr $RSS &lt;span style="color:#ae81ff"&gt;\*&lt;/span&gt; 4&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PageTable&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;grep PageTables /proc/meminfo | awk &lt;span style="color:#e6db74"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SlabInfo&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;cat /proc/slabinfo |awk &lt;span style="color:#e6db74"&gt;&amp;#39;BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}&amp;#39;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#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;echo $RSS&lt;span style="color:#e6db74"&gt;&amp;#34;KB&amp;#34;&lt;/span&gt;, $PageTable&lt;span style="color:#e6db74"&gt;&amp;#34;KB&amp;#34;&lt;/span&gt;, $SlabInfo&lt;span style="color:#e6db74"&gt;&amp;#34;MB&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;printf &lt;span style="color:#e6db74"&gt;&amp;#34;rss+pagetable+slabinfo=%sMB\n&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;echo $RSS/1024 + $PageTable/1024 + $SlabInfo|bc&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;free -m&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Running it require root access and the bc package installed. The result is most likely greater than the used memory value. Below is the result from my server:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;89925884KB, 201788KB, 3303.92MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rss+pagetable+slabinfo=91318.92MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; total used free shared buff/cache available&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mem: 128772 87032 726 498 41013 40346&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Swap: 2047 3 2044&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;So the result is over by (91318 &amp;#8211; 87032) = 4286M. This is due to shared memory. The RSS value from above include memory from shared libraries as long as the pages from those libraries are in the memory. If multiple processes use the same library, the memory from shared library is counted multiple times. Check out the difference between &lt;a href="https://en.wikipedia.org/wiki/Resident_set_size"&gt;RSS&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Proportional_set_size"&gt;PSS&lt;/a&gt; (proportional set size) &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;[Disclaimer] The chart and script are stolen from this authors &lt;a href="http://www.programmersought.com/article/6127180173/"&gt;post&lt;/a&gt;.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/04/common-local-git-operations/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Common local Git operations&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/04/cassandra-data-model-as-opposed-to-relational-database/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Cassandra data model (as opposed to relational model)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>High Availability and Load Balancer</title><link>https://static.digihunch.com/2020/01/several-ways-to-ensure-high-availability/</link><pubDate>Wed, 22 Jan 2020 20:49:00 -0400</pubDate><guid>https://static.digihunch.com/2020/01/several-ways-to-ensure-high-availability/</guid><description>&lt;h3 class="wp-block-heading" id="h-overview"&gt;Overview&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Fault tolerance and high availability are two architectural characteristics that people often confuse with each other. High availability focuses on minimizing downtime. It guarantees uptime, but not performance in the event of component failures. Fault tolerance, on the other hand, focuses on stable capacity even in the event of component failures. Fault tolerance has higher bar, and therefore is more expensive. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Suppose an application requires four servers to meet performance goal. Placing two servers in each of the two AZs will meet HA criteria but not FT requirement. In the event of an AZ failure, application can operate at degraded performance yet still be highly available. However, FT requires stable capacity and to meet FT requirement, we&amp;#8217;d have to place four servers in each AZ. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;High availability can be achieved either by clustering, or load balancing. A cluster involves several nodes, all able to perform the same function, but may take different roles at different times (e.g. primary, standby) in order for the cluster to perform its function as a single system. In Linux, clustering is implemented by pacemaker or corosync. With a high load system, it is common to set up load balancing system to achieve high availability (and fault tolerance).&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-load-balancing"&gt;Load balancing&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The idea of load balancing is simple: load goes high and we want to scale horizontally instead of simply upgrading server hardware. At a high level, there has been three approaches to load balancing:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;DNS rotating:&lt;/strong&gt; (aka. DNS round robin) DNS record resolves to multiple IPs, very simple and cheap to implement. Since DNS is cached, the load distribution will come imbalanced and it&amp;#8217;s hard to re-balance, making this a very limited approach;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Hardware Load Balancer&lt;/strong&gt;: using dedicated hardware device to configure load balancing. This option is expensive and only enterprises can afford it (&lt;a class="rank-math-link" href="https://kemptechnologies.com/compare-kemp-to-f5-big-ip-ltm-citrix-netscaler-mpx-load-balancers/"&gt;here&lt;/a&gt;&amp;#8216;s some pricing information). A classic load balancer operates at layer 3 and 4, which is also known as POLB (plain old load balancer). It is the core functionality of hardware load balancer. The hardware load balancer on the market today usually come with a variety of add-on features, such as advanced load balancing (L4, L7 path-based, script driven), compression, caching, SSL offloading, and even DDoS mitigation, etc. The whole suite of features makes it an Application Delivery Controller (ADC). Therefore many refer to hardware load balancer as &lt;a href="https://www.f5.com/company/blog/go-beyond-polb-plain-old-load-balancing"&gt;hardware-based ADC&lt;/a&gt; to highlight the features in addition to POLB. Hardware-based ADCs ship with manufactures hardware, with specialized processors, advanced network hardware, and often &lt;a href="https://www.f5.com/services/resources/white-papers/software-defined-hardware-enabling-performance-and-agility-with-the-big-ip-iseries-architecture"&gt;ASIC&lt;/a&gt; (application specific integrated circuit). At a higher expense, they have better reliability and capacity. Some major market players are:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;F5 &amp;#8211; &lt;a class="rank-math-link" href="https://www.f5.com/services/resources/white-papers"&gt;Big IP&lt;/a&gt;, F5 also has a &lt;a href="https://devcentral.f5.com/s/articles/what-is-load-balancing-24740"&gt;good article &lt;/a&gt;about history of load balancer.&lt;/li&gt;&#10;&lt;li&gt;Cisco &amp;#8211; Citrix A&lt;a href="https://www.citrix.com/products/citrix-adc/"&gt;https://www.citrix.com/products/citrix-adc/&lt;/a&gt;DC (formerly NetScaler ADC)&lt;/li&gt;&#10;&lt;li&gt;A10 Networks &amp;#8211; &lt;a class="rank-math-link" href="https://www.a10networks.com/products/thunder-adc/"&gt;Thunder&lt;/a&gt; (general) and &lt;a class="rank-math-link" href="http://docs.hc.a10networks.com/2.2.4/ads-intro.html"&gt;Lightning&lt;/a&gt; (cloud)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Software Load Balancer:&lt;/strong&gt; using software to achieve load balancing. These solutions are affordable, and usually open-source. They can be loaded on commodity hardware (including NIC). Some (e.g. &lt;a class="rank-math-link" href="https://www.nginx.com/resources/glossary/application-delivery-controller/"&gt;Nginx&lt;/a&gt;) refers to themselves as software-based ADC. Major players are:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;HA Proxy&lt;/li&gt;&#10;&lt;li&gt;Nginx&lt;/li&gt;&#10;&lt;li&gt;Linux Virtual Server (LVS, L4 only)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The hardware ADCs are usually supported commercially and there are plenty of resources from their white papers. There is an ongoing debate about whether one is better than the other. However, there is no doubt that a software-based load balancer is more approachable as open-source tools. The line between software and hardware load balancers becomes blurred today as hardware vendors try to adapt their software appliance to commodity hardware. Check out &lt;a href="https://www.nginx.com/blog/not-all-software-load-balancers-are-created-equal/"&gt;this&lt;/a&gt; article. The rest of this post, will focus on software-based load balancer. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-software-based-load-balancer"&gt;Software-based load balancer&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We explained that ADC (application delivery controller) is an expanded set of features from load balancer, and will only cover the load balancer part of the feature set in this article.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.haproxy.org/" class="rank-math-link"&gt;HAProxy&lt;/a&gt; supports both layer 4 and layer 7 load balancing. It supports load balancing based on cookie and session, as well as health check. Since it is layer 4 load balancing, it supports any TCP protocol such as read traffic for MySQL. &amp;nbsp;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.nginx.com/" class="rank-math-link"&gt;Nginx&lt;/a&gt; is a high-performance, event-driven, cross-platform layer 7 load balancing application. It works as a reverse proxy where it receives request for the Internet and forwards it to (upstream) internal servers. It consumes less memory than many of its alternatives for layer 7 load balancing. There are many strategies for load balancing such as round robin, by weight, by hash of requesting IP, by upstream response time, or by URL hash. It supports 20-30 k concurrent connections, and support compression and health check. It is known to be very stable and common for small and medium volume. Nginx has a commercial counterpart Nginx Plus with advanced features.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Nginx and HA proxy are commonly used in front end load balancing. For backend traffic such as database (e.g. separating read write traffic), LVS can be used.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-linux-virtual-server"&gt;Linux Virtual Server&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/virtual_server_administration/ch-lvs-overview-vsa" class="rank-math-link"&gt;LVS&lt;/a&gt; (Linux Virtual Server) is part of standard Linux kernel. It performs layer 4 load balancing based on TCP or UDP and therefore consumes less memory and CPU. Compared to layer 7 load balancing, the performance is generally higher, and the configuration is less complex (with simpler routing rules). &lt;a href="http://www.linuxvirtualserver.org/" class="rank-math-link"&gt;LVS&lt;/a&gt; is usually configured in a &lt;a href="http://www.linuxvirtualserver.org/architecture.html" class="rank-math-link"&gt;common cluster architecture&lt;/a&gt; involving these components:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Load balancer: the front-end machine of the whole cluster systems, and balances requests from clients among a set of servers, so that the clients consider that all the services is from a single IP address.&lt;/li&gt;&#10;&lt;li&gt;Server cluster: set of servers running actual business workload&lt;/li&gt;&#10;&lt;li&gt;Shared storage: a shared storage space for the servers, such as NFS&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://i.imgur.com/EU0gAUv.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Load balancer is the single entry-point of server cluster systems, it can run&amp;nbsp;IPVS&amp;nbsp;that implements IP load balancing techniques inside the Linux kernel, or&amp;nbsp;KTCPVS&amp;nbsp;that implements application-level load balancing inside the Linux kernel. When IPVS is used, all the servers are required to provide the same services and contents, the load balancer forward a new client request to a server according to the specified scheduling algorithms and the load of each server. No matter which server is selected, the client should get the same result. When KTCPVS is used, servers can have different contents, the load balancer can forward a request to a different server according to the content of request. Since KTCPVS is implemented inside the Linux kernel, the overhead of relaying data is minimal, so that it can still have high throughput.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;IPVS is also called layer-4 switching, it directs TCP/UDP requests to the real servers behind load balancer. It works in three modes:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Network Address Translation (NAT)&lt;/li&gt;&#10;&lt;li&gt;Direct Routing (DR)&lt;/li&gt;&#10;&lt;li&gt;Tunnel mode (TUN)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;These are three packet-forwarding methods in IPVS. The IPVS is implemented as a module over the netfilter framework, similar to &lt;a href="https://static.digihunch.com/2018/10/redhat-firewall-configuration-firewalld-vs-iptables/" class="rank-math-link"&gt;iptables&lt;/a&gt;, which is also built on top of netfilter, based on chain and rules.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-summary"&gt;Summary &lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We had an overview of high availability, and then expanded on load balancing, an important mechanism to implement high availability. We touched on both hardware-based and software-based load balancing technologies, and dived a little more into Linux Virtual Server. It is worth-noting that LVS is also the foundation of kube-proxy, the load balancing mechanism used in Kubernetes.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/01/nginx-as-a-reverse-proxy-for-nifi/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Nginx as a reverse proxy for Nifi web UI and Kibana&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/02/everything-about-the-domain/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Introduction to Active Directory (AD)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Nginx as a reverse proxy for Nifi web UI and Kibana</title><link>https://static.digihunch.com/2020/01/nginx-as-a-reverse-proxy-for-nifi/</link><pubDate>Thu, 16 Jan 2020 22:22:51 -0400</pubDate><guid>https://static.digihunch.com/2020/01/nginx-as-a-reverse-proxy-for-nifi/</guid><description>&lt;p class="wp-block-paragraph"&gt;Nginx can act as a application neutral proxy. One example is to front Nifi. The nifi default configuration provides an HTTP access point, specified in the following entries in nifi.properties:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nifi.web.http.host=192.168.133.5&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nifi.web.http.port=8080&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Nifi can provide secure port by commenting out the lines above and provide the followings:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nifi.web.https.host=192.168.133.5&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nifi.web.https.port=8083&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;However, it does require configuring JKS keystore for Java, as well as authentication. Customers with existing AD servers are likely to require authentication via LDAP. While Nifi does support LDAP integration according to its &lt;a href="https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#ldap_login_identity_provider"&gt;administration guide&lt;/a&gt;. The configuration is quite involving. You need to configure the identity provider, as well as authorizes. I have personally spent a couple days on this without much progress. The information in the logging isn&amp;#8217;t to the point. Restarting nifi also is a long process, making it painful to troubleshoot. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I then moved to Nginx (open-source) as an alternative and it is quite enlightening. I already knew that the SSL termination in nginx is super easy to configure. This time I learned that the opensource community even has a support for LDAP integration. Here is a diagram of how it works:&lt;/p&gt;&#10;&lt;p class="has-text-align-center 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="542px" viewBox="-0.5 -0.5 542 272" style="max-width:100%;max-height:272px;"&gt;&lt;defs&gt;&lt;linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-ffffff-1-33ebff-1-s-0"&gt;&lt;stop offset="0%" style="stop-color:#FFFFFF"&gt;&lt;/stop&gt;&lt;stop offset="100%" style="stop-color:#33EBFF"&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="540" height="270" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;rect x="10" y="75" width="60" height="30" rx="4.5" ry="4.5" fill="#ffffff" stroke="#000000" 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: 58px; height: 1px; padding-top: 90px; margin-left: 12px;"&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="40" y="94" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Client&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="169.25" y="230" width="118.5" height="30" rx="4.5" ry="4.5" fill="#ffffff" stroke="#000000" 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: 116px; height: 1px; padding-top: 245px; 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;Active Directory&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="229" y="249" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Active Directory&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="430" y="10" width="85" height="70" fill="#ffffff" stroke="#000000" stroke-dasharray="3 3" 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 flex-start; justify-content: unsafe center; width: 83px; height: 1px; padding-top: 17px; margin-left: 432px;"&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;Container1&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="473" y="29" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Container1&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="445" y="40" width="55" height="30" rx="4.5" ry="4.5" fill="#ffffff" stroke="#000000" 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: 53px; height: 1px; padding-top: 55px; margin-left: 447px;"&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;Nifi&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="473" y="59" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Nifi&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="430" y="120" width="85" height="70" fill="#ffffff" stroke="#000000" stroke-dasharray="3 3" 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 flex-start; justify-content: unsafe center; width: 83px; height: 1px; padding-top: 127px; margin-left: 432px;"&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;Container2&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="473" y="139" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Container2&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="445" y="150" width="55" height="30" rx="4.5" ry="4.5" fill="#ffffff" stroke="#000000" 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: 53px; height: 1px; padding-top: 165px; margin-left: 447px;"&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;Nifi&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="473" y="169" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Nifi&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="140" y="20" width="177" height="170" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/rect&gt;&lt;rect x="140" y="20" width="177" height="170" fill="#ffffff" stroke="#000000" stroke-dasharray="3 3" 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 flex-start; justify-content: unsafe center; width: 175px; height: 1px; padding-top: 27px; margin-left: 142px;"&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; text-decoration: underline; white-space: normal; word-wrap: normal; "&gt;Container&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="229" y="39" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline"&gt;Container&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="155" y="50" width="144" height="60" rx="9" ry="9" fill="#ffffff" stroke="#000000" 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 flex-start; justify-content: unsafe center; width: 142px; height: 1px; padding-top: 57px; margin-left: 157px;"&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; text-decoration: underline; white-space: normal; word-wrap: normal; "&gt;Nginx process&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="227" y="69" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline"&gt;Nginx process&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="165" y="76" width="120" height="28" rx="4.2" ry="4.2" fill="url(#mx-gradient-ffffff-1-33ebff-1-s-0)" 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 flex-start; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 83px; margin-left: 167px;"&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; text-decoration: underline; white-space: normal; word-wrap: normal; "&gt;http_auth_request&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="225" y="95" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline"&gt;http_auth_request&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="155" y="150" width="145" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#d6b656" 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: 143px; height: 1px; padding-top: 165px; margin-left: 157px;"&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;ldap-auth daemon&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="228" y="169" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;ldap-auth daemon&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 228 104.81 L 227.57 143.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 227.51 148.88 L 224.09 141.84 L 227.57 143.63 L 231.09 141.92 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&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: 1px; height: 1px; padding-top: 125px; margin-left: 228px;"&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; background-color: #ffffff; white-space: nowrap; "&gt;http&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="228" y="129" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;http&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 285 83 L 438.73 56.1" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 443.9 55.19 L 437.61 59.85 L 438.73 56.1 L 436.4 52.95 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&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: 1px; height: 1px; padding-top: 55px; margin-left: 370px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #FFFFCC; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; "&gt;d&lt;font color="#000000"&gt;http&lt;/font&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="370" y="58" fill="#FFFFCC" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;dhttp&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 285 97 L 439.14 162.51" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 443.97 164.56 L 436.16 165.05 L 439.14 162.51 L 438.9 158.6 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&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: 1px; height: 1px; padding-top: 120px; margin-left: 370px;"&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: #FFFFCC; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; "&gt;&lt;font color="#000000"&gt;http&lt;/font&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="370" y="124" fill="#FFFFCC" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;http&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 228.37 223.63 L 227.63 186.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 228.48 228.88 L 224.84 221.95 L 228.37 223.63 L 231.84 221.81 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 227.52 181.12 L 231.16 188.05 L 227.63 186.37 L 224.16 188.19 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&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: 1px; height: 1px; padding-top: 205px; margin-left: 228px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; "&gt;LDAP&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="228" y="208" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle"&gt;LDAP&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 76.37 90 L 158.63 90" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 71.12 90 L 78.12 86.5 L 76.37 90 L 78.12 93.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 163.88 90 L 156.88 93.5 L 158.63 90 L 156.88 86.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&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: 1px; height: 1px; padding-top: 90px; margin-left: 106px;"&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; background-color: #ffffff; white-space: nowrap; "&gt;https&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="106" y="94" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;https&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This approach is outlined in a &lt;a href="https://www.nginx.com/blog/nginx-plus-authenticate-users/"&gt;blog post&lt;/a&gt; on &lt;a href="https://www.nginx.com/"&gt;Nginx &lt;/a&gt;website. The &lt;a href="https://github.com/nginxinc/nginx-ldap-auth"&gt;ldap-auth daemon&lt;/a&gt; is implemented in Python can can be wrapped up as a systemd service. Once a client sends a request in https, security layer is terminated in nginx, and an authentication request in http is sent to the ldap-auth daemon, which proxies converts the request into LDAP searches and proxies it over to customer&amp;#8217;s Active Directory server, for authentication. Once authenticated, the http request can make to one of the backend container or server which hosts Nifi. Below is an example of how this can be configure on RedHat.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Install python3 and python-ldap&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;RedHat may have both python2 and python3 pre-installed, python2 being the default. We do not want to change the default because other applications such as yum still depends on python2 as of early 2020.&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;yum -y install python3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum -y install gcc python3-devel openldap-devel&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pip3 install python-ldap&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Once python3 is installed, pip3 will be available and we use that to install python-ldap. This is a module in Python3 that will be used by the script that act as ldap daemon.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Configure ldap-auth daemon as systemd service&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the github project for &lt;a href="https://github.com/nginxinc/nginx-ldap-auth"&gt;ldap-auth&lt;/a&gt;, download nginx-ldap-auth-daemon.py to local location such as /usr/bin, then we create &lt;a href="https://github.com/nginxinc/nginx-ldap-auth/blob/master/nginx-ldap-auth-daemon.py"&gt;nginx-ldap-auth.service&lt;/a&gt; in /etc/systemd/system/ with the following content.&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-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[Unit]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Description&lt;span style="color:#f92672"&gt;=&lt;/span&gt;LDAP authentication helper &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; Nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;After&lt;span style="color:#f92672"&gt;=&lt;/span&gt;network&lt;span style="color:#f92672"&gt;.&lt;/span&gt;target network&lt;span style="color:#f92672"&gt;-&lt;/span&gt;online&lt;span style="color:#f92672"&gt;.&lt;/span&gt;target&#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;[Service]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Type&lt;span style="color:#f92672"&gt;=&lt;/span&gt;simple&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;User&lt;span style="color:#f92672"&gt;=&lt;/span&gt;root&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Group&lt;span style="color:#f92672"&gt;=&lt;/span&gt;root&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WorkingDirectory&lt;span style="color:#f92672"&gt;=/&lt;/span&gt;var&lt;span style="color:#f92672"&gt;/&lt;/span&gt;run&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ExecStart&lt;span style="color:#f92672"&gt;=/&lt;/span&gt;usr&lt;span style="color:#f92672"&gt;/&lt;/span&gt;bin&lt;span style="color:#f92672"&gt;/&lt;/span&gt;python3 &lt;span style="color:#f92672"&gt;/&lt;/span&gt;usr&lt;span style="color:#f92672"&gt;/&lt;/span&gt;bin&lt;span style="color:#f92672"&gt;/&lt;/span&gt;nginx&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ldap&lt;span style="color:#f92672"&gt;-&lt;/span&gt;auth&lt;span style="color:#f92672"&gt;-&lt;/span&gt;daemon&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;KillMode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;KillSignal&lt;span style="color:#f92672"&gt;=&lt;/span&gt;SIGINT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Restart&lt;span style="color:#f92672"&gt;=&lt;/span&gt;on&lt;span style="color:#f92672"&gt;-&lt;/span&gt;failure&#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;[Install]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WantedBy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;multi&lt;span style="color:#f92672"&gt;-&lt;/span&gt;user&lt;span style="color:#f92672"&gt;.&lt;/span&gt;target&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then, run the following command to load, start and check nginx-ldap-auth service.&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;systemctl reload-daemon&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl start nginx-ldap-auth&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl status nginx-ldap-auth&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This service will be up and listening to port 8888 for http traffic.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Configure Nginx&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt; Then configure nginx with the following entries in its default.conf file, typically located in /etc/nginx/conf.d.&amp;nbsp; &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-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;upstream nifibackend {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; # default: round robin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server container1.nifi.digihunch.com:8080;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server container2.nifi.digihunch.com:8080;&#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;proxy_cache_path cache/ keys_zone=auth_cache:10m;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# nifi proxy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen 8083ssl;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; include /etc/nginx/ssl/default.conf;&#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; location / {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; auth_request /auth-proxy;&#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; proxy_pass http://nifibackend;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Host $host:$server_port;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-ProxyScheme https;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-ProxyHost $1;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-ProxyPort 8083;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-ProxyContextPath /;&#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; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location /auth-proxy {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; internal;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://127.0.0.1:8888;&#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; proxy_pass_request_body off;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Content-Length &amp;#34;&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_cache auth_cache;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_cache_valid 200 10m;&#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; proxy_cache_key &amp;#34;$http_authorization$cookie_nginxauth&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Ldap-URL &amp;#34;ldaps://ldap.digihunch.com:636&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Ldap-BaseDN &amp;#34;OU=Corporate User Accounts,DC=digihunch,DC=org&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Ldap-BindDN &amp;#34;CN=Digi Hunch Service Account,OU=Digi,OU=ServiceAccounts,OU=Digi,OU=Digi Applications,DC=digihunch,DC=org&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Ldap-BindPass &amp;#34;myownpasswordtricks&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-CookieName &amp;#34;nginxauth&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header Cookie nginxauth=$cookie_nginxauth;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Ldap_Starttls &amp;#34;true&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header X-Ldap-Template &amp;#34;(&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;amp;&lt;/span&gt;(sAMAccountName=%(username)s)(objectClass=organizationalPerson)(memberOf=CN=GH_SYSADMIN,OU=GHCO,OU=Groups,OU=Digi,OU=Digi Applications,DC=digihunch,DC=org))&amp;#34;;&#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;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;We need the full distinguished name of bind user to get this to work. Once configured properly, and user attempts to connect through a browser, Nginx will pop up a prompt for username and password. The username will be plugged into the X-Ldap-Template for further queries. The same HTTP header also allows you to filter by membership that the user is associated with.&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/12/networking-basics-3-of-3-common-network-technologies/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous 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;a rel="next" href="https://static.digihunch.com/2020/01/several-ways-to-ensure-high-availability/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;High Availability and Load Balancer&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Personal Vim cheatsheet</title><link>https://static.digihunch.com/2019/10/personal-vim-cheatsheet/</link><pubDate>Mon, 07 Oct 2019 17:52:00 -0400</pubDate><guid>https://static.digihunch.com/2019/10/personal-vim-cheatsheet/</guid><description>&lt;p class="wp-block-paragraph"&gt;This is my personal cheatsheet as intermediate Vim user so I skipped the ones that I consider basic. All the commands listed are used in command mode for fast editing.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Command execution&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In command mode, use colon to start ex command. Here are some examples of ex commands:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;e: edit file&lt;/li&gt;&lt;li&gt;g: global command&lt;/li&gt;&lt;li&gt;q: quit&lt;/li&gt;&lt;li&gt;w: write&lt;/li&gt;&lt;li&gt;s: substitute&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The commands (g)lobal and (s)ubstitute are heavily used in string manipulation. The rest are summarized here:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;:e!&lt;/td&gt;&lt;td&gt;reload current file discarding all unsaved changes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:e newfile.txt&lt;/td&gt;&lt;td&gt;open file newfile.txt for editing &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:e .&lt;/td&gt;&lt;td&gt;load current directory&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:w!&lt;/td&gt;&lt;td&gt;force write (if permission allows)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;shift + zz&lt;/td&gt;&lt;td&gt;equivalent to :wq!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;shift + zq&lt;/td&gt;&lt;td&gt;equivalent to :q!&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Operator&lt;/h4&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;repeat last operation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;fx&lt;/td&gt;&lt;td&gt;find next character x on the same line&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Text Editing&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;y for yank(copy), i for inside, a for around, d for delete, w for word, p for paragraph or paste. Examples:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;yyp&lt;/td&gt;&lt;td&gt;copy current line and insert after&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;diw&lt;/td&gt;&lt;td&gt;delete the entire word where the cursor sits in (dw deletes from cursor to end of word; db deletes from cursor to beginning of word)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;shift + V&lt;/td&gt;&lt;td&gt;select entire line in visual mode (v selects character in visual mode) &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&amp;gt;&lt;/td&gt;&lt;td&gt;visual mode: indent twice on all selected lines&lt;br&gt;edit mode: indent once for 2 lines&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&amp;lt;&lt;/td&gt;&lt;td&gt;visual mode: outdent three times on all selected lines&lt;br&gt;edit mode: outdent once for 3 lines&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;di&amp;#8221;&lt;/td&gt;&lt;td&gt;delete everything between the double quotes surrounding the cursor (exclusive); use c instead of d to finish the same effect with insert mode&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;di&amp;gt;&lt;/td&gt;&lt;td&gt;delete everything between &amp;lt; and &amp;gt; surrounding the cursor (exclusive); use (c)hange instead of (d)elete to finish the same effect with insert mode&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;dit&lt;/td&gt;&lt;td&gt;delete everything between tags. e.g. &amp;lt;xml&amp;gt;contenttodelete&amp;lt;/xml&amp;gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;dip&lt;/td&gt;&lt;td&gt;delete the entire paragraph&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;da&amp;#8217;&lt;/td&gt;&lt;td&gt;delete everything between the single quote surrounding the cursor (inclusive); use c instead of d to finish the same effect with insert mode&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;da}&lt;/td&gt;&lt;td&gt;delete everything between { and } surrounding the cursor (inclusive); use c instead of d to finish the same effect with insert mode&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;dt.&lt;/td&gt;&lt;td&gt;delete all characters until the next .&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i&lt;/td&gt;&lt;td&gt;insert at cursor location&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;shift + I&lt;/td&gt;&lt;td&gt;move cursor to first non-blank character of line and start in insert mode&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;insert at the location next to cursor&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;shift + A&lt;/td&gt;&lt;td&gt;move cursor to last non-blank character of line and start in insert mode&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;move to beginning of line. ^ moves to first non-blank character in the line. $ moves to the end of line&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note: wherever d is used in this table, c can be used instead for the same effect but switch to editing mode at the end.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading"&gt;String Manipulation&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The general patterns are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;[range]g/pattern/cmd&lt;/li&gt;&lt;li&gt;[range]s/match/replacement/option&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If range is not specified, it applies to current line only! To specify the whole file, use % range. You may also specify line range such as &amp;#8220;10,20&amp;#8221;. Here are some examples: &lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;:%s/bacon/lettuce&lt;/td&gt;&lt;td&gt;For every line of the file, replace the first occurrence of bacon in each line to lettuce&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:%s/bacon/lettuce/g&lt;/td&gt;&lt;td&gt;For every line of the file, replace all occurrences of bacon to lettuce&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:s/bacon/lettuce&lt;/td&gt;&lt;td&gt;For current line, replace the first occurrence of bacon to lettuce&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:s/bacon/lettuce/gi&lt;/td&gt;&lt;td&gt;For current line, replace all occurrences of bacon to lettuce, case insensitive&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:g/bacon/d&lt;/td&gt;&lt;td&gt;delete all lines that contain pattern &amp;#8216;bacon&amp;#8217;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:g!/lettuce/d&lt;/td&gt;&lt;td&gt;delete all lines that do not contain pattern &amp;#8216;lettice&amp;#8217;; or use :v/lettuce/d instead&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;:g/^\s*$/d&lt;/td&gt;&lt;td&gt;delete all blank lines. \s* represents zero or more white spaces&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Bookmarking&lt;/h4&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;ma&lt;/td&gt;&lt;td&gt;mark cursor line as bookmark a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;`a&lt;/td&gt;&lt;td&gt;jump to cursor position at line a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;#8216;a&lt;/td&gt;&lt;td&gt;jump to beginning of line a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;`.&lt;/td&gt;&lt;td&gt;jump to last line where change occurred&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;#8220;&lt;/td&gt;&lt;td&gt;jump back &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Insert Mode&lt;/h4&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Ctrl + N&lt;/td&gt;&lt;td&gt;Auto complete&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;h4 class="wp-block-heading"&gt;Edit and run&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;While tmux and screen can help split screen in Bash, we sometimes need to split a bash screen to run a quick command when we&amp;#8217;re already in vim. This can be done with some simple commands.&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-stripes"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;:term&lt;/td&gt;&lt;td&gt;Open up a terminal above vim. You can also spell :ter or :terminal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Ctrl+W; Ctrl+W&lt;/td&gt;&lt;td&gt;Press Ctrl+W twice can help you toggle between the terminal and vim buffer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Ctrl+D&lt;/td&gt;&lt;td&gt;Close the terminal&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This can be very helpful when you are debugging code and need it run repeatedly. You don&amp;#8217;t need to exit vim just to run a command and come back. Note that while you&amp;#8217;re in terminal, you can&amp;#8217;t use Ctrl+W as a shortcut key to backspace a word. Use Alt + Delete instead.&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/09/cryptographic-concepts-for-busy-it-professionals-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Cryptography basics 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/10/storage-nitty-gritty-4-of-5-backup-and-archive-solutions/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Storage Nitty-Gritty 4 of 5 – Backup and Archive Solutions&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>AWS Certified DevOps Engineer Exam Tips</title><link>https://static.digihunch.com/2019/08/aws-certified-devops-engineer-exam-tips/</link><pubDate>Sat, 17 Aug 2019 23:07:59 -0400</pubDate><guid>https://static.digihunch.com/2019/08/aws-certified-devops-engineer-exam-tips/</guid><description>&lt;p class="wp-block-paragraph"&gt;The last 30 days have been exhausting for me. I studied hard on the new AWS Certified DevOps Engineer exam and thank goodness I passed (750 out of 1000 is required). This was the hardest professional certification I ever worked on. The exam was re-launched recently in March 2019 so there is still a shortage of information around the community. I was hoping to share my experience to help demystify this new exam. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I had a somewhat solid background to begin with, having taken the AWS Certified Solution Architect Professional exam (before the 2019 update), and worked quite a bit on CloudFormation, automation and Git. However, I still did not anticipate the exam to be this difficult until I was halfway through and already had the exam and materials paid for.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img loading="lazy" decoding="async" width="1469" height="518" src="https://static.digihunch.com/wp-content/uploads/2019/08/image.png" alt="" class="wp-image-127"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Without clear guideline on study material other than the white papers, I first skimmed through the ACloudGuru course, which helped me form a high level sense of exam coverage. Nonetheless it does not cover any topic in-depth and therefore by no means makes an essential part of my study. I checked out &lt;strong&gt;LinuxAcademy course&lt;/strong&gt; and they are much more in-depth for the major topics indeed. I like the course material in Lucid chart. However, the LinuxAcademy course along does not cover everything you need to know.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;What I found extremely helpful is the free training videos from the &lt;a href="https://www.aws.training"&gt;official training website&lt;/a&gt;. I strongly recommend the 7-hour course &lt;strong&gt;Exam Readiness: AWS Certified DevOps Engineer – Professional&lt;/strong&gt;. The instructor did a great job outlining the services and knowledge areas in the assessment . The course also comes with quality sample questions with answers and explanations on what the thinkings are behind the correct answers or why some choices are obviously wrong. I went through these questions twice and feel much better at not only understanding the question, but also understanding the intent of the question.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img loading="lazy" decoding="async" width="833" height="156" src="https://static.digihunch.com/wp-content/uploads/2019/08/image-1.png" alt="" class="wp-image-129"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apart from the Exam Readiness course, other &lt;strong&gt;free introductory courses&lt;/strong&gt; from the official training website are helpful as well especially for those services that you only need to know the basics. Most of those courses are 5 ~ 10 minutes long, with brief but sufficient introduction and a demo session. The other extremely helpful resource is the &lt;strong&gt;official practice questions&lt;/strong&gt;. The practice exam is harder than the actual exam but they closely resemble the actual question style in the exam. Unfortunately, no answer is provided but they made me spend time finding answers across the documentations and blogs. It is worth-noting that the AWS blogs provides plenty of use cases that are covered in the questions.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When it comes to the real exam, it covers a lot more topics than its predecessor. Many questions are long and confusing. And I wish I could run a diff command to highlight the differences between choices. During exam preparation you really need to train yourself on reading efficiently. I found myself sometimes eyeball through all four choices at the same time, which get my mind scattered.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;During my study, I divide all services into three categories based on the level of familiarity, and here is my list:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Category 1. Know these services very well, in and out:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AWS ElasticBeanstalk, OpsWorks Stacks, OpsWorks Chef Automate, CloudFormation, CloudWatch, CodeBuild, CodeCommit, CodeDeploy, CodePipeline, CodeStar, Lambda, API Gateway, Config, Trusted Advisor, CloudTrail, Systems Manager, Autoscaling Group in EC2, DynamoDB&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Category 2. Know these services well, but not necessarily down to every single detail:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Amazon Kinesis Firehose, Kinesis Analytics, Kinesis Streams, Step Functions, Elastic Load Balancer, Secrets Manager, Serverless Application Model (SAM), Route53, RDS, Certificate Manager, ElasticSearch, ECS, ECR&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Category 3. Know about these services at a high level, but do not skip any:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AWS Organization, X-Ray, GuardDuty, Macie, Inspector, Service Catalog, KMS, Batch, Athena, Single-Sign-On, Data LifeCycle Manager, CloudSearch, Health Dashboard, Glue, QuickSight, LightSail&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Although I did not mention much about the white papers, I want to highlight their importance again. I would not attempt the exam without reading and understanding the required white papers. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If you aspire to take the AWS certified DevOps Engineer exam I hope this helps you a little bit. Good luck.&lt;/p&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/2019/07/storage-nitty-gritty-3-of-5-nas-and-object-storage/"&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 3 of 5 – NAS and Object Storage&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/09/cryptographic-concepts-for-busy-it-professionals-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Cryptography basics 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Set up automation with Ansible</title><link>https://static.digihunch.com/2019/05/automation-with-ansible-a-primer/</link><pubDate>Wed, 22 May 2019 22:11:00 -0400</pubDate><guid>https://static.digihunch.com/2019/05/automation-with-ansible-a-primer/</guid><description>&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.ansible.com/overview/how-ansible-works"&gt;Ansible &lt;/a&gt;is very flexible automation tools with many benefits. The free version is command-line based and here is an example to set it up.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Environment setup&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&lt;li&gt;Ansible 2.8 is required or some command may not work.&lt;/li&gt;&lt;li&gt;Ansible files (including playbooks, tasks and inventory files) are all located in /home/glowing/ansible&lt;/li&gt;&lt;li&gt;Default inventory file needs to be referenced in Ansible configuration /etc/ansible/ansible.cfg. This ensures ansible or ansible-playbook command can pick up hosts or host patterns without requiring inventory file through -i on every execution. Here is what the inventory config looks like in ansible.cfg:&lt;/li&gt;&lt;/ol&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[defaults]&#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;# some basic default values...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;inventory = /etc/ansible/hosts,/home/glowing/ansible/inventories/glowing_inventory.yml&#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;host_key_checking = False&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol class="wp-block-list" start="4"&gt;&lt;li&gt;As best practice, servers involved should be able to ssh to each other on RSA key authentication. This can be achieved by adding a separate authorized keys file and reference it from /etc/ssh/sshd_config, at the line starting with AuthorizedKeysFile, and separated with the file name of existing authorized keys with a space. In this way, you may keep public keys of human user in one authorized key file and the public keys of machines in the other.&lt;/li&gt;&lt;li&gt;Build inventory file in ~/ansible/inventories/glowing_inventory.yml. The inventory file can declare some variables to use across hosts. If password is involved (e.g. synchronize module still requires password), it can be stored here with base64 encoded. Here is an example of glowing_inventory.yml&lt;/li&gt;&lt;/ol&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-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&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;all:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ansible_user: glowing&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gh_sudo_pass: qGS0bWVuu3Jr&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gh_dir: &lt;span style="color:#f92672"&gt;/&lt;/span&gt;opt&lt;span style="color:#f92672"&gt;/&lt;/span&gt;glowing&lt;span style="color:#f92672"&gt;/&lt;/span&gt;etc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tmp_dir: &lt;span style="color:#f92672"&gt;/&lt;/span&gt;tmp&#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; children:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dc1_front_end:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe01:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe03:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe05:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe07:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe09:&#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; dc2_front_end:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe02:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe04:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe06:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe08:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghfe10:&#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; dc1_back_end:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghbe01:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghbe03:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghbe05:&#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; dc2_back_end:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghbe02:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghbe04:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghbe06:&#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; dc1_database:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghdb01:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghdb03:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghdb05:&#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; dc2_database:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghdb02:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghdb04:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; e9a&lt;span style="color:#f92672"&gt;-&lt;/span&gt;ghdb06:&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;That is the basic steps to set up Ansible. Now we can run adhoc commands. The command below allows me to copy a file from executing server to all destination servers that match a pattern:&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;&lt;span style="color:#75715e"&gt;# ansible &amp;#39;dc*_back_end:!&amp;#39;`hostname -s` -e &amp;#34;file_name={{gh_dir}}/test.zip&amp;#34; -m copy -a &amp;#34;src={{file_name}} dest={{file_name}}&amp;#34;&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;In this command:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;variable {{gh_dir}} is declared in the inventory file. It must be referenced by placing variable name between double curly bracket;&lt;/li&gt;&lt;li&gt;An extra variable {{file_name}} is declared at run time because this is the dynamic part of the command;&lt;/li&gt;&lt;li&gt;This adhoc ansible command uses copy module. With copy module, the src anddest files are in the same absolute path here so we use this variable to save some typing;&lt;/li&gt;&lt;li&gt;reference to the host support wildcard such as dc*_back_end;&lt;/li&gt;&lt;li&gt;&lt;code&gt;hostname -s&lt;/code&gt; returns the host name of the server where the adhoc command is run&lt;/li&gt;&lt;li&gt;:! excluds the running host from being matched as destination server. this is in case that running machine is already in the dc*_back_end group, where copy source and destination are identical&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here is another example for deleting a file from destination servers:&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;&lt;span style="color:#75715e"&gt;# ansible dc2_database -e &amp;#34;fn=/tmp/file_to_delete&amp;#34; -m file -a &amp;#34;path={{fn}} state=absent&amp;#34;&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;If we can run adhoc command, then we can start writing some playbook and roles. Below is a simple playbook test-conn.yml to ping each server:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: measure mint retrieval time from {{ ansible_limit }}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts: &amp;#39;{{ ansible_limit }}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; serial: 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; order: sorted&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gather_facts: no&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ignore_errors: yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tasks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: measure time&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; command: curl -s -XGET http://{{ inventory_hostname }}:8080/index.html -o /dev/null&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; delegate_to: localhost&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; register: curlout&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; no_log: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: display result&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; debug:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; msg: &amp;#34;Time to load webpage from {{ inventory_hostname }} is {{ curlout.delta }}.&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then you can run that playbook 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-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# ansible-playbook -l dc2_front_end test-conn.yml&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Ansible automation is essentially editing yaml files for playbooks. Writing playbook involves a lot of module interaction and one needs to follow best practices. Understanding&lt;a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html"&gt; Ansible roles&lt;/a&gt; can help reuse some code.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition here are some common playbook keywords you should be familiar with:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;serial&lt;/li&gt;&lt;li&gt;order&lt;/li&gt;&lt;li&gt;gather_facts&lt;/li&gt;&lt;li&gt;ignore_errors&lt;/li&gt;&lt;li&gt;when&lt;/li&gt;&lt;li&gt;run_once&lt;/li&gt;&lt;li&gt;local_action&lt;/li&gt;&lt;li&gt;register&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here are common modules to know&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;set_fact&lt;/li&gt;&lt;li&gt;state&lt;/li&gt;&lt;li&gt;touch&lt;/li&gt;&lt;li&gt;fail&lt;/li&gt;&lt;li&gt;synchoronize&lt;/li&gt;&lt;li&gt;lineinfile&lt;/li&gt;&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/2019/05/storage-nitty-gritty-2-5/"&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 2 of 5 – SAN&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/06/git-explained-1-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Git Explained 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Package Repository Management for Linux</title><link>https://static.digihunch.com/2019/02/package-repository-management-in-linux/</link><pubDate>Sat, 09 Feb 2019 22:14:56 -0400</pubDate><guid>https://static.digihunch.com/2019/02/package-repository-management-in-linux/</guid><description>&lt;p class="wp-block-paragraph"&gt;RPM is the package manager tool in Linux. YUM is a repository management tool to fetch appropriate package for the particular version of Linux. YUM performs automatic dependency resolution when updating, installing or removing packages, and thus is able to automatically determine, fetch and install all available dependent packages. This posting is about common commands used for package management. Then we walk through the step to set up a local yum repository. Lastly, we summarize the best practice for patch management.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Tools&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition to the basic yum install, update and remove commands, here are some more tools for repository management:&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;&lt;span style="color:#75715e"&gt;## check for installed packages with updates available&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum check-update&#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;&lt;span style="color:#75715e"&gt;## search for packages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum search package.name&#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;&lt;span style="color:#75715e"&gt;## check for dependency&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum deplist package.name&#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;&lt;span style="color:#75715e"&gt;## list installed or available packages:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum list installed package.name&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum list available package.name&#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;&lt;span style="color:#75715e"&gt;## list all available packages of a repo:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum --disablerepo&lt;span style="color:#f92672"&gt;=&lt;/span&gt;* --enablerepo&lt;span style="color:#f92672"&gt;=&lt;/span&gt;repo.name list available&#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;&lt;span style="color:#75715e"&gt;## display package info&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum info package.name&#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;&lt;span style="color:#75715e"&gt;## list all repositories&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum repolist&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum repoinfo&#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;&lt;span style="color:#75715e"&gt;## list all transactions&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum history list all&#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;&lt;span style="color:#75715e"&gt;## display history of a package or transaction id&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum history package-list package.name&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum history info package.name&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum history info transaction.id&#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;&lt;span style="color:#75715e"&gt;## undo or redo a transaction&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum history undo transaction.id&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum history redo transaction.id&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;RHEL provides a more complete &lt;a href="https://access.redhat.com/sites/default/files/attachments/rh_yum_cheatsheet_1214_jcs_print-1.pdf"&gt;cheatsheet&lt;/a&gt; for yum commands.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition to single package, YUM also manages &lt;a href="https://access.redhat.com/solutions/15815"&gt;package groups&lt;/a&gt;, and works with &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-yum_plugins"&gt;plugins&lt;/a&gt;. For example, you may enable security related packages only by using the &lt;a href="https://access.redhat.com/solutions/10021"&gt;yum-plugin-security&lt;/a&gt;. For security, YUM repositories can enable GPG check (based on public key cryptography).&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Local Repo configuration&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now we configure a YUM repository server and reference that from a client to update packages. To begin with, we collect all RPM packages in /home/dhunch/upgrade/downloads/, then we install createrepo package and use it to create metadata:&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;yum install createrepo yum-utils&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;createrepo /home/dhunch/upgrade/downloads/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Examine the directory and you will find a new repodata directory created. Now we can configure nginx with the following configuration:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen 8088;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name rpmsource.digihunch.com;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; root /home/dhunch/upgrade/downloads/;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location / {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; autoindex on; #enable listing of directory index&#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;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Restart nginx and browse to server name at port 8088, you should see the directory in html. If you&amp;#8217;re getting 403 error, most likely nginx has issues accessing the directory. Nginx process should be able to traverse each level of directory to serve the files. The parent directories should have executable permission for others. For example:&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;chmod o+x /home/dhunch/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Here is a reference to &lt;a href="https://www.digitalocean.com/community/questions/proper-permissions-for-web-server-s-directory"&gt;nginx permission&lt;/a&gt; requirement. Now we can continue to configure the client.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the client, we need to add a file in /etc/repos.d/yum&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[digirepo]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;name=Local YUM Repository &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;baseurl=http://rpmsource.digihunch.com:8088/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;enabled=1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gpgcheck=0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Last we can check the available packages from the client:&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;yum --disablerepo&lt;span style="color:#f92672"&gt;=&lt;/span&gt;* --enablerepo&lt;span style="color:#f92672"&gt;=&lt;/span&gt;digirepo list available&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note that in order to keep the local repo up-to-date, there is additional maintenance work on the server. You may need to sync from official source, such as:&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;reposync -g -l -d -m --repoid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;base-source --newest-only --download-metadata --download_path&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/home/dhunch/upgrade/downloads/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;You may also need to set up a daily job with &lt;a href="https://www.redhat.com/sysadmin/using-yum-cron"&gt;yum-cron&lt;/a&gt; service so this is automated.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Sometimes the server is locked down and you need HTTP proxy to allow YUM to access repo. You may configure proxy in /etc/yum.conf in the proxy, proxy_username, and proxy_password entries. Also, you may export environment variable http_proxy. &lt;a href="https://www.rosehosting.com/blog/how-to-enable-proxy-settings-for-yum-command-on-centos-7/" class="rank-math-link"&gt;Here&lt;/a&gt; are more information.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Sometimes yum cache may introduce issues. To clean cache before installing, run:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum clean all &amp;amp;amp;&amp;amp;amp; yum -y install python3&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 class="wp-block-heading"&gt;Python packages&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Python3 is not installed by default on CentOS 7. So it needs to be installed with YUM. Do not replace the existing python2 with python3 by changing where symbolic link /bin/python points to, because YUM is dependent on python2.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For python3 use pip3 as package management. If the server does not have a public route, then you need to install pip3 package offline. For example, on a server with Internet, run&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;pip3 download -d ~/Downloads javaobj-py3&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then SCP the file to the offline server (e.g. to /home/dhunch/javaobj/), from which you can run:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pip3 install --no-index --find-links=/home/dhunch/javaobj/ javaobj-py3 --user&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This will install the pip3 package offline. Note it is recommended to not run pip3 installer as root user. The switch &amp;#8211;user allows you to run as non-root user.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Best Practices&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To configure a patch management environment, we assume that the servers do not have access to the Internet, not even through proxy. This should be part of the security guideline anyways. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This requires a local repository server to be setup. Administrators may use createrepo tool as outline above to create such repo, use reposync to synchronize local source from official source, or yum-cron to automate this for daily task.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the clients, administrators should manage the repo file in /etc/yum.repo.d, to ensure they are pointing to the correct source, using gpg check, etc. A local script to enable and disable different repos are also helpful. Otherwise, the enabelrepo and disablerepo switch can be used per command.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It is important to catalogue the state of operating system, before and after each patching activity, for verification and auditing purposes. This usually requires scripting work using yum history or package-cleanup tools.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The actual patch work can be done either manually or automatically (e.g. with Ansible&amp;#8217;s yum module). RPM is also a good tool for troubleshooting. If the scope of patching is only for security, use the yum-plugin-security to limit the packages to only security related ones.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Roll-back should be prepared in case of inadvertent outcome. Roll-back scripting relies heavily on yum history commands. If the OS needs to boot with a previous kernel, use the grubby tool.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Happy Patching!&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/01/interesting-terms-about-unsuccessful-software-project-management/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Interesting terms and principles&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/03/storage-nitty-gritty-1-5/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Storage Nitty-Gritty 1 of 5 – Disk and RAID&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Redhat Firewall configuration: from iptables to firewalld</title><link>https://static.digihunch.com/2018/10/redhat-firewall-configuration-firewalld-vs-iptables/</link><pubDate>Fri, 12 Oct 2018 17:56:00 -0400</pubDate><guid>https://static.digihunch.com/2018/10/redhat-firewall-configuration-firewalld-vs-iptables/</guid><description>&lt;h3 class="wp-block-heading"&gt;Tools to manage firewall&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Packet filter rules in Linux Kernel is managed by an user-space application named iptables in CentOS and RedHat. Since CentOS 7, &lt;a href="https://en.wikipedia.org/wiki/Firewalld"&gt;firewalld&lt;/a&gt; is introduced as an alternative to iptables. Firewalld can be installed and executed as a systemd service, and it is supposed to replace iptables. This &lt;a href="https://www.tecmint.com/firewalld-vs-iptables-and-control-network-traffic-in-firewall/"&gt;article&lt;/a&gt; describes how to configure both. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are several advantages in firewalld. One is is the support of &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-using_zones_to_manage_incoming_traffic_depending_on_source"&gt;zones&lt;/a&gt;. &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-using-firewalld-on-centos-7"&gt;Here&lt;/a&gt; are some useful information. Also, iptables involves three different services for IPv4(iptables), IPv6(ip6tables), and software bridging (ebtables), whereas firewalld only involves a single service to manage all three. Firewalld allows user to add or remove rules/ports from running firewall, without restarting firewall. Unless you have specific reason to use iptables, always use firewalld service to manage firewall. Here is an instruction to firewalld service. In this posting however, we will be focusing on iptables to understand firewall managment. We also go through an example of opening a TCP port. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;How does iptables work&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When working with iptables, it is important to understand that its related concepts (&lt;strong&gt;tables-&amp;gt;chains-&amp;gt;rules-&amp;gt;criteria and targets&lt;/strong&gt;) and how the &lt;strong&gt;order of rules&lt;/strong&gt; plays a factor. There are five independent &lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;tables&lt;/span&gt;&lt;/strong&gt;, each contains a number of &lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;chains&lt;/span&gt;&lt;/strong&gt;, either &lt;em&gt;built-in&lt;/em&gt; or &lt;em&gt;user-defined&lt;/em&gt;. Administrators mostly deals with &lt;em&gt;&lt;span style="text-decoration: underline;"&gt;built-in chains&lt;/span&gt;&lt;/em&gt; in &lt;em&gt;&lt;span style="text-decoration: underline;"&gt;filter&lt;/span&gt;&lt;/em&gt; and &lt;em&gt;&lt;span style="text-decoration: underline;"&gt;nat&lt;/span&gt;&lt;/em&gt; tables. The five tables are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;&lt;strong&gt;filter&lt;/strong&gt;: If -t isn&amp;#8217;t specified, this is the default table. It contains built-in chains:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;INPUT&lt;/strong&gt;: for packet destined to local sockets&lt;/li&gt;&lt;li&gt;&lt;strong&gt;FORWARD&lt;/strong&gt;: for packets being routed through the box&lt;/li&gt;&lt;li&gt;&lt;strong&gt;OUTPUT&lt;/strong&gt;: for locally-generated packets&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;nat&lt;/strong&gt;: this table is consulted when a packet that creates a new connection is encountered. It has three built-in chains:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;PREROUTING&lt;/strong&gt;: for altering packets as soon as they come in&lt;/li&gt;&lt;li&gt;&lt;strong&gt;OUTPUT&lt;/strong&gt;: for altering locally generated packets before routing&lt;/li&gt;&lt;li&gt;&lt;strong&gt;POSTROUTING&lt;/strong&gt;: for altering packets as they are about to go out&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;mangle&lt;/strong&gt;: this table is used for specialized packet alternation, with five built-in chains (since kernel 2.4.18): PREROUTING and OUTPUT, INPUT, FORWARD, and POSTROUTING&lt;/li&gt;&lt;li&gt;&lt;strong&gt;raw&lt;/strong&gt;: this table is mainly for configuring exceptions from connection tracking with two built-in chains: PREROUTING and OUTPUT&lt;/li&gt;&lt;li&gt;&lt;strong&gt;security&lt;/strong&gt;: for Mandatory Access Control (MAC) networking rules, with three built-in chains: INPUT, OUTPUT, and FORWARD.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Under the table (e.g. filter, nat), each chain (e.g. INPUT, OUTPUT, etc) consists of list of &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;firewall rules&lt;/strong&gt;&lt;/span&gt;. Each rule is made up of two parts defined for the packets:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;&lt;strong&gt;Criteria&lt;/strong&gt;: if the packet does not match the criteria, the next rule in the chain is examined; if it does match, then the next rule is specified by the value of the target.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Target&lt;/strong&gt;: what to do if criteria is met. The target can be:&lt;ul&gt;&lt;li&gt;user-defined chain, &lt;/li&gt;&lt;li&gt;one of the target described in iptables-extensions, or &lt;/li&gt;&lt;li&gt;in most cases, one of the special values ACCEPT, DROP or RETURN&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ACCEPT&lt;/strong&gt; &amp;#8211; let the packet through&lt;/li&gt;&lt;li&gt;&lt;strong&gt;DROP&lt;/strong&gt; &amp;#8211; drop the packet on the floor&lt;/li&gt;&lt;li&gt;&lt;strong&gt;RETURN&lt;/strong&gt; &amp;#8211; stop traversing this chain, and resume at &lt;span style="text-decoration: underline;"&gt;next rule in the previous (calling) chain&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The rules, defined in each chain under their tables, can be found in file /etc/sysconfig/iptables. You can find tables (prefix with asterisk *), chains (prefix with colon :), rules under their chains and a statement COMMIT after each table. The iptables process flow illustrates how a packet interact with all these rules under different chains and tables defined in this file: &lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://miro.medium.com/max/1000/1*OIoNQkH4RTSm-eY2lUMBcQ.jpeg" alt="IPTables and Docker. In this post I will be talking about… | by Edouard Buschini | Medium"/&gt;&lt;figcaption&gt;iptables Process Flow&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Although this big picture looks formidable, an administrator commonly only deals with the green and purple blocks (filter and nat), with the big picture in mind. Here is an example of /etc/sysconfig/iptables file from a newly installed system:&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;&lt;span style="color:#75715e"&gt;# Generated by iptables-save v1.4.21 on Fri Sep 11 23:15:32 2017&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;*filter&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:INPUT ACCEPT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0:0&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;:FORWARD ACCEPT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;0:0&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;:OUTPUT ACCEPT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;132:17200&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;-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p icmp -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -i lo -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p tcp -m state --state NEW -m tcp --dport &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -j REJECT --reject-with icmp-host-prohibited&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A FORWARD -j REJECT --reject-with icmp-host-prohibited&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;COMMIT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Completed on Fri Sep 11 23:15:32 2017&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;The rule simply allows SSH traffic. This file will be loaded up on every reboot (specifically, restart of iptables service). So if you have made some changes to rules and you want the change picked up on reboot. The rules should be saved to this file:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo iptables-save &amp;gt; /etc/sysconfig/iptables&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Other than saving rule for reboot, if you simply want to edit the rules (e.g. order of rules is incorrect), you can save the rules to file, modify the file and restore the rule from file:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo iptables-save &amp;gt; ~/iptables.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo vi ~/iptables.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo iptables-restore &amp;amp;lt; ~/iptables.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture"&gt;Here&lt;/a&gt; is some further reading about iptables architecture.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Anatomy of a rule&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The man page for iptables species the following synopsis:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;iptables [-t table] {-A|-C|-D} chain rule-specification&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rule-specification = [matches...] [target]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;match = -m matchname [per-match-options]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target = -j targetname [per-target-options]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;So when you append (-A), delete (-D), insert (-I) or replace (-R) a rule, you need to specify rule specification. The man page further explains that the following parameters make up a rule specification:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;&lt;strong&gt;protocol (-p)&lt;/strong&gt;: the protocol of the rule of the packet to check. value can be tcp, udp, icmp, all or any name defined in /etc/protocols.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;match (-m)&lt;/strong&gt;: specifies the name of a match to use and is followed by match options. The match refers to an extension module that tests for a specific property. Those extension modules are documented in the man page of &lt;a href="https://ipset.netfilter.org/iptables-extensions.man.html"&gt;iptables-extensions&lt;/a&gt;. You may specify -m multiple times for different match names, which together make up the condition under which a target is invoked. Matches are evaluated first to last as specified. We often use extensions &lt;em&gt;tcp&lt;/em&gt; and &lt;em&gt;state&lt;/em&gt;. According to iptables-extensions man page, we can specify &amp;#8211;dport followed by port number for the &lt;em&gt;tcp&lt;/em&gt; extension, and &amp;#8211;state followed by value such as NEW or ESTABLISHED for the &lt;em&gt;state&lt;/em&gt; extension.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;jump (-j)&lt;/strong&gt;: specifies the target of the rule, such as ACCEPT, REJECT or DROP.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;source and destination (-s and -d)&lt;/strong&gt;: source and destination IP address or masks. Hostname will work but not recommended since resolution is needed.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;inbound and outbound interface (-i and -o)&lt;/strong&gt;: name of interface via which the packet was received and is going to be sent.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;goto (-g)&lt;/strong&gt;: processing should continue in a user specified chain&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Other&lt;/strong&gt; parameters: -4/&amp;#8211;ipv4, -6/&amp;#8211;ipv6, -c/&amp;#8211;set-counters, -f/&amp;#8211;fragment&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When we run iptables command to view rules, we need to specify the table (e.g. filter, nat, etc) followed by -S or &amp;#8211;list-rules:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ iptables -t nat -S&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If you do not specify -t switch, the default (-t filter) is applied. Be aware that in this case, you&amp;#8217;re only seeing rules under filter table, and not all rules under tall tables!&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the result, for example one line from command &amp;#8220;iptables -S&amp;#8221; may say:&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;-A INPUT -p tcp -m state --state NEW -m tcp --dport &lt;span style="color:#ae81ff"&gt;9200&lt;/span&gt; -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The interpretation: appending a rule to INPUT chain of filter table (implicitly specified). The protocol is tcp. The first match extension is state, and the state value shall be NEW. The second match extension is tcp, and the dport value shall be 9200. If the packet is a match, then the target (action) is ACCEPT.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Managing rules&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As mentioned earlier, rules can be dumped to any file or /etc/sysconfig/iptables, in which the rules are assessed in order. Below is a real life iptables file with a nat table as well. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Generated by iptables-save v1.4.21 on Wed Jan 15 13:58:39 2017&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;*filter&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:INPUT DROP [0:0]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:FORWARD DROP [0:0]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:OUTPUT ACCEPT [4:208]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p icmp -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -i lo -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -s 10.100.160.56/32 -p tcp -m state --state NEW -m tcp --dport 7000:7001 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -s 10.100.160.56/32 -p tcp -m state --state NEW -m tcp --dport 7199 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -s 10.100.160.56/32 -p tcp -m state --state NEW -m tcp --dport 9042 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -s 10.100.160.56/32 -p tcp -m state --state NEW -m tcp --dport 9160 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p tcp -m state --state NEW -m tcp --dport 8080 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p udp -m state --state NEW -m udp --dport 161 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p udp -m state --state NEW -m udp --dport 162 -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -j REJECT --reject-with icmp-host-prohibited&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A FORWARD -j REJECT --reject-with icmp-host-prohibited&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;COMMIT&#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;*nat&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:PREROUTING ACCEPT [1:328]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:INPUT ACCEPT [0:0]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:OUTPUT ACCEPT [0:0]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:POSTROUTING ACCEPT [0:0]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A PREROUTING -p tcp -m tcp --dport 2392 -j REDIRECT --to-ports 2398&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A PREROUTING -p tcp -m tcp --dport 2393 -j REDIRECT --to-ports 2398&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A OUTPUT -o lo -p tcp -m tcp --dport 2392 -j REDIRECT --to-ports 2398&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A OUTPUT -o lo -p tcp -m tcp --dport 2393 -j REDIRECT --to-ports 2398&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;COMMIT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Completed on Wed Jan 15 13:58:39 2017&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In this example, the nat table defines traffic forwarding: traffic arriving at TCP port 2392 and 2393 are forwarded to port 2398; outgoing traffic to port 2392 and 2393 are also redirected to port 2398. These rules do not overlap each other so the rules probably don&amp;#8217;t matter.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the other hand, the tcp filter table lists the rules to open certain TCP and UDP ports. Its block starts with a couple accepting rules and ends with a couple reject rules (regardless of protocols or ports). This is a good way to close a chain of rules with security. However, if you need to add additional rules to open more TCP ports, the new rule should not be appended after the reject rules at the bottom since the order matter here!&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Correct way to open a TCP port&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It&amp;#8217;s a common task for developers to open a TCP port simply for the purpose of bring up a web service and make it accessible to client. If we simply add a new rule to existing list, for example:&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;&lt;span style="color:#75715e"&gt;# iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 9870 -j ACCEPT&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;# iptables -S&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-P INPUT ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-P FORWARD ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-P OUTPUT ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p icmp -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -i lo -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p tcp -m state --state NEW -m tcp --dport &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -j REJECT --reject-with icmp-host-prohibited&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p tcp -m state --state NEW -m tcp --dport &lt;span style="color:#ae81ff"&gt;9870&lt;/span&gt; -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A FORWARD -j REJECT --reject-with icmp-host-prohibited&#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;&lt;span style="color:#75715e"&gt;# systemctl reload iptables&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;You will notice that the rule is appended to the end of INPUT block, below the INPUT REJECT rule, which will never take effect.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To address this, you can use iptables-save and iptables-restore to export, edit to correct order and reload the rule, as illustrated above, instead of using iptables command to modify the rule directly. &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;&lt;span style="color:#75715e"&gt;# iptables-save &amp;gt; /tmp/rule.list&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;# vi /tmp/rule.list&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;# iptables-restore &amp;lt; /tmp/rule.list&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;# iptables -S&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-P INPUT ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-P FORWARD ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-P OUTPUT ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p icmp -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -i lo -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p tcp -m state --state NEW -m tcp --dport &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -p tcp -m state --state NEW -m tcp --dport &lt;span style="color:#ae81ff"&gt;9870&lt;/span&gt; -j ACCEPT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A INPUT -j REJECT --reject-with icmp-host-prohibited&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-A FORWARD -j REJECT --reject-with icmp-host-prohibited&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Alternatively, you could use some advanced iptables command switches to add the new rule to certain line number with &amp;#8211;line-number switch. &lt;a href="https://www.osetc.com/en/linux-iptables-insert-rule-at-a-specific-position-prepend-firewall-rule.html"&gt;Here&lt;/a&gt; is more information.&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/2018/09/log-shipping-through-elk/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Log shipping through ELK&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2018/11/the-java-confusions/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Java version confusions&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Linux Admin Basics 3 of 3 – text processing, regex, sed &amp; awk</title><link>https://static.digihunch.com/2018/06/text-processing-with-linux-bash/</link><pubDate>Wed, 06 Jun 2018 19:56:00 -0400</pubDate><guid>https://static.digihunch.com/2018/06/text-processing-with-linux-bash/</guid><description>&lt;p class="wp-block-paragraph"&gt;Most of the text processing can be processed by awk and sed. Sed is non-interactive stream editor that allows you to specify all editing instructions in one place and execute them on a single pass through the file. Awk is a pattern-matching programming language.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Using sed and awk requires some understanding of regular expressions. Here&amp;#8217;s the basics of regular expression signs:&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;sign&lt;/td&gt;&lt;td&gt;operation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;^&lt;/td&gt;&lt;td&gt;matches beginning of line&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;$&lt;/td&gt;&lt;td&gt;matches end of line&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;.&lt;/td&gt;&lt;td&gt;matches any single character (wildcard)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;repeat previous token zero, one or more times.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;+&lt;/td&gt;&lt;td&gt;repeat previous token one or more times&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;?&lt;/td&gt;&lt;td&gt;repeat previous token zero or one time&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;[&amp;#8230;]&lt;/td&gt;&lt;td&gt;matches any one of the class of characters enclosed between the classes.&lt;br&gt; ^ as first character reverses the match&lt;br&gt; &amp;#8211; is used to ndicate a range of characters&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;()&lt;/td&gt;&lt;td&gt;groups regex &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;|&lt;/td&gt;&lt;td&gt;either preceding or following regex can be matched&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;{n,m}&lt;/td&gt;&lt;td&gt;matches a range of occurrences of the single character that immediately precedes it. &lt;br&gt; {n} will match exactly n occurrences&lt;br&gt; {n,} will match at least n occurrences&lt;br&gt; {n,m} will match any number of occurrences between n and m&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Common expressions&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;exp&lt;/td&gt;&lt;td&gt;interpretation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;[^0-9]&lt;/td&gt;&lt;td&gt;excluding number&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;[15]00*&lt;/td&gt;&lt;td&gt;matches &amp;#8220;10&amp;#8221;, &amp;#8220;50&amp;#8221;, &amp;#8220;100&amp;#8221;, &amp;#8220;500&amp;#8221;, &amp;#8220;1000&amp;#8221;, &amp;#8220;5000&amp;#8221;. Here the first 0 is literal, the second is modified by *, see the table above&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;.*&lt;/td&gt;&lt;td&gt;any number (including 0) of any character&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;.*&amp;gt;&lt;/td&gt;&lt;td&gt;any html tags&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt; book &lt;/td&gt;&lt;td&gt;matches book with preceding and following spaces&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt; books* &lt;/td&gt;&lt;td&gt;matches books, or book, but not &amp;#8220;book.&amp;#8221; &amp;#8220;book?&amp;#8221; etc&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt; book.* &lt;/td&gt;&lt;td&gt;matches book, followed by any number of characters, or none followed by a space&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that regular expression comes in several different flavours, which can be confusing and frustrating. &lt;a href="https://unix.stackexchange.com/questions/119905/why-does-my-regular-expression-work-in-x-but-not-in-y" class="rank-math-link"&gt;This&lt;/a&gt; is a good summary. There are DFA (Deterministic Finite Automata) based engines and NFA (Non-Deterministic Finite Automata) based engines:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;NFA based engines can &amp;#8220;go back&amp;#8221; in the regex, used in Perl, Python, vim, sed and GNU grep.&lt;/li&gt;&lt;li&gt;DFA based engines cannot &amp;#8220;go back&amp;#8221; in the regex, used in awk and BSD grep. &lt;/li&gt;&lt;/ul&gt;&#10;&lt;figure class="wp-block-table"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Standard&lt;/td&gt;&lt;td&gt;IEEE POSIX&lt;br&gt;BRE&lt;/td&gt;&lt;td&gt;IEEE POSIX&lt;br&gt;ERE&lt;/td&gt;&lt;td&gt;PCRE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Detail&lt;/td&gt;&lt;td&gt;Basic Regular Expressions&lt;/td&gt;&lt;td&gt;Extended Regular Expressions that add repetition, alternation on top of BRE&lt;/td&gt;&lt;td&gt;Perl Compatible regular expression.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Engine&lt;/td&gt;&lt;td&gt;DFA&lt;/td&gt;&lt;td&gt;DFA&lt;/td&gt;&lt;td&gt;NFA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GNU grep&lt;/td&gt;&lt;td&gt;grep by default, or grep -G&lt;/td&gt;&lt;td&gt;egrep&lt;br&gt;grep -E&lt;/td&gt;&lt;td&gt;grep -P&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;BSD grep&lt;/td&gt;&lt;td&gt;grep&lt;/td&gt;&lt;td&gt;egrep&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GNU sed&lt;/td&gt;&lt;td&gt;sed&lt;/td&gt;&lt;td&gt;sed -r&lt;/td&gt;&lt;td&gt;NA. Just use perl&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;BSD sed&lt;/td&gt;&lt;td&gt;sed&lt;/td&gt;&lt;td&gt;sed -E&lt;/td&gt;&lt;td&gt;NA. Just use perl&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;awk&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;awk&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The best way to check isn on &lt;a href="https://www.freebsd.org/cgi/man.cgi" class="rank-math-link"&gt;BSD&lt;/a&gt; manual and &lt;a href="https://www.gnu.org/software/" class="rank-math-link"&gt;GNU&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here are several examples of sed and awk I came across at work:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Find and remove duplicate lines:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;awk &amp;#39;!x[$0]++&amp;#39; input_file.txt &amp;gt; output_file.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Remove white spaces at the beginning and end of each line:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;awk &amp;#39;{$1=$1}1&amp;#39; input_file.txt &amp;gt; output_file.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Print with multiple dilimiters (;, , , and |)&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;awk -F &amp;#39;[;,|]&amp;#39; &amp;#39;{print $1, $3, $5}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Print with calculation between columns&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;awk &amp;#39;{res=$1-$2;print res,$0}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Print rows conditionally&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;awk &amp;#39;$1&amp;gt;20{print;}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Prefix each line of a file&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;awk &amp;#39;$0=&amp;#34;PREFIX|&amp;#34;$0&amp;#39; input.txt &amp;gt; prefix.input.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Replace string original to new in file&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &amp;#39;s/original/new/g&amp;#39; file.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Remove multiple patterns&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed &amp;#39;s/pattern1\|pattern2\|pattern3//g&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Delete the first matching pattern only&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed &amp;#39;s/pattern//&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Remove blank lines:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &amp;#39;/^$/d&amp;#39; input_file.txt &amp;gt; output_file.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Copy from line 100 to line 500 of input file to output file&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -n 100,500p input.log&amp;gt;output.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Merge every three lines:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed &amp;#39;N;N;N; s/\n/ /g&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2018/05/cron-and-logrotate-in-centos/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;cron and anacron in RedHat Linux (How logrotate works)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2018/06/dicom-data-encoding/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;DICOM data encoding&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>cron and anacron in RedHat Linux (How logrotate works)</title><link>https://static.digihunch.com/2018/05/cron-and-logrotate-in-centos/</link><pubDate>Tue, 15 May 2018 14:11:00 -0400</pubDate><guid>https://static.digihunch.com/2018/05/cron-and-logrotate-in-centos/</guid><description>&lt;h4 class="wp-block-heading"&gt;Cron and anacron&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We all know cron is a job scheduler. Many admin uses crontab to manage scheduled task. It is also important to know that crontab works at different levels as well, as well as the distinction between cron and anacron. They are similar, but different, managed by different sets of files. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Below is a brief description of how cron works from this &lt;a href="https://www.sitepoint.com/a-comprehensive-crash-course-into-cronjobs/"&gt;article&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;After Cron starts, it searches its spool area to find and load crontab files into the memory. It additionally checks the /etc/crontab and or /etc/cron.d directories for system crontabs.&lt;br&gt;After loading the crontabs into memory, Cron checks the loaded crontabs on a minute-by-minute basis, running the events which are due.&lt;br&gt;In addition to this, Cron regularly (every minute) checks if the spool directory’s modtime (modification time) has changed. If so, it checks the modetime of all the loaded crontabs and reloads those which have changed. That’s why we don’t have to restart the daemon when installing a new cron job.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Basically, in cron, you specify a particular time at which a job will run. These jobs are managed by files in &lt;em&gt;/var/spool/cron/ &lt;/em&gt;directory. In this directory, each file is named by the username that owns the crontab file. These files shall not be edited directly by respective users. Instead, they are edited by crontab by each user. To understand the syntax, one can refer to RedHat document for &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/ch-Automating_System_Tasks"&gt;automating system tasks&lt;/a&gt;. Note that you can specify periodical jobs here with special syntax. For example, */5 at the minute slot indicates every five minutes.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Running cron jobs can be allowed or disallowed for different users. For this purpose, use the &lt;em&gt;/etc/cron.allow&lt;/em&gt; and &lt;em&gt;/etc/cron.deny&lt;/em&gt; files. If the cron.allow file exists, a user must be listed in it to be allowed to use cron If the cron.allow file does not exist but the cron.deny file does exist, then a user must not be listed in the cron.deny file in order to use cron. If neither of these files exists, only the super user is allowed to use cron.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition, there is a system-wide crontab file in /etc/crontab, in which you need to not only specify tasks, but also the user to run those tasks. By default, the schedule in this file is empty.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The limitation of cron is it assumes the servers is up all the time, if a script misses the schedule while the server is down, it will not be executed when the server comes back up. This is where anacron comes in handy. Although anacron can only be used by superuser, it doesn&amp;#8217;t expect system to be running 24&amp;#215;7. If a job is scheduled at a time system is down, it starts the job when system comes back up. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Both cron and anacron are run by systemd service named crond.service. Although they require different packages installed (cronie vs cronie-anacron). They are also managed by different sets of files as explained below:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&#10;&lt;table id="tablepress-4" class="tablepress tablepress-id-4 tbody-has-connected-cells"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1"&gt;&#10;&#9;&lt;th class="column-1"&gt;package&lt;/th&gt;&lt;th class="column-2"&gt;file or directory&lt;/th&gt;&lt;th class="column-3"&gt;purpose&lt;/th&gt;&lt;th class="column-4"&gt;example&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-striping row-hover"&gt;&#10;&lt;tr class="row-2"&gt;&#10;&#9;&lt;td rowspan="2" class="column-1"&gt;cronie&lt;/td&gt;&lt;td class="column-2"&gt;/var/spool/cron/&lt;/td&gt;&lt;td class="column-3"&gt;this directory accommodates files that represents cron jobs for each individual users.&lt;/td&gt;&lt;td class="column-4"&gt;if a file named digihunch contains a valid line, it means that Linux user digihunch has a scheduled task for the time specified.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3"&gt;&#10;&#9;&lt;td class="column-2"&gt;/etc/crontab&lt;/td&gt;&lt;td class="column-3"&gt;This file keeps system-wide cronjob entries. Each line needs to sepcify users.&lt;/td&gt;&lt;td class="column-4"&gt;if a line specifies schedule, user and command, it means that at the scheduled time, that user will execute the command.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4"&gt;&#10;&#9;&lt;td rowspan="3" class="column-1"&gt;cronie-anacron&lt;/td&gt;&lt;td class="column-2"&gt;/var/spool/anacron/&lt;/td&gt;&lt;td class="column-3"&gt;This directory accommodates files such as cron.daily, in which a timestamp is kept to indicate last execution time.&lt;/td&gt;&lt;td class="column-4"&gt;if cron.daily in this directory reads 20180418, it indicates last daily execution time stamp is 20180418&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5"&gt;&#10;&#9;&lt;td class="column-2"&gt;/etc/anacrontab&lt;/td&gt;&lt;td class="column-3"&gt;This file tells anacron where in the file system to go for directories for periodical jobs.&lt;/td&gt;&lt;td class="column-4"&gt;Example:&lt;br /&gt;&#10;&lt;code&gt;&lt;br /&gt;&#10;#period in days delay in minutes job-identifier command&lt;br /&gt;&#10;1 5 cron.daily nice run-parts /etc/cron.daily&lt;br /&gt;&#10;7 25 cron.weekly nice run-parts /etc/cron.weekly&lt;br /&gt;&#10;@monthly 45 cron.monthly nice run-parts /etc/cron.monthly&lt;br /&gt;&#10;&lt;/code&gt;&lt;br /&gt;&#10;The file usually also indicates RANDOM_DELAY and START_HOURS_RANGE&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6"&gt;&#10;&#9;&lt;td class="column-2"&gt;/etc/cron.hourly/&lt;br /&gt;&#10;/etc/cron.daily/&lt;br /&gt;&#10;/etc/cron.weekly/&lt;br /&gt;&#10;/etc/cron.monthly/&lt;/td&gt;&lt;td class="column-3"&gt;These directories stores script files that anacron needs to execute at different intervals. this is configured in /etc/anacrontab&lt;/td&gt;&lt;td class="column-4"&gt;if script logrotate is present in /etc/cron.daily/, it means the script is to be executed daily&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;!-- #tablepress-4 from cache --&gt;&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading"&gt;An anacron example: logrotate&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Rotating logs is a common task in Linux that can be done by logrotate. To understand how this works, first, make sure cronie-anacron package is installed and crond.service is up. Then examine the /etc/anacrontab file:&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;&lt;span style="color:#75715e"&gt;# /etc/anacrontab: configuration file for anacron&lt;/span&gt;&#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;&lt;span style="color:#75715e"&gt;# See anacron(8) and anacrontab(5) for details.&lt;/span&gt;&#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;SHELL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/bin/sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PATH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/sbin:/bin:/usr/sbin:/usr/bin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MAILTO&lt;span style="color:#f92672"&gt;=&lt;/span&gt;root&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# the maximal random delay added to the base delay of the jobs&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;RANDOM_DELAY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;45&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;# the jobs will be started during the following hours only&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;START_HOURS_RANGE&lt;span style="color:#f92672"&gt;=&lt;/span&gt;3-22&#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;&lt;span style="color:#75715e"&gt;#period in days delay in minutes job-identifier command&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; cron.daily nice run-parts /etc/cron.daily&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt; cron.weekly nice run-parts /etc/cron.weekly&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@monthly &lt;span style="color:#ae81ff"&gt;45&lt;/span&gt; cron.monthly nice run-parts /etc/cron.monthly&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This indicates that daily, weekly and monthly jobs are active. Go into /etc/cron.daily/, and examine script logrotate:&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;&lt;span style="color:#75715e"&gt;#!/bin/sh&#10;&lt;/span&gt;&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;/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;EXITVALUE&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:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; $EXITVALUE !&lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /usr/bin/logger -t logrotate &lt;span style="color:#e6db74"&gt;&amp;#34;ALERT exited abnormally with [&lt;/span&gt;$EXITVALUE&lt;span style="color:#e6db74"&gt;]&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;exit &lt;span style="color:#ae81ff"&gt;0&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 indicates that logrotate loads configuration from /etc/logrotate.conf, the man page of logrotate explains how this configuration works, along with an example. If you have any custom application where the log file needs rotated, it can be configured in this file.&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/2018/04/basics-of-linux-os/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Basics Terms in Linux OS&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2018/06/text-processing-with-linux-bash/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Linux Admin Basics 3 of 3 – text processing, regex, sed &amp;amp; awk&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>