<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Journal</title>
		<link>https://www.journal.petrausch.info/</link>
		<description>Recent content on www.journal.petrausch.info</description>
		<generator>Hugo -- gohugo.io</generator>
		<language>en-us</language>
		<copyright>© Copyright notice | Impressum und Datenschutz | Made with Vitae theme for Hugo</copyright>
		<lastBuildDate>Sat, 27 Jan 2024 10:00:47 +0100</lastBuildDate>
		<atom:link href="https://www.journal.petrausch.info/index.xml" rel="self" type="application/rss+xml" />
		<item>
			<title>I Need a New NAS</title>
			<link>https://www.journal.petrausch.info/post/2024/01/new-nas-design-adr/</link>
			<pubDate>Sat, 27 Jan 2024 10:00:47 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2024/01/new-nas-design-adr/</guid>
			<description>
			&lt;h2 id=&#34;context-and-problem-statement&#34;&gt;Context and Problem Statement&lt;/h2&gt;
&lt;p&gt;My current NAS, a &lt;a href=&#34;https://www.qnap.com/de-de/product/ts-251&amp;#43;&#34; target=&#34;_blank&#34;&gt;QNAP TS-251+&lt;/a&gt; with 4TB of usable space. I use about 2.5TB of the storage, so there is still some space left. When I set it up 6 years ago, I started with 500GB of used space. This is a monthly growth of about 30GB.
Our current usage profile is&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatically sync photos from our smartphones and use them as an archive&lt;/li&gt;
&lt;li&gt;Search the photo library from both the PC and the smartphones&lt;/li&gt;
&lt;li&gt;Sync services such as Nextcloud&lt;/li&gt;
&lt;li&gt;Data storage for locally hosted services (Prometheus, Firefly III)&lt;/li&gt;
&lt;li&gt;Central place to create and send offsite backups&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is still plenty of free space, but the NAS is becoming increasingly unusable. The CPU is too slow for the modern QTS operating system. The web interface is so laggy that routine operations such as updating the OS take around 20 minutes, with 18 minutes of waiting.
Also, searching the photo archive on the smartphone via the QNAP apps takes ages. The QuMagic server is unusable on the TS-251+ because it clogs up the CPU.&lt;/p&gt;
&lt;p&gt;What is more, I currently miss some fast scratch space for bigger data sets. As the CPU is so slow, any access via the network is bound by the CPU speed and not the disk speed.&lt;/p&gt;
&lt;p&gt;The quality of the internal docker support is also rather bad. I currently have some applications still running, but the docker compose description used to configure the applications is not accessible in the Container Station UI anymore. So I can&amp;rsquo;t change them anymore.&lt;/p&gt;
&lt;p&gt;Last but not least, I suspect that the hardware has some issues, as I observe random hard reboots of the NAS. This results in the RAID resyncing. This resync is also very slow and takes two days to complete for this 2 disk RAID.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;h2 id=&#34;decision-drivers&#34;&gt;Decision Drivers&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It must be able to run Linux docker container to host small applications&lt;/li&gt;
&lt;li&gt;It should consume very few watts of idle power&lt;/li&gt;
&lt;li&gt;It should support hot swap disks&lt;/li&gt;
&lt;li&gt;It should have 8TB of usable disk space&lt;/li&gt;
&lt;li&gt;It should be in the price range of 400-600€&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;considered-options&#34;&gt;Considered Options&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Build NAS myself and use General Purpose Linux OS&lt;/li&gt;
&lt;li&gt;Build NAS myself and use specialized NAS Distributions&lt;/li&gt;
&lt;li&gt;Rent a server/storage box&lt;/li&gt;
&lt;li&gt;Buy a NAS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;decision-outcome&#34;&gt;Decision Outcome&lt;/h2&gt;
&lt;p&gt;Chosen option: &amp;ldquo;Build NAS myself and use General Purpose Linux OS&amp;rdquo;, because I use a small set of services, and have the best flexibility&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;h3 id=&#34;consequences&#34;&gt;Consequences&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Good, because the NAS has enough computing power to run also as small home server, or some compute intensive ad-hoc tasks.&lt;/li&gt;
&lt;li&gt;Good, because I can use my Linux knowledge and the CLI to configure the system&lt;/li&gt;
&lt;li&gt;Bad, because I have to spend time to set it up initially and keep it up to date&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;h2 id=&#34;pros-and-cons-of-the-options&#34;&gt;Pros and Cons of the Options&lt;/h2&gt;
&lt;h3 id=&#34;build-nas-myself-and-use-general-purpose-linux-os&#34;&gt;Build NAS myself and use General Purpose Linux OS&lt;/h3&gt;
&lt;p&gt;There are &lt;a href=&#34;https://mattgadient.com/7-watts-idle-on-intel-12th-13th-gen-the-foundation-for-building-a-low-power-server-nas/&#34; target=&#34;_blank&#34;&gt;several guides&lt;/a&gt; around in the internet to build NAS with below 10 Watt idle power consumption. Asuming 10 Watt idle power, this is roughly 7,5 kWh per month, and 90 kWh per year. Assuming 35 cent/kWh, this translates to 31,50€ per year or 2,63€ per month in energy costs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Good, because the NAS has enough computing power to run also as small home server, or some compute intensive ad-hoc tasks.&lt;/li&gt;
&lt;li&gt;Good, because I can use my Linux knowledge and the CLI to configure the system&lt;/li&gt;
&lt;li&gt;Bad, because I have to spend time to set it up initially and keep it up to date&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;build-nas-myself-and-use-specialized-nas-distributions&#34;&gt;Build NAS myself and use specialized NAS Distributions&lt;/h3&gt;
&lt;p&gt;Use homemade NAS hardware as above, but use a NAS distribution.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Good, because the NAS has enough processing power to run as a small home server or for some computationally intensive ad-hoc tasks.&lt;/li&gt;
&lt;li&gt;Good, because I don&amp;rsquo;t have to spend as much time setting it up and keeping it up to date.&lt;/li&gt;
&lt;li&gt;Bad, because they often don&amp;rsquo;t support Docker out of the box.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;rent-a-serverstorage-box&#34;&gt;Rent a server/storage box&lt;/h3&gt;
&lt;p&gt;Renting a server or storage box has a higher monthly cost. In addition, we currently only have 30mbit/s upload and 100mbit/s download in our house. This makes any interactive work on large amounts of data very uncomfortable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Good, because I don&amp;rsquo;t have to run the NAS in my basement.&lt;/li&gt;
&lt;li&gt;Bad because the monthly cost is higher&lt;/li&gt;
&lt;li&gt;Bad because my current internet connection is not fast enough to support fast viewing of our image library.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;buy-a-nas&#34;&gt;Buy a NAS&lt;/h3&gt;
&lt;p&gt;Buy a newer NAS from either QNAP or Synology and use their software.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Good, because I can buy a pre-built and pre-configured system.&lt;/li&gt;
&lt;li&gt;Bad because these NAS are notoriously underpowered in terms of CPU.&lt;/li&gt;
&lt;/ul&gt;

			</description>
		</item>
		<item>
			<title>TIL: jq exit code</title>
			<link>https://www.journal.petrausch.info/post/2023/10/jq-exit-code/</link>
			<pubDate>Tue, 24 Oct 2023 06:00:47 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2023/10/jq-exit-code/</guid>
			<description>
			&lt;p&gt;&lt;a href=&#34;https://jqlang.github.io/jq/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt; is one of the most common tools I use in shell scripts and ad hoc shell commands. It allows you to parse, and
query JSON data. Personally, I&amp;rsquo;m on the same page as Kelly Brazil,
modern Unix tools should support both a human-readable text output and a structured text output, so that data can be
safely processed in scripts. He wrote a great &lt;a href=&#34;https://blog.kellybrazil.com/2019/11/26/bringing-the-unix-philosophy-to-the-21st-century/&#34; target=&#34;_blank&#34;&gt;blog post&lt;/a&gt; back in 2019.
He also wrote the great &lt;a href=&#34;https://github.com/kellyjonbrazil/jc&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;jc&lt;/code&gt;&lt;/a&gt; wrapper, which parses text output and generate structured JSON data from it.&lt;/p&gt;
&lt;p&gt;Today, I learned, that &lt;code&gt;jq&lt;/code&gt; can set its exit code depending on the last boolean expression in
the &lt;code&gt;jq&lt;/code&gt; query. This makes it very easy to write checks like: &amp;ldquo;Are there 10 infiniband interfaces on my machine?&amp;rdquo; This is because
modern &lt;code&gt;iproute2&lt;/code&gt;supports JSON based output. The command line for the above question is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip -j l | jq -e &#39;.| map(select(.link_type == \&amp;quot;infiniband\&amp;quot;)) | length == 10&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will result in either exit code 1, of there are less or more then 10 infiniband interfaces.&lt;/p&gt;
&lt;p&gt;Another powerful query is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip -j a | jq &#39;.[] | .addr_info[] | select(.scope==&amp;quot;global&amp;quot; and .family==&amp;quot;inet6&amp;quot;) | .local&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This gets you all IPv6 addresses on your machine with a global scope.&lt;/p&gt;
&lt;h2 id=&#34;a-note-on-yaml-and-jq&#34;&gt;A note on Yaml and JQ&lt;/h2&gt;
&lt;p&gt;Learning &lt;code&gt;jq&lt;/code&gt; also helps you with processing structured yaml data. With small scripts like &lt;a href=&#34;https://github.com/snoyberg/yaml/tree/master/yaml&#34; target=&#34;_blank&#34;&gt;yaml2json&lt;/a&gt;,
you can convert yaml files to jq back and forth. There is also a tool called &lt;code&gt;yq&lt;/code&gt; out there. Sadly, there are ad least three different implementations, with sligthly different
command line arguements. If you are not in charge of the concrete dependencies, user of a script or Makefile have locally installed, I always use &lt;code&gt;yaml2json&lt;/code&gt; combined with &lt;code&gt;jq&lt;/code&gt;.
As there is currently only a single &lt;code&gt;jq&lt;/code&gt; implementation out there.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Monitoring nginx with mtail</title>
			<link>https://www.journal.petrausch.info/post/2023/02/nginx-monitoring-mtail/</link>
			<pubDate>Sun, 05 Feb 2023 10:00:47 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2023/02/nginx-monitoring-mtail/</guid>
			<description>
			&lt;p&gt;I use &lt;a href=&#34;https://prometheus.io/&#34; target=&#34;_blank&#34;&gt;prometheus&lt;/a&gt; to monitor my infrastructure and until now, the nginx serving this blog
wasn&amp;rsquo;t monitored properly. Prometheus is a pull based monitoring system, scraping the monitored components via HTTP
requests. Sadly, nginx doesn&amp;rsquo;t provide a native &lt;code&gt;/metrics&lt;/code&gt; endpoint, serving metrics in the &lt;a href=&#34;https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md&#34; target=&#34;_blank&#34;&gt;OpenMetrics&lt;/a&gt;
format. Hence, we need a prometheus exporter. There is a nginx exporter provided by nginx INC
&lt;a href=&#34;https://github.com/nginxinc/nginx-prometheus-exporter&#34; target=&#34;_blank&#34;&gt;nginx-prometheus-exporter&lt;/a&gt;. This exporter only provides
basic information like the active connections, and total served connections.&lt;/p&gt;
&lt;p&gt;To get more insights, you need to run nginx plus.
Another option is to analyze the logs of nginx and generate Prometheus metrics from this.
I can recommend &lt;a href=&#34;https://github.com/google/mtail&#34; target=&#34;_blank&#34;&gt;mtail&lt;/a&gt; for this task. It&amp;rsquo;s reliable and performant.&lt;br&gt;
Matt Probert has written a good introduction as &lt;a href=&#34;https://gist.github.com/mattpr/de96f3a9c7b895ce5a9fbbe8812d0890&#34; target=&#34;_blank&#34;&gt;GitHub Gist&lt;/a&gt;.
Based on this example, I build my mtail configuration. The main difference is, that I use prometheus histograms to
analyze the distribution of the request size and timing. Moreover, I use fewer labels to reduce the size of the
prometheus datastore. Prometheus generates for every combination of labels a new time series in the database.
Especially, the &lt;code&gt;nginx_uri&lt;/code&gt; used in the GitHub Gist will explode the number of timeseries, if the URI contains an
object ID in e.g. a REST API. The &lt;a href=&#34;https://prometheus.io/docs/practices/naming/#labels&#34; target=&#34;_blank&#34;&gt;prometheus documentation&lt;/a&gt;
advices to not use user provided IDs in prometheus labels. Also, the &lt;code&gt;nginx_port&lt;/code&gt; and &lt;code&gt;nginx_content_type&lt;/code&gt;is
irrelevant for my monitoring.&lt;/p&gt;
&lt;p&gt;This is my current &lt;code&gt;nginx.mtail&lt;/code&gt; program based in the example provided by Matt Probert:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;42
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;45
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;46
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;47
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;48
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;49
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;50
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;51
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;52
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;53
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;54
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;55
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;56
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;57
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;58
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;59
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;60
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;61
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;62
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;63
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;# we stick with nginx var names here and prefix the exported metric with nginx_ by using &amp;#34;as&amp;#34;
# &amp;#34;by&amp;#34; allows us to specify our labelling/grouping
counter request_count             by nginx_host, nginx_method, nginx_status as &amp;#34;nginx_request_count&amp;#34;
histogram request_length_bytes    by nginx_host, nginx_method, nginx_status buckets 1024, 2048, 4096, 10000, 30000, 60000, 120000, 240000 as &amp;#34;nginx_request_length_bytes&amp;#34;
histogram bytes_sent              by nginx_host, nginx_method, nginx_status buckets 1024, 2048, 4096, 10000, 30000, 60000, 120000, 240000 as &amp;#34;nginx_bytes_sent&amp;#34;
counter body_bytes_sent           by nginx_host, nginx_method, nginx_status as &amp;#34;nginx_body_bytes_sent&amp;#34;
histogram request_time_hist       by nginx_host, nginx_method, nginx_status buckets 1, 10, 50, 100, 200, 400, 800, 1000, 2000 as &amp;#34;nginx_request_time_milliseconds&amp;#34;
histogram upstream_connect_time   by nginx_host, nginx_method, nginx_status buckets 1, 10, 50, 100, 200, 400, 800, 1000, 2000 as &amp;#34;nginx_upstream_connect_time_milliseconds&amp;#34;
histogram upstream_header_time    by nginx_host, nginx_method, nginx_status buckets 1, 10, 50, 100, 200, 400, 800, 1000, 2000 as &amp;#34;nginx_upstream_header_time_milliseconds&amp;#34;
histogram upstream_response_time  by nginx_host, nginx_method, nginx_status buckets 1, 10, 50, 100, 200, 400, 800, 1000, 2000 as &amp;#34;nginx_upstream_response_time_milliseconds&amp;#34;
counter nginx_log_nomatch_count

# the following pattern matches exactly the tab-separated fields in our custom access_log format
# if you want to customize...this pattern should be updated to match changes you make in the nginx log format.
/^/ +
/(?P&amp;lt;msec&amp;gt;\d+)\.\d+\t/ +       # settime() needs just the seconds so we exclude the .milliseconds part
/(?P&amp;lt;host&amp;gt;\S+)\t/ +
/(?P&amp;lt;server_port&amp;gt;\S+)\t/ +
/(?P&amp;lt;request_method&amp;gt;\S+)\t/ +
/(?P&amp;lt;uri&amp;gt;\S+)\t/ +
/(?P&amp;lt;content_type&amp;gt;\S+)\t/ +
/(?P&amp;lt;status&amp;gt;\S+)\t/ +
/(?P&amp;lt;request_length&amp;gt;\d+)\t/ +
/(?P&amp;lt;bytes_sent&amp;gt;\d+)\t/ +
/(?P&amp;lt;body_bytes_sent&amp;gt;\d+)\t/ +
/(?P&amp;lt;request_time&amp;gt;\d+\.\d+)\t/ +
/(?P&amp;lt;upstream_connect_time&amp;gt;\S+)\t/ +
/(?P&amp;lt;upstream_header_time&amp;gt;\S+)\t/ +
/(?P&amp;lt;upstream_response_time&amp;gt;\S+)/ +
/$/ {
    settime($msec)
    request_count[$host][$request_method][$status]++
    request_length_bytes[$host][$request_method][$status] = $request_length
    bytes_sent[$host][$request_method][$status] = $bytes_sent
    body_bytes_sent[$host][$request_method][$status] += $body_bytes_sent

    # Especially, for static files, the request time is often below a millisecond, hence 0. We set them to 1, to
    # count them in the histogram
    $request_time*1000.0 &amp;lt; 1 {
      request_time_hist[$host][$request_method][$status] = 1.0
    } else {
      request_time_hist[$host][$request_method][$status] = $request_time*1000.0
    }
    # mtail is happier doing counters with floats/ints.
    # nginx logs &amp;#39;-&amp;#39; when there isn&amp;#39;t a value which
    # we check for - and skip updating these counters if found.
    # otherwise we cast the string to a float and increment the counter.
    $upstream_connect_time != &amp;#34;-&amp;#34; {
        upstream_connect_time[$host][$request_method][$status] = float($upstream_connect_time)*1000
    }
    $upstream_header_time != &amp;#34;-&amp;#34; {
        upstream_header_time[$host][$request_method][$status] = float($upstream_header_time)*1000
    }
    $upstream_response_time != &amp;#34;-&amp;#34; {
        upstream_response_time[$host][$request_method][$status] = float($upstream_response_time)*1000
    }
} else {
    # our pattern doesn&amp;#39;t match.
    # in this example since we have a single program with a single log file...it should always match
    # or we have a bug.
    # can use this metric to detect when our parser is failing.
    nginx_log_nomatch_count++
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;I use the same nginx access log format as Matt Probert have shown in his gist:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;log_format prometheus_log &amp;#39;$msec\t$host\t$server_port\t$request_method\t$uri\t$content_type\t$status\t$request_length\t$bytes_sent\t$body_bytes_sent\t$request_time\t$upstream_connect_time\t$upstream_header_time\t$upstream_response_time&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The dashboard I currently use looks like this:
&lt;figure&gt;
  &lt;img src=&#34;https://www.journal.petrausch.info/images/nginx_grafana_dashboard.png&#34; alt=&#34;Screenshot of Grafana dashboard for nginx&#34;  /&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The Grafana export can be found &lt;a href=&#34;https://www.journal.petrausch.info/gists/nginx.json&#34;&gt;here&lt;/a&gt;&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>[Link] Architecture best practices for your small team</title>
			<link>https://www.journal.petrausch.info/post/2022/12/low-ops-cloud-native/</link>
			<pubDate>Wed, 14 Dec 2022 10:00:47 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2022/12/low-ops-cloud-native/</guid>
			<description>
			&lt;p&gt;Yesterday, I published a &lt;a href=&#34;https://www.inovex.de/de/blog/low-ops-cloud-native-architecture/&#34; target=&#34;_blank&#34;&gt;longer text in the blog&lt;/a&gt;
of my employer. I wrote how to structure your software architecture, as a small team targeting a non-hyper-growth
market. Mainly, how to not let Kubernetes eat all your engineering time, yet being able to scale your application
and shift it between clouds.&lt;/p&gt;
&lt;p&gt;If you like the content here, you should definitly check out that text as well.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Things I learned about VMs with two interfaces on OpenStack</title>
			<link>https://www.journal.petrausch.info/post/2022/11/til-multihomed-openstack/</link>
			<pubDate>Tue, 29 Nov 2022 21:00:47 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2022/11/til-multihomed-openstack/</guid>
			<description>
			&lt;p&gt;Sometimes you want to attach two interfaces to a OpenStack virtual machine (VM). As discussed in my &lt;a href=&#34;../til-ipvs-openstack&#34;&gt;last post&lt;/a&gt;,
I had to disable OpenStacks &lt;a href=&#34;https://superuser.openstack.org/articles/managing-port-level-security-openstack/&#34; target=&#34;_blank&#34;&gt;port security&lt;/a&gt; feature
to allow my IPVS realservers to implement direct server return. Disabling port-security has the downside, that my
realserver can participate in other OpenStack security groups. For my use case, my realservers have to be part of a
security group to reach certain backends. To implement that, I added a second network interface to my VM. It turned out,
it was not easy as expected. This picture shows the setup:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
  &lt;img src=&#34;https://www.journal.petrausch.info/images/2022-11-two-interfaces.svg&#34; alt=&#34;picture of a virtual machine with two interfaces and a router&#34;  /&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The underlying OpenStack network implemented with Linux bridges is very picky about which traffic can be sent over
which interface. By default, Linux is &lt;a href=&#34;https://access.redhat.com/solutions/30564&#34; target=&#34;_blank&#34;&gt;not configured&lt;/a&gt; for this setup. You
have to change certain defaults to make this work. To sum the linked article up, Linux will respond by default to an
ARP request received on any interface requesting an IP assigned to any local interface. Thus, in the example above,
an ARP request received on &lt;code&gt;ens3&lt;/code&gt; requesting the IP &lt;code&gt;192.0.2.4&lt;/code&gt; will be answered. This messes up the OpenStack network,
since it contradicts the security model and assumes the response is spoofing. OpenStack compares ARP responses with
the configured IP addresses in its network model. The second problem is, that for any packets originating on my
realserver, only the interface &lt;code&gt;ens3&lt;/code&gt; is used. Even if the source IP is &lt;code&gt;192.0.2.4&lt;/code&gt;. This is due to the fact, that
by default the first matching route is used. We use policy-based routing to fix this problem.&lt;/p&gt;
&lt;h2 id=&#34;arp&#34;&gt;ARP&lt;/h2&gt;
&lt;p&gt;For ARP, we use the same settings as in &lt;a href=&#34;../til-ipvs-openstack&#34;&gt;my last post&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sysctl -qw net.ipv4.conf.all.arp_ignore&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
sysctl -qw net.ipv4.conf.ens3.arp_ignore&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
sysctl -qw net.ipv4.conf.ens4.arp_ignore&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;As explained in my last post, the &lt;a href=&#34;https://sysctl-explorer.net/net/ipv4/arp_ignore/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;arp_ignore=1&lt;/code&gt;&lt;/a&gt; sysctl settings will
instruct the linux kernel only to answer ARP requests for IPs attached to the receiving interface. Thus, in our
example, the kernel will only respond to ARP requests received via &lt;code&gt;ens3&lt;/code&gt; requesting the IP &lt;code&gt;192.0.2.3&lt;/code&gt;. ARP
requests for the IP &lt;code&gt;192.0.2.4&lt;/code&gt; are ignored on the interface &lt;code&gt;ens3&lt;/code&gt; after this setting is set.&lt;/p&gt;
&lt;h2 id=&#34;policy-based-routing&#34;&gt;Policy-Based Routing&lt;/h2&gt;
&lt;p&gt;The next problem we have to solve, is that the Linux kernel will send traffic originating from the IP &lt;code&gt;192.0.2.4&lt;/code&gt;
via the &lt;code&gt;ens3&lt;/code&gt; interface. This traffic will be dropped by OpenStack, since it assumes this is spoofed traffic.
Furthermore, we want to use the security groups
attached to &lt;code&gt;ens4&lt;/code&gt;. To make sure, traffic originating from &lt;code&gt;192.0.2.4&lt;/code&gt; is forwarded via the &lt;code&gt;ens4&lt;/code&gt; interface, we
must use policy-based routing.&lt;/p&gt;
&lt;p&gt;First, we create two new routing tables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;echo &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; table_ens3 &amp;gt; /etc/iproute2/rt_tables
echo &lt;span style=&#34;color:#ae81ff&#34;&gt;201&lt;/span&gt; table_ens4 &amp;gt; /etc/iproute2/rt_tables
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;You can choose what ever name you want. I used &lt;code&gt;table_ensX&lt;/code&gt; for clarity. You must however, choose a different ID for
both tables. I have chosen the ID 200 and 201.&lt;/p&gt;
&lt;p&gt;Next, we add the default routes to the two routing tables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Adding host route for our gateway&lt;/span&gt;
ip route add table table_ens3 192.0.2.1 dev ens3
&lt;span style=&#34;color:#75715e&#34;&gt;# Adding default route via the gateway&lt;/span&gt;
ip route add table table_ens3 default via 192.0.2.1 dev ens3

&lt;span style=&#34;color:#75715e&#34;&gt;# Adding host route for our gateway&lt;/span&gt;
ip route add table table_ens4 192.0.2.1 dev ens4
&lt;span style=&#34;color:#75715e&#34;&gt;# Adding default route via the gateway&lt;/span&gt;
ip route add table table_ens4 default via 192.0.2.1 dev ens4
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;ip route add table table_ensX&lt;/code&gt; instructs the &lt;code&gt;ip route add&lt;/code&gt; command, to add the route to the routing table &lt;code&gt;table_ensX&lt;/code&gt;.
If you have other routing requirements, e.g. allowing use &lt;code&gt;ens4&lt;/code&gt; only for traffic within the subnet &lt;code&gt;192.0.2.0/24&lt;/code&gt;,
you can do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Adding route for subnet via the gateway&lt;/span&gt;
ip route add table table_ens4 192.0.2.0/24 via 192.0.2.1 dev ens4
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The last step is to configure the policy-based routing. Therefore, we use the &lt;code&gt;ip rule&lt;/code&gt; command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use the table table_ens4 for routing lookups for the ip 192.0.2.4&lt;/span&gt;
ip rule add from 192.0.2.3 lookup table_ens3

&lt;span style=&#34;color:#75715e&#34;&gt;# Use the table table_ens4 for routing lookups for the ip 192.0.2.4&lt;/span&gt;
ip rule add from 192.0.2.4 lookup table_ens4
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To show the rules/policies in effect, you can use the command &lt;code&gt;ip rule show&lt;/code&gt;. The output should look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;0:	from all lookup local
32764:	from 192.0.2.3 lookup table_ens3
32765:	from 192.0.2.4 lookup table_ens4
32766:	from all lookup main
32767:	from all lookup default
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The first number is the priority. The rules are check from the lowest priority number (zero) to the highest (here
32767). The first matching rule is used.&lt;/p&gt;
&lt;p&gt;To test your routing setup, the command &lt;code&gt;ip route get&lt;/code&gt; is very handy. This let you check the where a packet would be
routed.
Doing this should give you an output like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;ip route get 8.8.8.8 from 192.0.2.3
8.8.8.8 via 192.0.2.1 dev ens3 src 192.0.2.3 table table_ens3 uid &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt; 
    cache 
    
ip route get 8.8.8.8 from 192.0.2.4
8.8.8.8 via 192.0.2.1 dev ens4 src 192.0.2.4 table table_ens3 uid &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;
    cache 
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;As you can see, &lt;code&gt;ip route get&lt;/code&gt; shows you the device &lt;code&gt;dev ens3&lt;/code&gt; and the used table to retrieve that information. The
downside of this set up is, you have to manage the routes in the tables &lt;code&gt;table_ens3&lt;/code&gt; and &lt;code&gt;table_ens4&lt;/code&gt; by yourself.
Thus, you should to this only if your routing and the IPs are pretty static.&lt;/p&gt;
&lt;p&gt;To sum it up, we have learned how to configure Linux to run with two interfaces in the same subnet. First, we have
to reconfigure the default ARP answering behaviour. Secondly, we have to use policy-based routing to steer the
egress traffic to the proper interfaces.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Things I learned about IPVS on OpenStack</title>
			<link>https://www.journal.petrausch.info/post/2022/11/til-ipvs-openstack/</link>
			<pubDate>Sun, 06 Nov 2022 21:00:47 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2022/11/til-ipvs-openstack/</guid>
			<description>
			&lt;p&gt;Currently, I&amp;rsquo;m working with IPVS and OpenStack. This block post records some quirks I have found while setting up
IPVS within a VM on top of OpenStack.
None of these are unknown for experienced networking people, but I think they are worth to write down. In my setup
I use IPVS with the
TUN mode. Both the IPVS director and the server are located within the same OpenStack network. I have assigned the
virtual IP (VIP) to the &lt;code&gt;tunl0&lt;/code&gt; interface of the realservers. This causes some ARP problems since, by default most
linux servers answer ARP requests on any interface. For example, let&amp;rsquo;s assume our realserver has an interface &lt;code&gt;eth0&lt;/code&gt;
attached to the OpenStack network. The VIP (&lt;code&gt;192.168.48.3&lt;/code&gt;) is attached to &lt;code&gt;tunl0&lt;/code&gt;. By default our realserver will
answer
any ARP request for the IP &lt;code&gt;192.168.48.3&lt;/code&gt; on the interface &lt;code&gt;eth0&lt;/code&gt; as well. To deactivate this, I have configured&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sysctl -qw net.ipv4.conf.all.arp_filter&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
sysctl -qw net.ipv4.conf.all.arp_ignore&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
sysctl -qw net.ipv4.conf.eth0.arp_filter&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
sysctl -qw net.ipv4.conf.eth0.arp_ignore&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://sysctl-explorer.net/net/ipv4/arp_ignore/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;arp_ignore=1&lt;/code&gt;&lt;/a&gt; instructs the kernel only to answer ARP requests,
if the requested IP address is assigned to the
network interface, the ARP request was received on. &lt;a href=&#34;https://sysctl-explorer.net/net/ipv4/arp_filter/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;arp_filter&lt;/code&gt;&lt;/a&gt; does the same but will also respect your source
based routing setup and will answer only if the kernel had routed an outgoing packet via the interface the
ARP request was received on. I have set it for both &lt;code&gt;all&lt;/code&gt; and the &lt;code&gt;eth0&lt;/code&gt; interface, since the maximum value of the
value configured for &lt;code&gt;all&lt;/code&gt; and an interface is used to determine the effective value for the interface.
The IPVS &lt;a href=&#34;http://kb.linuxvirtualserver.org/wiki/ARP_Issues_in_LVS/DR_and_LVS/TUN_Clusters&#34; target=&#34;_blank&#34;&gt;knowledgebase&lt;/a&gt; has more
details and other solutions for this problem.&lt;/p&gt;
&lt;p&gt;The second and harder problem I ran into was that my realservers got the the SYN packet of a new connection via the
&lt;code&gt;tunl0&lt;/code&gt; interface, but never replied with a &lt;code&gt;SYN-ACK&lt;/code&gt;. Thus, the TCP three-way handshake could never succeed. After
a very helpful tip of &lt;a href=&#34;https://twitter.com/awlnx&#34; target=&#34;_blank&#34;&gt;@awlnx&lt;/a&gt; on &lt;a href=&#34;https://twitter.com/awlnx/status/1587904208757346305&#34; target=&#34;_blank&#34;&gt;twitter&lt;/a&gt;
I disabled &lt;a href=&#34;https://sysctl-explorer.net/net/ipv4/rp_filter/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;rp_filter&lt;/code&gt;&lt;/a&gt; on the &lt;code&gt;tunl0&lt;/code&gt; interface. &lt;code&gt;rp_filter&lt;/code&gt; is a
spoofing protection enabled by default. It discards all packets received on an interface where the source IP address
is not reachable via that interface. This is a very secure and advised default, but since we do asymmetrical routing
it will drop our &lt;code&gt;SYN&lt;/code&gt; packets received via the &lt;code&gt;tunl0&lt;/code&gt; interface.
I have configured:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sysctl -qw net.ipv4.conf.tunl0.rp_filter&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
sysctl -qw net.ipv4.conf.all.rp_filter&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Also, for both &lt;code&gt;all&lt;/code&gt; and the &lt;code&gt;tunl0&lt;/code&gt; interface, because the maximum value is chosen. The default for &lt;code&gt;rp_filter&lt;/code&gt; is 1.&lt;/p&gt;
&lt;p&gt;The last problem I encountered where related to OpenStacks &lt;a href=&#34;https://superuser.openstack.org/articles/managing-port-level-security-openstack/&#34; target=&#34;_blank&#34;&gt;port security&lt;/a&gt; feature.
I have added the &lt;code&gt;VIP&lt;/code&gt; as &lt;a href=&#34;https://access.redhat.com/documentation/en-us/red_hat_openstack_platform/10/html/networking_guide/sec-allowed-address-pairs&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;allowed-address-pair&lt;/code&gt;&lt;/a&gt;
on the &lt;code&gt;eth0&lt;/code&gt; interface of my realservers, yet the OpenStack networking layer drops the outgoing &lt;code&gt;SYN-ACK&lt;/code&gt; packets
from my realservers. The only solutions is to disable port security for the interface in OpenStack. I have yet to
find out if this is related to the used OpenStack network implementation or a general OpenStack problem. Disabling
port security entirely will also disable all security groups attached to that interface.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Explore Container Images Without A Shell</title>
			<link>https://www.journal.petrausch.info/post/2021/02/explore-container-image/</link>
			<pubDate>Fri, 19 Feb 2021 21:00:47 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2021/02/explore-container-image/</guid>
			<description>
			&lt;p&gt;A best practice in building container images is to add as little dependencies as possible into the image.
Most application don&amp;rsquo;t need a shell to run, hence dropping the shell from the container image reduces the size
of the image and reduces the attack surface. Popular base images for that use case is either not using a base image at all
and build the image &lt;code&gt;FROM SCRATCH&lt;/code&gt; or use &lt;a href=&#34;https://github.com/GoogleContainerTools/distroless&#34; target=&#34;_blank&#34;&gt;distroless&lt;/a&gt;. The downside is that we can&amp;rsquo;t open a shell inside the running container
for debugging.&lt;/p&gt;
&lt;p&gt;Kubernetes introduces &lt;a href=&#34;https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/&#34; target=&#34;_blank&#34;&gt;ephemeral containers&lt;/a&gt;
to spawn a debugging container into a running pod.
To debug build issues or examine a container image before bringing it in production we have to have a look at the content
of the filesystem in the image. In a container image with a shell installed we can create a container instance and launch a shell as entrypoint.
This is not possible in images based on &lt;code&gt;SCRATCH&lt;/code&gt; or distroless.&lt;/p&gt;
&lt;p&gt;The container engine &lt;a href=&#34;https://podman.io/&#34; target=&#34;_blank&#34;&gt;podman&lt;/a&gt; allows us to mount a container image into the filesystem of the developer machine.
This allows us to examine the filesystem content of the container image with the tools installed on the developers machine.&lt;/p&gt;
&lt;h2 id=&#34;mounting-the-image&#34;&gt;Mounting the image&lt;/h2&gt;
&lt;p&gt;To demonstrate this feature of podman we want to examine the current distroless base image .
Pull that image:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;christoph@thinkpad-sport % podman image pull gcr.io/distroless/base-debian10
Trying to pull gcr.io/distroless/base-debian10:latest...
Getting image source signatures
Copying blob 1cfcc1bb8434 &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;  
Copying blob d94d38b8f0e6 &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;  
Copying config af31651e48 &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;  
Writing manifest to image destination
Storing signatures
af31651e48fe5f4a0788ad9812ba41315d3f9ef41fd5665313c619fdd20e0f6e
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The next step is to create a new user namespace. This allows us to freely explore the container image as root user.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;christoph@thinkpad-sport % podman unshare

root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# id&lt;/span&gt;    
uid&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;root&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; gid&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;root&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; groups&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;root&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;,65534&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;nobody&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After this we can mount a container image into the user namespace.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# podman image mount gcr.io/distroless/base-debian10&lt;/span&gt;
/home/christoph/.local/share/containers/storage/vfs/dir/021295fa05fd0d2ac6b0eabbbc525bcfd6e2e1959f6ac5da80f97dabf9dc0fd1
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The command returns the mount point where the image is mounted.
Let examine the glibc version installed in the distroless image:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# cd /home/christoph/.local/share/containers/storage/vfs/dir/021295fa05fd0d2ac6b0eabbbc525bcfd6e2e1959f6ac5da80f97dabf9dc0fd1&lt;/span&gt;
root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# ls&lt;/span&gt;
bin  boot  dev  etc  home  lib  lib64  proc  root  run  sbin  sys  tmp  usr  var
root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# ls lib/x86_64-linux-gnu/&lt;/span&gt;
ld-2.28.so               libanl-2.28.so    libc.so.6        libmvec.so.1    libnss_compat-2.28.so  libnss_files.so.2       libnss_nis-2.28.so  libresolv-2.28.so    libthread_db.so.1
ld-linux-x86-64.so.2     libanl.so.1       libdl-2.28.so    libm-2.28.so    libnss_compat.so.2     libnss_hesiod-2.28.so   libnss_nis.so.2     libresolv.so.2       libutil-2.28.so
libBrokenLocale-2.28.so  libcrypt-2.28.so  libdl.so.2       libm.so.6       libnss_dns-2.28.so     libnss_hesiod.so.2      libpcprofile.so     librt-2.28.so        libutil.so.1
libBrokenLocale.so.1     libcrypt.so.1     libmemusage.so   libnsl-2.28.so  libnss_dns.so.2        libnss_nisplus-2.28.so  libpthread-2.28.so  librt.so.1
libSegFault.so           libc-2.28.so      libmvec-2.28.so  libnsl.so.1     libnss_files-2.28.so   libnss_nisplus.so.2     libpthread.so.0     libthread_db-1.0.so
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Based on the filenames we assume a glibc 2.28 installed in the image. Since we know that the image is based on debian we can
have a look at the dpkg database.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# cat -p var/lib/dpkg/status.d/libc6 | head -n 5&lt;/span&gt;
Package: libc6
Source: glibc
Version: 2.28-10
Architecture: amd64
Maintainer: GNU Libc Maintainers &amp;lt;debian-glibc@lists.debian.org&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;So we have the concrete package version 2.28-10.
We can do the same to find the installed openssl version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# cat var/lib/dpkg/status.d/libssl1 | head -n 5&lt;/span&gt;
Package: libssl1.1
Source: openssl
Version: 1.1.1d-0+deb10u4
Architecture: amd64
Maintainer: Debian OpenSSL Team &amp;lt;pkg-openssl-devel@lists.alioth.debian.org&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;cleanup&#34;&gt;Cleanup&lt;/h2&gt;
&lt;p&gt;To clean up, exit the user namespace:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;root@thinkpad-sport &lt;span style=&#34;color:#75715e&#34;&gt;# exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Last but not least delete the image:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;christoph@thinkpad-sport % podman image rm gcr.io/distroless/base-debian10
Untagged: gcr.io/distroless/base-debian10:latest
Deleted: af31651e48fe5f4a0788ad9812ba41315d3f9ef41fd5665313c619fdd20e0f6e
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;alternatives&#34;&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;An alternative to podman is &lt;a href=&#34;https://github.com/wagoodman/dive&#34; target=&#34;_blank&#34;&gt;dive&lt;/a&gt;. This tool let you explore the image layers in a ncurses
UI. It focuses on the filesystem attributes of files and the changes between the image layers. Hence you can see the names and
the attributes of a file but not the content.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Set Default Annotations with Kyverno</title>
			<link>https://www.journal.petrausch.info/post/2021/02/kyverno-default-annotations/</link>
			<pubDate>Fri, 05 Feb 2021 20:51:02 +0100</pubDate>
			<guid>https://www.journal.petrausch.info/post/2021/02/kyverno-default-annotations/</guid>
			<description>
			&lt;p&gt;&lt;a href=&#34;https://kyverno.io/&#34; target=&#34;_blank&#34;&gt;Kyverno&lt;/a&gt; is a policy engine for kubernetes.
It allows you to implement &lt;a href=&#34;https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook&#34; target=&#34;_blank&#34;&gt;ValidatingAdmissionWebhooks&lt;/a&gt; and &lt;a href=&#34;https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook&#34; target=&#34;_blank&#34;&gt;MutatingAdmissionWebhooks&lt;/a&gt; by creating (Cluster)Policy custom resources.
Kyverno is less powerful than &lt;a href=&#34;https://www.openpolicyagent.org/docs/latest/policy-language/#what-is-rego&#34; target=&#34;_blank&#34;&gt;rego&lt;/a&gt; powered &lt;a href=&#34;https://www.openpolicyagent.org/&#34; target=&#34;_blank&#34;&gt;OpenPolicyAgent&lt;/a&gt;,
but it is also easier to write.&lt;/p&gt;
&lt;p&gt;Today I had to set an annotation to an &lt;code&gt;Ingress&lt;/code&gt; resource if the user does not provide any value for this annotation.&lt;/p&gt;
&lt;p&gt;This is very easy using the &lt;a href=&#34;https://kyverno.io/docs/writing-policies/mutate/#conditional-logic-using-anchors&#34; target=&#34;_blank&#34;&gt;&lt;em&gt;Add if not present&lt;/em&gt; anchor&lt;/a&gt; in a mutate rule.
In our use case we want to set the &lt;code&gt;alb.ingress.kubernetes.io/certificate-arn&lt;/code&gt; to the value &lt;code&gt;arn:aws:acm:eu-central-1:XXXXXX:certificate/12345&lt;/code&gt; if the user does not provide a value.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;apiVersion&lt;/span&gt;: kyverno.io/v1
&lt;span style=&#34;color:#66d9ef&#34;&gt;kind&lt;/span&gt;: ClusterPolicy
&lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: set-default-arn
&lt;span style=&#34;color:#66d9ef&#34;&gt;spec&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;rules&lt;/span&gt;:
    - &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: set-default-arn
      &lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;resources&lt;/span&gt;:
          &lt;span style=&#34;color:#66d9ef&#34;&gt;kinds&lt;/span&gt;:
            - Ingress
      &lt;span style=&#34;color:#66d9ef&#34;&gt;mutate&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;patchStrategicMerge&lt;/span&gt;:
          &lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
            &lt;span style=&#34;color:#66d9ef&#34;&gt;annotations&lt;/span&gt;:
              &lt;span style=&#34;color:#66d9ef&#34;&gt;+(alb.ingress.kubernetes.io/certificate-arn)&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arn:aws:acm:eu-central-1:XXXXXX:certificate/12345&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After applying the above &lt;code&gt;ClusterPolicy&lt;/code&gt;, we can create this ingress:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;apiVersion&lt;/span&gt;: extensions/v1beta1
&lt;span style=&#34;color:#66d9ef&#34;&gt;kind&lt;/span&gt;: Ingress
&lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: helloworld
&lt;span style=&#34;color:#66d9ef&#34;&gt;spec&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;rules&lt;/span&gt;:
    - &lt;span style=&#34;color:#66d9ef&#34;&gt;host&lt;/span&gt;: helloworld.example.com
      &lt;span style=&#34;color:#66d9ef&#34;&gt;http&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;paths&lt;/span&gt;:
          - &lt;span style=&#34;color:#66d9ef&#34;&gt;backend&lt;/span&gt;:
              &lt;span style=&#34;color:#66d9ef&#34;&gt;serviceName&lt;/span&gt;: helloworld
              &lt;span style=&#34;color:#66d9ef&#34;&gt;servicePort&lt;/span&gt;: http
            &lt;span style=&#34;color:#66d9ef&#34;&gt;path&lt;/span&gt;: /
            &lt;span style=&#34;color:#66d9ef&#34;&gt;pathType&lt;/span&gt;: ImplementationSpecific
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The resulting &lt;code&gt;Ingress&lt;/code&gt; will have the annotation &lt;code&gt;alb.ingress.kubernetes.io/certificate-arn&lt;/code&gt; set to the value &lt;code&gt;arn:aws:acm:eu-central-1:XXXXXX:certificate/12345&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;% kubectl apply -f ingress.yaml               
ingress.extensions/helloworld created
% kubectl get ingress helloworld -o json | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.metadata.annotations[&amp;#34;alb.ingress.kubernetes.io/certificate-arn&amp;#34;]&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arn:aws:acm:eu-central-1:XXXXXX:certificate/12345&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If we create the following &lt;code&gt;Ingress&lt;/code&gt;, the kyverno policy will not change the annotation at all:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;apiVersion&lt;/span&gt;: extensions/v1beta1
&lt;span style=&#34;color:#66d9ef&#34;&gt;kind&lt;/span&gt;: Ingress
&lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;annotations&lt;/span&gt;:
    &lt;span style=&#34;color:#66d9ef&#34;&gt;alb.ingress.kubernetes.io/certificate-arn&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dont-touch-this&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: helloworld-dont-touch
&lt;span style=&#34;color:#66d9ef&#34;&gt;spec&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;rules&lt;/span&gt;:
    - &lt;span style=&#34;color:#66d9ef&#34;&gt;host&lt;/span&gt;: helloworld.example.com
      &lt;span style=&#34;color:#66d9ef&#34;&gt;http&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;paths&lt;/span&gt;:
          - &lt;span style=&#34;color:#66d9ef&#34;&gt;backend&lt;/span&gt;:
              &lt;span style=&#34;color:#66d9ef&#34;&gt;serviceName&lt;/span&gt;: helloworld
              &lt;span style=&#34;color:#66d9ef&#34;&gt;servicePort&lt;/span&gt;: http
            &lt;span style=&#34;color:#66d9ef&#34;&gt;path&lt;/span&gt;: /
            &lt;span style=&#34;color:#66d9ef&#34;&gt;pathType&lt;/span&gt;: ImplementationSpecific
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Create the resource and observe the value of the annotation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;% kubectl apply -f ingress-dont-touch.yaml               
ingress.extensions/helloworld-dont-touch created
% kubectl get ingress helloworld -o json | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.metadata.annotations[&amp;#34;alb.ingress.kubernetes.io/certificate-arn&amp;#34;]&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dont-touch-this&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Combining this with the feature of matching rules on annotation, we can apply this annotation only to certain ALB ingress groups.
The AWS loadbalancer controller, will create an ALB ingress for every value of &lt;code&gt;alb.ingress.kubernetes.io/group.name&lt;/code&gt;.
Certain settings must be equal across all ingresses from the same group.
The following kyverno policy allows us to set the &lt;code&gt;alb.ingress.kubernetes.io/scheme&lt;/code&gt; annotation to the same default value in the ingress group &lt;code&gt;internal&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;apiVersion&lt;/span&gt;: kyverno.io/v1
&lt;span style=&#34;color:#66d9ef&#34;&gt;kind&lt;/span&gt;: ClusterPolicy
&lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: set-default-internal-scheme
&lt;span style=&#34;color:#66d9ef&#34;&gt;spec&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;rules&lt;/span&gt;:
    - &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: set-default-internal-scheme
      &lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;resources&lt;/span&gt;:
           &lt;span style=&#34;color:#66d9ef&#34;&gt;annotations&lt;/span&gt;:
             &lt;span style=&#34;color:#66d9ef&#34;&gt;alb.ingress.kubernetes.io/group.name&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;
             &lt;span style=&#34;color:#66d9ef&#34;&gt;kubernetes.io/ingress.class&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;alb&amp;#34;&lt;/span&gt;
          &lt;span style=&#34;color:#66d9ef&#34;&gt;kinds&lt;/span&gt;:
            - Ingress
      &lt;span style=&#34;color:#66d9ef&#34;&gt;mutate&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;patchStrategicMerge&lt;/span&gt;:
          &lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
            &lt;span style=&#34;color:#66d9ef&#34;&gt;annotations&lt;/span&gt;:
              &lt;span style=&#34;color:#66d9ef&#34;&gt;+(alb.ingress.kubernetes.io/scheme)&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After applying this &lt;code&gt;ClusterPolicy&lt;/code&gt; every &lt;code&gt;Ingress&lt;/code&gt; with the ingress class &lt;code&gt;alb&lt;/code&gt; annotation, the ALB group &lt;code&gt;internal&lt;/code&gt; will have the &lt;code&gt;alb.ingress.kubernetes.io/scheme&lt;/code&gt; annotation set to &lt;code&gt;internal&lt;/code&gt; if not set.
If we want to enforce the value &lt;code&gt;ìnternal&lt;/code&gt; for the annotation &lt;code&gt;alb.ingress.kubernetes.io/scheme&lt;/code&gt; we can apply the following policy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;apiVersion&lt;/span&gt;: kyverno.io/v1
&lt;span style=&#34;color:#66d9ef&#34;&gt;kind&lt;/span&gt;: ClusterPolicy
&lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: enforce-internal-scheme
&lt;span style=&#34;color:#66d9ef&#34;&gt;spec&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;rules&lt;/span&gt;:
    - &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: enforce-internal-scheme
      &lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;resources&lt;/span&gt;:
           &lt;span style=&#34;color:#66d9ef&#34;&gt;annotations&lt;/span&gt;:
             &lt;span style=&#34;color:#66d9ef&#34;&gt;alb.ingress.kubernetes.io/group.name&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;
             &lt;span style=&#34;color:#66d9ef&#34;&gt;kubernetes.io/ingress.class&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;alb&amp;#34;&lt;/span&gt;
          &lt;span style=&#34;color:#66d9ef&#34;&gt;kinds&lt;/span&gt;:
            - Ingress
      &lt;span style=&#34;color:#66d9ef&#34;&gt;mutate&lt;/span&gt;:
        &lt;span style=&#34;color:#66d9ef&#34;&gt;patchStrategicMerge&lt;/span&gt;:
          &lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
            &lt;span style=&#34;color:#66d9ef&#34;&gt;annotations&lt;/span&gt;:
              &lt;span style=&#34;color:#66d9ef&#34;&gt;alb.ingress.kubernetes.io/scheme&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The difference is the missing &lt;code&gt;+()&lt;/code&gt; anchor around the annotation key. This policy will overwrite any value of &lt;code&gt;alb.ingress.kubernetes.io/scheme&lt;/code&gt; a created or changed ingress will have.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>My Personal Backup Design</title>
			<link>https://www.journal.petrausch.info/post/2021/01/backup-checklist/</link>
			<pubDate>Fri, 08 Jan 2021 14:26:23 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2021/01/backup-checklist/</guid>
			<description>
			&lt;p&gt;Compute devices may fail and lose your data. Hardware failures, software bugs and encrypting trojans threaten your data. And even if your computers don&amp;rsquo;t lose your data, a human error can erase a lot of data quickly. Without a backup you are either doomed to redo a lot of work or the precious pictures of the last years are lost forever. In this blogpost I want to show you the design goals I use to design my backup strategy. I will start with the goals itself and will outline my reasoning later and describe my implementation of this design.&lt;/p&gt;
&lt;h2 id=&#34;design-goals&#34;&gt;Design Goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Have two backups, an onsite and an offsite backup&lt;/li&gt;
&lt;li&gt;Encrypt at least your offsite backup&lt;/li&gt;
&lt;li&gt;Be able to restore your offsite backup without any of your personal computing devices&lt;/li&gt;
&lt;li&gt;Use different backup tools for your onsite and offsite backups&lt;/li&gt;
&lt;li&gt;Script your backups&lt;/li&gt;
&lt;li&gt;Test a restore regularly&lt;/li&gt;
&lt;li&gt;Synchronisation without version history is not a backup&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;reasoning&#34;&gt;Reasoning&lt;/h2&gt;
&lt;p&gt;The two kinds of backups are used to protect your data from different threads and enable restores on different time scales. The onsite backup protects your data from hardware failures, software bugs, encrypting trojans or human errors. The local backup target may be an external USB harddrive or a NAS. Since your backup target device is local to the source of the data, the network or USB speeds are quite high. This allows for a high frequency of backups. The frequency of backups are between every couple of minutes up to every day. The restore time is low since we can achieve a couple hundert MBit/s up to GBit/s over local network or USB connections.&lt;/p&gt;
&lt;p&gt;In contrast the offsite backup is often connected with way lower speeds to your home. The offsite backup protects your data from a total loss of your home. Common causes of a total loss of your home is a fire, earth quake or if your local computing hardware is in the basement, a flood. As an offsite backup target you can either use a service like &lt;a href=&#34;https://www.backblaze.com/de_DE/&#34; target=&#34;_blank&#34;&gt;Backblaze&lt;/a&gt;, &lt;a href=&#34;https://aws.amazon.com/de/s3/&#34; target=&#34;_blank&#34;&gt;Amazon S3 Glacier&lt;/a&gt; or &lt;a href=&#34;https://rsync.net/&#34; target=&#34;_blank&#34;&gt;rsync.net&lt;/a&gt; via you internet connection or you can store a (USB) harddrive at a friends house or at work. An external harddrive costs no recuring fee, but the creation of a backup involves alot of repetitive manual labor. Thus it requires alot of discipline to get a regular backup. Using a service via the internet allows you to automate the complete backup process.&lt;/p&gt;
&lt;p&gt;Regardless of your of your offsite backup target, you want to encrypt your backup since you can&amp;rsquo;t physical prevent any unauthorized third party from reading your data. In case of the harddrive backup target you can either encrypt the drive itself or use a tool encrypting your files in the filesystem. Most modern backup tools like &lt;a href=&#34;https://restic.net/&#34; target=&#34;_blank&#34;&gt;restic&lt;/a&gt; or &lt;a href=&#34;https://borgbackup.readthedocs.io/en/stable/&#34; target=&#34;_blank&#34;&gt;borg&lt;/a&gt; backup the data encrypted by default. Moreover they support to upload the backup directly to services like &lt;a href=&#34;https://www.backblaze.com/de_DE/&#34; target=&#34;_blank&#34;&gt;Backblaze&lt;/a&gt;, &lt;a href=&#34;https://aws.amazon.com/de/s3/&#34; target=&#34;_blank&#34;&gt;Amazon S3 Glacier&lt;/a&gt; or &lt;a href=&#34;https://rsync.net/&#34; target=&#34;_blank&#34;&gt;rsync.net&lt;/a&gt; via their native APIs.&lt;/p&gt;
&lt;p&gt;Encrypting your backup data and using an external service requires you to memorize some credentials. Those credentials are required to access your data at the external service itself, and you need credentials to decrypt your backup. Todays best practice is to use a password manager to use completly random passwords for every service. As discussed earlier, an offsite backup protects your data from a total loss of your home. In this case it is very likely that you not only use your house but also all of your personal computing devices. Therefore you must be able to restore your offsite backup without any of your personal computing devices in your home. If you use a hardware token to access your password manager – as a service or an offline password manager like keepass – you should have a backup hardware token stored somewhere outside of your home. Hint: Storing the hardware token in the garage instead of your home, may not be the best idea. Disasters like fire, earthquake and floods are not limited to your home. Storing the credentials to your backup somewhere else introduce a conflict with your OpSec. This tradeoff can only made by yourself. If you manage the backup for multiple members of your familie or friends, consider to share the secrets required to restore the backup. Natural disasters threatens not only your data but also your life and thus the capability to decrypt your backup. If you don&amp;rsquo;t want to trust a single person, you can use &lt;a href=&#34;https://de.wikipedia.org/wiki/Shamir%E2%80%99s_Secret_Sharing&#34; target=&#34;_blank&#34;&gt;Shamir&#39;s Secret Sharing&lt;/a&gt; to distribute parts of the secret to trusted persons. The Shamir&amp;rsquo;s Secret Sharing allows the reconstruction of the secret only if a certain number of persons combine their part of the secret. It&amp;rsquo;s like distributing your digital horcruxes.&lt;/p&gt;

&lt;aside class=&#34;notebox&#34; style=&#34;background-color: rgba(138, 218, 255, 0.97); margin: 5px;&#34;&gt;
   &lt;h4 class=&#34;notebox-header&#34; style=&#34;padding-top: 1%;&#34;&gt; &lt;i title=&#34;Twitter&#34; class=&#34;fas fa-info fa-s fa-fw&#34;&gt;&lt;/i&gt; Classify Backups&lt;/h4&gt;
    &lt;div class=&#34;markdown&#34; style=&#34;padding-bottom: 1%; padding-left: 1%; padding-right: 1%;font-size: 0.9em;&#34;&gt;
You must not apply the same backup policies and mechanisms to all of your data. Some data might not be that crucial to lose. For example the media library of music and videos you found during the last years in the internet. Those libraries often contain several terrabytes of data. Most backup services charge a requiring fee based on the size of the backed up data. Hence it might be too expensive to backup these files to a managed service. Moreover, in case of a total loss of your home, the loss of your media library might be a minor loss.
The confidentialility of your data might be different. The pictures of your family should be restorable of every member of your family, but you might have some data personal to yourself. You can split these two classes of data into two different offsite backup archives with different credentials. The credentials to decrypt your family pictures are shared with your family members, but you don&#39;t share the credentials to decrypt your personal data with anybody else.
&lt;/div&gt;
&lt;/aside&gt;
&lt;p&gt;A common proverb around the IT operations community is &amp;ldquo;Nobody wants a backup, everyone wants a restore&amp;rdquo;. Since creating a backup is a dull repeating task, it is best automated. This reduces the likelyhood that you forget – intentionally or not – to create a backup. You should also test to restore your backups. There are many stories like these &lt;a href=&#34;https://about.gitlab.com/blog/2017/02/10/postmortem-of-database-outage-of-january-31/&#34; target=&#34;_blank&#34;&gt;gitlab outtage&lt;/a&gt; around the internet. They had multiple backups automated, by the automation failed. Upon requiring a restore due to human error deleting production data, they found there backups empty. To prevent this, regularly test a restore. This ensures you know how to restore the data, and secondly you know your backup process work. A second major takeaway from that gitlab post mortem is to use different backup mechanism for your offsite and onsite backup. Two different backup mechanism ensure that a bug or configuration error in one of the backup tools only one backup corrupts.&lt;/p&gt;
&lt;p&gt;Data synchronisation services like &lt;a href=&#34;https://www.dropbox.com/&#34; target=&#34;_blank&#34;&gt;Dropbox&lt;/a&gt;, &lt;a href=&#34;https://www.google.de/drive/apps.html&#34; target=&#34;_blank&#34;&gt;Google Drive&lt;/a&gt; or &lt;a href=&#34;https://www.qnap.com/de-de/software/qsync&#34; target=&#34;_blank&#34;&gt;Qsync&lt;/a&gt; are used to synchronise data between multiple devices. Since they replicate the data onto multiple devices, some use them as their backup tool, too. This works perfectly fine if you want to prevent data loss due to a hardware failure. But synchronisation itself can&amp;rsquo;t prevent you from data loss due to human error, software bugs or encrypting trojans. In all those cases your data synchronisation service will replicate the unwanted data change - deletion or encryption - in real time onto every device. You can use them as backup if they support a file version history with a restore functionality. This allows you to restore an old version in case of an unwanted data change. If your data synchronisation tool doesn&amp;rsquo;t support a file version history it is not a proper backup tool.&lt;/p&gt;
&lt;h2 id=&#34;my-implementation&#34;&gt;My Implementation&lt;/h2&gt;
&lt;p&gt;The my &lt;a href=&#34;https://www.journal.petrausch.info/post/2020/05/moving-the-nas/&#34; target=&#34;_blank&#34;&gt;NAS in the basement&lt;/a&gt; is my central data sink. The NAS is backed up daily to a connected external USB harddrive. To create this backup I use the build in QNAP backup tool. Once a day I create a snapshot of the NAS with restic into my &lt;a href=&#34;https://www.backblaze.com/b2/cloud-storage.html&#34; target=&#34;_blank&#34;&gt;Backblaze B2&lt;/a&gt; bucket. The backed up dataset on the NAS is roughly 1 TB in size with a couple of hundred Megabytes added per day. Restic uploads only the added and changed chunks, hence the daily backup is finished on average after five minutes. The initial backup took 4 days with my 30 Mbit/s upload.
I use resillio sync to sync the pictures taken by our smartphones to my NAS. As argued earlier this synchronisation
itself is not a backup, but I backup the NAS. Hence, all my pictures are backed up automatically. My wife and I use
free Dropbox accounts to share our daily documents like letters or forms. I synchronize my Dropbox account via the
QNAP buildin synchronization tool to the NAS. This synchronized copy is also backed up. To enable me to access my
backup without any of my computing devices I placed a printed and sealed copy of the credentials required to access
the backup at another place. I did this OpSec tradeoff since the backup contains all the pictures of my family. The data
private to myself is stored in encrypted data containers inside the global backup.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Linkdump: CPU alerts and why they are mostly useless</title>
			<link>https://www.journal.petrausch.info/post/2020/12/linkdump/</link>
			<pubDate>Tue, 15 Dec 2020 01:26:57 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/12/linkdump/</guid>
			<description>
			&lt;p&gt;This article from my reading backlogs shows a nice summary why your CPU alerts are mostly useless.
&lt;a href=&#34;https://blog.koehntopp.info/2020/06/08/waffle-house-index-of-tooling.html&#34;&gt;https://blog.koehntopp.info/2020/06/08/waffle-house-index-of-tooling.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I never saw a useful application of CPU alerts. They generate alert noise and increase your alert fatigue since they are mostly unactionable.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Lookup Public IP via Commandline</title>
			<link>https://www.journal.petrausch.info/post/2020/10/public-ip-command-line/</link>
			<pubDate>Wed, 28 Oct 2020 01:26:57 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/10/public-ip-command-line/</guid>
			<description>
			&lt;p&gt;When working from home, I have a changing public IP. My ISP assigns me a new public IP on every router reboot.
For debugging I often have to know my current public IP. There are many websites you can visit and they will show you your
public IP and advertisements.&lt;/p&gt;
&lt;p&gt;To look it up from command line without advertisements or from a script, there are two main mechanism.
First there are REST services answering your request with the IP they see as client IP, secondly there are some DNS resolver
answering with the observed client IP if you query certain DNS records. In general the REST based service responses are easier
to parse since the answer is machine-readable. It&amp;rsquo;s very easy to parse the JSON output with &lt;code&gt;jq&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;rest&#34;&gt;REST&lt;/h2&gt;
&lt;p&gt;Many REST services show more metadata they know about your IP. Mostly it is location data. This location data is very
inaccurate.
The most extensive response is from the &lt;a href=&#34;https://ipdata.co&#34; target=&#34;_blank&#34;&gt;ipdata.co&lt;/a&gt; IP. Using this API in a script may be a bad idea, since the API is rate limited.
You can increase your rate limits by buying on of their plans.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;42
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;45
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;46
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;47
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;48
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;49
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;50
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;51
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;52
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;53
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;54
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;55
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;56
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;57
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;58
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;59
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;60
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;61
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;62
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;curl https://api.ipdata.co?api-key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;test

&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;88.71.116.156&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_eu&amp;#34;&lt;/span&gt;: true,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;city&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Neuburg&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;region&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Rheinland-Pfalz&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;region_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;RP&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;country_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Germany&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;country_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;continent_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Europe&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;continent_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EU&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;latitude&amp;#34;&lt;/span&gt;: 48.9821,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;longitude&amp;#34;&lt;/span&gt;: 8.25,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;postal&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;76776&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;calling_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;49&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://ipdata.co/flags/de.png&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;emoji_flag&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\ud83c\udde9\ud83c\uddea&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;emoji_unicode&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;U+1F1E9 U+1F1EA&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;asn&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;asn&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AS3209&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Vodafone GmbH&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;domain&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vodafone.de&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;route&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;88.64.0.0/12&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;isp&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;carrier&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Vodafone&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mcc&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;262&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mnc&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;02&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;languages&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;German&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;native&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Deutsch&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;currency&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Euro&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EUR&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;symbol&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\u20ac&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;native&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\u20ac&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;plural&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;euros&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;time_zone&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Europe/Berlin&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abbr&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CET&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;+0100&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_dst&amp;#34;&lt;/span&gt;: false,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;current_time&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2020-10-28T20:51:58.377385+01:00&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;threat&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_tor&amp;#34;&lt;/span&gt;: false,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_proxy&amp;#34;&lt;/span&gt;: false,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_anonymous&amp;#34;&lt;/span&gt;: false,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_known_attacker&amp;#34;&lt;/span&gt;: false,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_known_abuser&amp;#34;&lt;/span&gt;: false,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_threat&amp;#34;&lt;/span&gt;: false,
        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;is_bogon&amp;#34;&lt;/span&gt;: false
    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;count&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1561&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The API of &lt;a href=&#34;https://ipinfo.io&#34; target=&#34;_blank&#34;&gt;ipinfo.io&lt;/a&gt; is less extensive but I think they have no rate limit. As you can see from the
example responses of &lt;a href=&#34;https://ipinfo.io&#34; target=&#34;_blank&#34;&gt;ipinfo.io&lt;/a&gt; and &lt;a href=&#34;https://ipdata.co&#34; target=&#34;_blank&#34;&gt;ipdata.co&lt;/a&gt;, the location data is very inaccurate.
Both location responses are in a 130km radius around my actual location.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;curl http://ipinfo.io                  
&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;88.71.116.156&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hostname&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dslb-088-071-116-156.088.071.pools.vodafone-ip.de&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;city&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Schuttertal&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;region&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Baden-Württemberg&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;country&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;loc&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;48.2667,7.9500&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AS3209 Vodafone GmbH&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;postal&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;77978&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;timezone&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Europe/Berlin&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;readme&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://ipinfo.io/missingauth&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;%                                   
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;dns&#34;&gt;DNS&lt;/h2&gt;
&lt;p&gt;The DNS based services are only returning the IP. One service is the google DNS:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{ print $2}&amp;#39;&lt;/span&gt;
88.71.116.156
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;OpenDNS also provide such a DNS name:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;dig +short myip.opendns.com @resolver1.opendns.com
88.71.116.156
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
			</description>
		</item>
		<item>
			<title>The Non-Obvious properties of JSON Encoder.Encode directly to http.ResponseWriter</title>
			<link>https://www.journal.petrausch.info/post/2020/06/golang-json-encoder-http-response-writer/</link>
			<pubDate>Sun, 07 Jun 2020 01:26:57 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/06/golang-json-encoder-http-response-writer/</guid>
			<description>
			&lt;p&gt;Today I came across the following code snipped in a golang HTTP handler:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt;(
	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;encoding/json&amp;#34;&lt;/span&gt;
	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;
	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
)

&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;handler&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ResponseWriter&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Request&lt;/span&gt;) {
	&lt;span style=&#34;color:#75715e&#34;&gt;// [... handler code...]
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;json&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewEncoder&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Encode&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;myApplicationResponse&lt;/span&gt;); &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
		&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;could not marshal the response: %v\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
		&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WriteHeader&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;StatusInternalServerError&lt;/span&gt;)
		&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;My first reaction was that this does not work as indented. The documentation of the ResponseWriter states the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If WriteHeader is not called explicitly, the first call to Write
will trigger an implicit WriteHeader(http.StatusOK).
Thus explicit calls to WriteHeader are mainly used to
send error codes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I thought that the Encoder will write to the given &lt;code&gt;io.Writer&lt;/code&gt; while encoding the JSON. So this combined with the &lt;code&gt;w.WriteHeader(http.StatusInternalServerError)&lt;/code&gt; in case of an error will cause a superfluous WriteHeader call, since the encoding called already &lt;code&gt;w.Write()&lt;/code&gt; and thus setting the response code to 200. The superfluous WriterHeader call will be &lt;a href=&#34;https://github.com/golang/go/blob/release-branch.go1.14/src/net/http/server.go#L1115-L1125&#34; target=&#34;_blank&#34;&gt;ignored&lt;/a&gt;. This is logicall, since the body is send to the client after the HTTP header. The status code is part of the header. Hence the status code must be written before the first body byte. The &lt;code&gt;ReponseWriter&lt;/code&gt; streams the body to the client while the application HTTP handler is still running.&lt;/p&gt;
&lt;p&gt;After digging into the Encoder code I learned that the JSON is encoded into a &lt;a href=&#34;https://github.com/golang/go/blob/release-branch.go1.14/src/encoding/json/stream.go#L205-L209&#34; target=&#34;_blank&#34;&gt;temporary buffer&lt;/a&gt; and after that copied to the given &lt;code&gt;io.Writer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I have three tackaways of this. First of all, the given code works as intented. It sets the status code 503 if the encoding fails. Secondly, the current behaviour (encode complete, than write) is not documented. It might change in the future. Hence the above snipped may not work as intended in the future. This post is written as of Golang 1.14.&lt;/p&gt;
&lt;p&gt;The third takeaway is that &lt;code&gt;Encoder.Encode&lt;/code&gt; can allocate alot of memory. For example, your JSON struct has a encoded size of 1MB and your application serves 1000 Requests/s. The memory consumption of the temporary encoding buffers alone is roughly 1 GB.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Managing Kubernetes Ingress JSON Log Format with Sanity</title>
			<link>https://www.journal.petrausch.info/post/2020/05/managing-kubernetes-ingress-json-log-format-with-sanity/</link>
			<pubDate>Sat, 30 May 2020 22:02:37 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/managing-kubernetes-ingress-json-log-format-with-sanity/</guid>
			<description>
			&lt;p&gt;The nginx ingress supports a custom log format. The option can be set via the &lt;code&gt;log_format&lt;/code&gt; field in the &lt;a href=&#34;https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/log-format/&#34; target=&#34;_blank&#34;&gt;ingress configmap&lt;/a&gt;.
As you can see, the log format must be a single line. I wanted to implement the &lt;a href=&#34;https://www.elastic.co/guide/en/ecs/current/ecs-using-ecs.html&#34; target=&#34;_blank&#34;&gt;Elasticsearch Common Schema&lt;/a&gt;
for our nginx ingress access log. Writing the ECS JSON for our access log results in:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;{
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$time_iso8601&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;network&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;forwarded_ip&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$http_x_forwarded_for&amp;#34;&lt;/span&gt;},
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$remote_user&amp;#34;&lt;/span&gt;},
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;user_agent&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;original&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$http_user_agent&amp;#34;&lt;/span&gt;},
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;:{
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$server_protocol&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;request&amp;#34;&lt;/span&gt;:{
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$body_bytes_sent&lt;/span&gt;},
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$request_length&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;method&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$request_method&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;referrer&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$http_referer&amp;#34;&lt;/span&gt;
    },
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response&amp;#34;&lt;/span&gt;:{
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$body_bytes_sent&lt;/span&gt;},
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$bytes_sent&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;status_code&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$status&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$request_time&lt;/span&gt;
    },
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;upstream&amp;#34;&lt;/span&gt;: {
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$upstream_response_length&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;status_code&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$upstream_status&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$upstream_response_time&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;address&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$upstream_addr&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$proxy_upstream_name&amp;#34;&lt;/span&gt;
    }
  },
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;:{
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;domain&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$host&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$uri&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$args&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;original&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$request_uri&amp;#34;&lt;/span&gt;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This 34 lines of JSON must be condensed to one line. Doing this manually is error prone. Moreover, maintaining this JSON
struct in one line is nearly impossible. Since we manage the deployment of our ingress in a helm chart, I used the
&lt;a href=&#34;http://masterminds.github.io/sprig/strings.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;nospace&lt;/code&gt;&lt;/a&gt; sprig function. This function removes every whitespace from the input string.
Be aware, this approach works only if your JSON struct contains no whitespace. The whitespaces from your JSON key and values
will be stripped as well.&lt;/p&gt;
&lt;p&gt;I saved the JSON struct to the file &lt;code&gt;config/logpattern.json&lt;/code&gt; in the helm chart.
My &lt;code&gt;templates/configmap.yml&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;kind&lt;/span&gt;: ConfigMap
&lt;span style=&#34;color:#66d9ef&#34;&gt;apiVersion&lt;/span&gt;: v1
&lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: nginx-configuration
  &lt;span style=&#34;color:#66d9ef&#34;&gt;namespace&lt;/span&gt;: ingress
  &lt;span style=&#34;color:#66d9ef&#34;&gt;labels&lt;/span&gt;:
    &lt;span style=&#34;color:#66d9ef&#34;&gt;app.kubernetes.io/name&lt;/span&gt;: ingress
&lt;span style=&#34;color:#66d9ef&#34;&gt;data&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;log-format-escape-json&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#66d9ef&#34;&gt;log-format-upstream&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{ .Files.Get &amp;#34;config/logpattern.json&amp;#34; | nospace }}&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;.Files.Get&lt;/code&gt; loads the JSON log pattern from the log pattern file and pipes that into the &lt;code&gt;nospace&lt;/code&gt; function.
This results in the following rendered configmap:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;kind&lt;/span&gt;: ConfigMap
&lt;span style=&#34;color:#66d9ef&#34;&gt;apiVersion&lt;/span&gt;: v1
&lt;span style=&#34;color:#66d9ef&#34;&gt;metadata&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;name&lt;/span&gt;: nginx-configuration
  &lt;span style=&#34;color:#66d9ef&#34;&gt;namespace&lt;/span&gt;: ingress
  &lt;span style=&#34;color:#66d9ef&#34;&gt;labels&lt;/span&gt;:
    &lt;span style=&#34;color:#66d9ef&#34;&gt;app.kubernetes.io/name&lt;/span&gt;: ingress
&lt;span style=&#34;color:#66d9ef&#34;&gt;data&lt;/span&gt;:
  &lt;span style=&#34;color:#66d9ef&#34;&gt;log-format-escape-json&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#66d9ef&#34;&gt;log-format-upstream&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{&amp;#34;network&amp;#34;:{&amp;#34;forwarded_ip&amp;#34;:&amp;#34;$http_x_forwarded_for&amp;#34;},&amp;#34;user&amp;#34;:{&amp;#34;name&amp;#34;:&amp;#34;$remote_user&amp;#34;},&amp;#34;user_agent&amp;#34;:{&amp;#34;original&amp;#34;:&amp;#34;$http_user_agent&amp;#34;},&amp;#34;http&amp;#34;:{&amp;#34;version&amp;#34;:&amp;#34;$server_protocol&amp;#34;,&amp;#34;request&amp;#34;:{&amp;#34;body&amp;#34;:{&amp;#34;bytes&amp;#34;:$body_bytes_sent},&amp;#34;bytes&amp;#34;:$request_length,&amp;#34;method&amp;#34;:&amp;#34;$request_method&amp;#34;,&amp;#34;referrer&amp;#34;:&amp;#34;$http_referer&amp;#34;},&amp;#34;response&amp;#34;:{&amp;#34;body&amp;#34;:{&amp;#34;bytes&amp;#34;:$body_bytes_sent},&amp;#34;bytes&amp;#34;:$bytes_sent,&amp;#34;status_code&amp;#34;:&amp;#34;$status&amp;#34;,&amp;#34;time&amp;#34;:$request_time}},&amp;#34;url&amp;#34;:{&amp;#34;domain&amp;#34;:&amp;#34;$host&amp;#34;,&amp;#34;path&amp;#34;:&amp;#34;$uri&amp;#34;,&amp;#34;query&amp;#34;:&amp;#34;$args&amp;#34;,&amp;#34;original&amp;#34;:&amp;#34;$request_uri&amp;#34;,&amp;#34;foo&amp;#34;:&amp;#34;bar&amp;#34;}}&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Chart directory layout:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;.
├── Chart.yaml
├── config
│   └── logpattern.json
├── templates
│   ├── configmap.yml
│   ├── ....
....
│   └── ....
└── values.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
			</description>
		</item>
		<item>
			<title>Moving the NAS</title>
			<link>https://www.journal.petrausch.info/post/2020/05/moving-the-nas/</link>
			<pubDate>Wed, 27 May 2020 22:32:43 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/moving-the-nas/</guid>
			<description>
			&lt;p&gt;I had to move my NAS into the basement. There is no room in our flat left for noisy computer equipment.
My flat is in the first floor. I have no chance to build a wired ethernet connection into the basement.
So I had to build up a wireless connection into the basement. The current setup is drawed in the following pictures:
&lt;figure&gt;
  &lt;img src=&#34;https://www.journal.petrausch.info/images/nas-location.jpg&#34; alt=&#34;NAS Setup&#34;  /&gt;
&lt;/figure&gt;
The settings of the OpenWRT Router are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hardware: TP-Link Archer AC1750 C7 v5&lt;/li&gt;
&lt;li&gt;Software: OpenWrt 19.07.3 r11063-85e04e9f46&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My first approach was to just bridge a WiFi interface of the router to the ethernet ports.
However, I &lt;a href=&#34;https://oldwiki.archive.openwrt.org/doc/howto/clientmode#bridged_client_mode_issues&#34; target=&#34;_blank&#34;&gt;learned&lt;/a&gt;, that bridging
between WiFi and ethernet is not that simple. The root cause is a missing source MAC address in the 802.11 standard. The best solution to
this problem is using WDS. This switches WiFi to a four MAC address mode. The details are in the linked article. I didn&amp;rsquo;t
get WDS working. Therefore I used &lt;a href=&#34;https://openwrt.org/docs/guide-user/network/wifi/relay_configuration&#34; target=&#34;_blank&#34;&gt;relayd&lt;/a&gt; as
workaround. I followed the setup in the linked article. Relayd has some drawbacks. Relayd does not support IPv6. Furthermore it does Layer 3 things to emulate Layer 2
connectivity.&lt;/p&gt;
&lt;p&gt;I have a static route (&lt;code&gt;192.168.88.0/24&lt;/code&gt;) installed on my NAS to route traffic for my VPN to my raspberry Pi. After the initial relayd setup
I was unable to connect from my VPN to the NAS. Connecting to the NAS from any device in my home network to the NAS worked.
Including the raspberry Pi terminating the VPN. I tracerouted a target in the VPN from the NAS. Packets for the VPN host
where routed by my easybox into the network of my ISP.
&lt;figure&gt;
  &lt;img src=&#34;https://www.journal.petrausch.info/images/nas-traceroute.png&#34; alt=&#34;traceroute&#34;  /&gt;
&lt;/figure&gt;
After some debugging (tcpdump yeah!) I found that my NAS did a correct nexthop and ARP lookup. It set the raspberry Pis MAC address as target.
However, the relayd on the OpenWRT router redoes the nexthop and ARP lookup on relaying the packets.
Installing the static route on the OpenWRTs main routing table solved the problem. To be sure I installed the route on both the relayd interface, and the WiFi uplink interface. After this the NAS was able to connect to hosts
in the VPN.&lt;/p&gt;
&lt;p&gt;This &lt;a href=&#34;https://twitter.com/hikhvar/status/1264637530504335363&#34; target=&#34;_blank&#34;&gt;twitter thread&lt;/a&gt; documents my debugging rants in German.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;tl;dr&lt;/h2&gt;
&lt;p&gt;relayd resets the nexthop. If a host behind your relayd has static routes, you must have that route on the
OpenWRT in the main routing table.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>Set Default Value of Prometheus Label if not set</title>
			<link>https://www.journal.petrausch.info/post/2020/05/prometheus-relabeling-if-not-set/</link>
			<pubDate>Wed, 13 May 2020 08:37:21 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/prometheus-relabeling-if-not-set/</guid>
			<description>
			&lt;p&gt;I had to implement the following behaviour in a prometheus relabel config:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given two labels A and B. I want to set A to the value of label B, if and only if A is empty/not-set.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;First I tried to find a proper action in the prometheus &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config&#34; target=&#34;_blank&#34;&gt;relabel_config&lt;/a&gt;,
but I did not find any. Luckily the &lt;code&gt;replace&lt;/code&gt; action only replaces the target label
if the given regex matches. Therefore, the following relabel config has the wanted property:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;- &lt;span style=&#34;color:#66d9ef&#34;&gt;source_labels&lt;/span&gt;: [A, B]
  &lt;span style=&#34;color:#66d9ef&#34;&gt;action&lt;/span&gt;: replace
  &lt;span style=&#34;color:#66d9ef&#34;&gt;separator&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;;&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#66d9ef&#34;&gt;regex&lt;/span&gt;: ;(.&lt;span style=&#34;color:#75715e&#34;&gt;*)&lt;/span&gt;
  &lt;span style=&#34;color:#66d9ef&#34;&gt;replacement&lt;/span&gt;: $&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
  &lt;span style=&#34;color:#66d9ef&#34;&gt;target_label&lt;/span&gt;: A
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It works because the values of the &lt;code&gt;source_labels&lt;/code&gt; are joined by the &lt;code&gt;separator&lt;/code&gt;. After
concatenating the two values, the regex is matched against the concatenated values. The regex above,
only matches if &lt;code&gt;A&lt;/code&gt; is empty. The value of &lt;code&gt;B&lt;/code&gt; will be matched by the first and only group reference.
Hence &lt;code&gt;replace&lt;/code&gt; only replaces the value of label &lt;code&gt;A&lt;/code&gt; if it is empty.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>On Errors in Golang</title>
			<link>https://www.journal.petrausch.info/post/2020/05/must-pattern/</link>
			<pubDate>Mon, 11 May 2020 21:37:21 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/must-pattern/</guid>
			<description>
			&lt;p&gt;In Golang are two ways to signal an error in a function or method. The first is the convention to return an &lt;code&gt;error&lt;/code&gt; value
as last return parameter of a function or method. The position of the return parameter is only a convention, but I&amp;rsquo;m not
aware of any library not using this convention. The &lt;code&gt;error&lt;/code&gt; type is a &lt;a href=&#34;https://golang.org/ref/spec#Errors&#34; target=&#34;_blank&#34;&gt;builtin interface&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The second way to signal an error is raising a panic. A panic have to be catched via the &lt;code&gt;recover&lt;/code&gt; method  in a defer block
in the call stack. If the panic is not catched it will crash the program. This sounds like exceptions in languages like Java,
but panics should only be used if there is something unexpected and non-recoverable. In general, panics should only be
recovered to post them services like &lt;a href=&#34;https://sentry.io&#34; target=&#34;_blank&#34;&gt;sentry.io&lt;/a&gt;. After delivering the panic to your observability stack,
the program should be terminated. This &lt;a href=&#34;https://blog.golang.org/defer-panic-and-recover&#34; target=&#34;_blank&#34;&gt;blog post&lt;/a&gt; goes into the details
of panics, defer and recover.&lt;/p&gt;
&lt;p&gt;As described in the first paragraph, the convention is to return an error if the function can return an error. Since it is
a good practice to check every error go code has a lot of &lt;code&gt;if err != nil&lt;/code&gt; statements. There are a lot of people out there
hating that pattern. I got used to it. Now it shapes my way of thinking. Before doing anything with the return value of
function I think about the error cases. What should the code do in case of an error? Abort? Does the code have to clean up
any resources? Rollback any transaction? Can the code recover safely from the error? Yes this distracts from the core
business logic in the first place, but I think it leads overall to a more robust code.&lt;/p&gt;
&lt;h2 id=&#34;the-must-pattern&#34;&gt;The Must Pattern&lt;/h2&gt;
&lt;p&gt;However, always checking for that possible error can be annoying in cases where the function returns an error, but I know
at time of programming there will never be an error. Or, if there is an error, some fundamental assumptions broke.
A good example is the &lt;a href=&#34;https://golang.org/pkg/regexp/#Compile&#34; target=&#34;_blank&#34;&gt;Compile&lt;/a&gt; function from the &lt;code&gt;regexp&lt;/code&gt; package. This function
has the following signature:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Compile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Regexp&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The function tries to compile the given string as regular expression. If the string is not a valid regular expression an
error is returned. So far, the usual method signature. There is a possible error, hence return error. In the following example, the error check is never true, since I know in advance that the static expression is always a
valid expression.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;regexp&amp;#34;&lt;/span&gt;
)

&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
    &lt;span style=&#34;color:#a6e22e&#34;&gt;exp&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;foo.*&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; []byte(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;foobar&amp;#34;&lt;/span&gt;)
    &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;regexp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Compile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;exp&lt;/span&gt;)
    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
        &lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatal&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Failed to compile expression&amp;#34;&lt;/span&gt;)
    }
    &lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%v matched: %v&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Match&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;regexp&lt;/code&gt; package provides us a handy wrapper around &lt;code&gt;Compile&lt;/code&gt;. It is called &lt;code&gt;MustCompile&lt;/code&gt; and returns only a &lt;code&gt;*Regexp&lt;/code&gt;.
If &lt;code&gt;Compile&lt;/code&gt; returns an error not equals nil, &lt;code&gt;MustCompile&lt;/code&gt; panics. This reduces the above code to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;regexp&amp;#34;&lt;/span&gt;
)

&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
    &lt;span style=&#34;color:#a6e22e&#34;&gt;exp&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;foo.*&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; []byte(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;foobar&amp;#34;&lt;/span&gt;)
    &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;regexp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;MustCompile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;exp&lt;/span&gt;)
    &lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%v matched: %v&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Match&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Personally I use &lt;code&gt;MustCompile&lt;/code&gt; only if I know the regular expression at compile time. If my program fails to parse the
regular expression, something fundamental in the &lt;code&gt;regexp&lt;/code&gt; library has changed. If it depends on user input you should
never use &lt;code&gt;MustCompile&lt;/code&gt; since the user may mess up your regular expression.&lt;/p&gt;
&lt;p&gt;There are other packages providing a methods and function with a &lt;code&gt;Must&lt;/code&gt; prefix. E.g. &lt;a href=&#34;https://godoc.org/github.com/prometheus/client_golang/prometheus#MustRegister&#34; target=&#34;_blank&#34;&gt;MustRegister&lt;/a&gt;
from the prometheus client library, or &lt;a href=&#34;https://godoc.org/github.com/google/uuid#MustParse&#34; target=&#34;_blank&#34;&gt;MustParse&lt;/a&gt; from the &lt;code&gt;uuid&lt;/code&gt; package.
All those functions panic instead of returning an error. All those functions should only be used if you know for sure an
error can&amp;rsquo;t happen. Vice versa, the &lt;code&gt;Must&lt;/code&gt; prefix of a function indicates the user of your package that your function will
panic on error. I made it a rule of thumb for myself to prefix every function with &lt;code&gt;Must&lt;/code&gt; if I implement a panic in that
function.&lt;/p&gt;
&lt;p&gt;If your package API has many functions returning the same type, and an error you can copy the &lt;code&gt;Must&lt;/code&gt;-wrapper pattern
from the template package. This &lt;a href=&#34;https://golang.org/pkg/text/template/#Must&#34; target=&#34;_blank&#34;&gt;wrapper&lt;/a&gt; has the following signature:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Must&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Template&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Template&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It accepts a Template and an error. In case &lt;code&gt;err!=nil&lt;/code&gt; it will panic. The example for this function shows a lesser known
feature of golang. Example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;template&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Must&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;template&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;New&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Parse&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;template.New(&amp;quot;name&amp;quot;)&lt;/code&gt; returns a &lt;code&gt;Template&lt;/code&gt; and an error. Since &lt;code&gt;Must&lt;/code&gt; accept exactly those two arguments, you can just
pass the output of &lt;code&gt;template.New&lt;/code&gt; into &lt;code&gt;Must&lt;/code&gt;. This saves a lot of &lt;code&gt;Must&lt;/code&gt; prefixed functions in the API of the template
package. Sadly, the following example will not compile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (
	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
)

&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sub&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; {
	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;
}

&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; {
	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;c&lt;/span&gt;
}

&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
	&lt;span style=&#34;color:#a6e22e&#34;&gt;res&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;sub&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;), &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;)
	&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;(1-2)+3=%d\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;res&lt;/span&gt;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The error message is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;./prog.go:16:12: not enough arguments in call to add
	have (int, number)
	want (int, int, int)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you want to pass multiple return values of a function directly into another function, the receiving function must have
exactly the same input values.&lt;/p&gt;
&lt;p&gt;In conclusion, use the prefix &lt;code&gt;Must&lt;/code&gt; if your method or function panics. Be careful if an API provides a &lt;code&gt;Must&lt;/code&gt; function.
Expect that function to panic.&lt;/p&gt;

			</description>
		</item>
		<item>
			<title>On Using Fluentd to Parse Elastic Common Scheme from Kubernetes Pod Logs</title>
			<link>https://www.journal.petrausch.info/post/2020/05/fluentd-ruby-merge/</link>
			<pubDate>Fri, 08 May 2020 21:39:47 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/fluentd-ruby-merge/</guid>
			<description>
			&lt;p&gt;Today I had to parse the JSON logs of our containers in Kubernetes. Our application are logging in the
&lt;a href=&#34;https://www.elastic.co/guide/en/ecs/current/ecs-using-ecs.html&#34; target=&#34;_blank&#34;&gt;Elastic Common Scheme&lt;/a&gt; format to STDOUT.
This format is a JSON object with well-defined fields per log line.
We use a fluentd daemonset to read the container logs from the nodes. The outputs of STDOUT and STDERR are saved in
&lt;code&gt;/var/log/containers&lt;/code&gt; on the nodes by the docker daemon. This setup is very common in the Kubernetes environment. The official &lt;a href=&#34;https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsearch&#34; target=&#34;_blank&#34;&gt;fluend-elasticsearch&lt;/a&gt; addon uses the same approach.
In this article I will show the problems I encountered while parsing these logs.&lt;/p&gt;
&lt;p&gt;The fluentd input to read the container logs is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
    @type tail
    @id in_tail_container_logs
    path &amp;#34;/var/log/containers/*.log&amp;#34;
    pos_file &amp;#34;/var/log/fluentd-containers.log.pos&amp;#34;
    tag &amp;#34;kubernetes.*&amp;#34;
    read_from_head true
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;parse&amp;gt;&lt;/span&gt;
      @type &amp;#34;json&amp;#34;
      time_format &amp;#34;%Y-%m-%dT%H:%M:%S.%NZ&amp;#34;
      time_type string
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/parse&amp;gt;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;As you can see in the above snippet the input parses the container logs as JSON via the fluentd &lt;a href=&#34;https://docs.fluentd.org/parser/json&#34; target=&#34;_blank&#34;&gt;JSON parser&lt;/a&gt;.
The format of the container log files is the docker default &lt;code&gt;json-file&lt;/code&gt; (&lt;a href=&#34;https://docs.docker.com/config/containers/logging/json-file/&#34; target=&#34;_blank&#34;&gt;details&lt;/a&gt;).
If the container prints the string &lt;code&gt;this is a log line\n&lt;/code&gt; to STDOUT, the docker daemon saves the following line to the container log file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;this is a log line\n&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2019-01-01T11:11:11.111111111Z&amp;#34;&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After passing the fluentd input, the fluentd event has exact three fields. &lt;code&gt;log&lt;/code&gt;, &lt;code&gt;stream&lt;/code&gt; and the timestamp.&lt;/p&gt;
&lt;p&gt;Since our container are logging JSON to STDOUT, the lines in the container logs looks like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{\&amp;#34;message\&amp;#34;:\&amp;#34;this is a log line\&amp;#34;, \&amp;#34;log\&amp;#34;:{\&amp;#34;level\&amp;#34;:\&amp;#34;info\&amp;#34;}}&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2019-01-01T11:11:11.111111111Z&amp;#34;&lt;/span&gt;}

&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is where the problems start. We told the input to parse every line has JSON. The resulting fluentd event looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;{
  log &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{&amp;#34;&lt;/span&gt;message&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;this is a log line&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;log&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;:{&amp;#34;&lt;/span&gt;level&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;info&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;}}&amp;#34;&lt;/span&gt;,
  stream &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; stdout,
  time &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2019-01-01T11:11:11.111111111Z&amp;#34;&lt;/span&gt;,
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The fluentd JSON parser can not parse the output of our application as JSON since the docker daemon escaped the JSON in
the log string. To solve this I used a filter with a JSON parser:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;**&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
  @type parser
  key_name &amp;#34;log&amp;#34;
  reserve_data true
  reserve_time true
  hash_value_field &amp;#34;parsed&amp;#34;
  remove_key_name_field true
  replace_invalid_sequence true
  emit_invalid_record_to_error false
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;parse&amp;gt;&lt;/span&gt;
    @type &amp;#34;json&amp;#34;
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/parse&amp;gt;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After our fluentd event passed this filter it looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;{
    {
      parsed &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
        message &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;this is a log line&amp;#34;&lt;/span&gt;,
        log &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
           level &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;info&amp;#34;&lt;/span&gt;
        },
      },
      stream &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; stdout,
      time &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2019-01-01T11:11:11.111111111Z&amp;#34;&lt;/span&gt;,
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The parser removes the original log line from the event since we set the option &lt;code&gt;remove_key_name_field&lt;/code&gt;. We also tell the
JSON parser to keep all data, and the already parsed timestamp via the options &lt;code&gt;reserve_time&lt;/code&gt; and &lt;code&gt;reserve_data&lt;/code&gt;.
Some applications in the cluster are not logging in JSON format. Therefore, we set the option &lt;code&gt;emit_invalid_record_to_error&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;.
Without that setting, every non-JSON log line get the &lt;code&gt;@ERROR&lt;/code&gt; label and require special treatment by other filters.&lt;/p&gt;
&lt;p&gt;The ECS logging scheme does not have a field &lt;code&gt;parsed&lt;/code&gt;. Moreover, the field &lt;code&gt;message&lt;/code&gt; is at the top-level of the object.
To mutate records, fluentd has the &lt;code&gt;record_transformer&lt;/code&gt; filter. This filter can set event field values to values of other fields,
but can&amp;rsquo;t copy the content of the field &lt;code&gt;parsed&lt;/code&gt; to the top-level of the event. This was the hardest problem I encountered.
After some googling I found the filter &lt;a href=&#34;https://github.com/repeatedly/fluent-plugin-record-modifier&#34; target=&#34;_blank&#34;&gt;record_modifier&lt;/a&gt;.
I applied the trick shown in the &lt;code&gt;record_modifier&lt;/code&gt; &lt;a href=&#34;https://github.com/repeatedly/fluent-plugin-record-modifier#ruby-code-trick-for-complex-logic&#34; target=&#34;_blank&#34;&gt;README&lt;/a&gt; to implement complex logic in ruby.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;**&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
  @type record_modifier
  remove_keys _dummy_,parsed
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;record&amp;gt;&lt;/span&gt;
    _dummy_ ${record.merge!(record[&amp;#34;parsed&amp;#34;])}
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;We set the field &lt;code&gt;_dummy_&lt;/code&gt; to the result of the ruby expression &lt;code&gt;${record.merge!(record[&amp;quot;parsed&amp;quot;])}&lt;/code&gt;. The content of our fluentd event
is the hash &lt;code&gt;record&lt;/code&gt;. The function &lt;code&gt;merge!&lt;/code&gt;merges the event in place with the values of the field &lt;code&gt;record[&amp;quot;parsed]&lt;/code&gt;. The result
of the merge is irrelevant. Therefore we drop the field &lt;code&gt;_dummy_&lt;/code&gt; after applying the filter. The filter deletes also the merged
field &lt;code&gt;parsed&lt;/code&gt;.
After applying that filter our event looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;{
    {
        message &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;this is a log line&amp;#34;&lt;/span&gt;,
        log &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
           level &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;info&amp;#34;&lt;/span&gt;
        },
        stream &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; stdout,
        time &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2019-01-01T11:11:11.111111111Z&amp;#34;&lt;/span&gt;,
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This event complies with the &lt;a href=&#34;https://www.elastic.co/guide/en/ecs/current/ecs-using-ecs.html&#34; target=&#34;_blank&#34;&gt;Elastic Common Scheme&lt;/a&gt;.
The final fluentd configuration is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;42
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
    @type tail
    @id in_tail_container_logs
    path &amp;#34;/var/log/containers/*.log&amp;#34;
    pos_file &amp;#34;/var/log/fluentd-containers.log.pos&amp;#34;
    tag &amp;#34;kubernetes.*&amp;#34;
    read_from_head true
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;parse&amp;gt;&lt;/span&gt;
      @type &amp;#34;json&amp;#34;
      time_format &amp;#34;%Y-%m-%dT%H:%M:%S.%NZ&amp;#34;
      time_type string
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/parse&amp;gt;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;

  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;**&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
    @type parser
    key_name &amp;#34;log&amp;#34;
    reserve_data true
    reserve_time true
    hash_value_field &amp;#34;parsed&amp;#34;
    remove_key_name_field true
    replace_invalid_sequence true
    emit_invalid_record_to_error false
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;parse&amp;gt;&lt;/span&gt;
      @type &amp;#34;json&amp;#34;
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/parse&amp;gt;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;

  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;filter&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;**&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
    @type record_modifier
    remove_keys _dummy_,parsed
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;record&amp;gt;&lt;/span&gt;
      _dummy_ ${record.merge!(record[&amp;#34;parsed&amp;#34;])}
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;

  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;match&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;my.logs&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
    @type elasticsearch
    host localhost
    port 9200
    logstash_format true
  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/match&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
			</description>
		</item>
		<item>
			<title>Mount Local GOPATH Directory into Container</title>
			<link>https://www.journal.petrausch.info/post/2020/05/gopath/</link>
			<pubDate>Fri, 08 May 2020 01:00:00 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/gopath/</guid>
			<description>
			&lt;p&gt;Given you have an old golang project depending on the &lt;code&gt;GOPATH&lt;/code&gt;. You want to build that project in the golang docker image. This one liner mounts the current directory into the GOPATH of the golang image.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;docker run -it &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;	-w /go/src/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pwd&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;#$GOPATH/src/&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;	-v &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pwd&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;:/go/src/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pwd&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;#$GOPATH/src/&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;	golang:1.10
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;user@host:/home/user/go/src/github.com/hikhvar/zkillbeat &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;git&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;-&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;master&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; % docker run -it &lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;                                                              :&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;
        -w /go/src/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pwd&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;#$GOPATH/src/&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        -v &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pwd&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;:/go/src/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pwd&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;#$GOPATH/src/&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        golang:1.10
root@5c7f5e394b2a:/go/src/github.com/hikhvar/zkillbeat# go build 
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
			</description>
		</item>
		<item>
			<title>Migrate Elasticsearch 5.x to 6.x</title>
			<link>https://www.journal.petrausch.info/post/2020/05/elasticsearch5to6/</link>
			<pubDate>Mon, 04 May 2020 20:40:00 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/elasticsearch5to6/</guid>
			<description>
			&lt;p&gt;We want to migrate an pre 6.0.0 cluster to 6.x.x. Therefore we have to make sure every index contains only one mapping. The following snippets shows how to inspect the indices with default unix tools.&lt;/p&gt;
&lt;p&gt;Required tools:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;cat
jq
curl
mkdir
wc
echo
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To decrease the load on the cluster we download the mappings of every index to &lt;code&gt;/tmp/indices&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;esHost&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://localhost:9200&amp;#34;&lt;/span&gt;
mkdir /tmp/indices
&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i in &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;curl &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;esHost&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/_cat/indices?h=index&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; curl &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;esHost&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;i&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/_mapping&amp;#34;&lt;/span&gt; &amp;gt; /tmp/indices/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;i&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;.json; &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Show the number of mappings for all indices:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i in &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;ls -1 /tmp/indices&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; echo -n $i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;;jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.[].mappings | to_entries[].key&amp;#39;&lt;/span&gt; /tmp/indices/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;i&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; | wc -l; &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Show the names of mappings in an index:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;index&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;index-name&amp;#34;&lt;/span&gt;
cat /tmp/indices/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;index&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;.json | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;.[\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;index&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\&amp;#34;].mappings | to_entries[].key&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
			</description>
		</item>
		<item>
			<title>Initial Commit</title>
			<link>https://www.journal.petrausch.info/post/2020/05/initial/</link>
			<pubDate>Mon, 04 May 2020 20:15:41 +0200</pubDate>
			<guid>https://www.journal.petrausch.info/post/2020/05/initial/</guid>
			<description>
			&lt;p&gt;Initial post to test the theme and all the other stuff.&lt;/p&gt;

			</description>
		</item>
	</channel>
</rss>
