<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ParanoiaSystem</title><link>https://paranoiasystem.com/</link><description>Recent content on ParanoiaSystem</description><generator>Hugo -- 0.154.4</generator><language>en-us</language><lastBuildDate>Fri, 16 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://paranoiasystem.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Reboot</title><link>https://paranoiasystem.com/posts/reboot/</link><pubDate>Fri, 16 Jan 2026 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/posts/reboot/</guid><description>In this article, I share my journey of revamping my personal blog, the challenges I faced, and my commitment to maintaining a consistent writing schedule.</description><content:encoded><![CDATA[<p>Hi there, it has been a long time since I haven&rsquo;t written on my blog. And I was thinking a lot about that, every month I used to think: &ldquo;oh shit.. another month passed and I didn&rsquo;t write anything&rdquo;.</p>
<p>During my summer holidays I decided to give a new look to my blog, I decided to switch to Hugo and move from GitHub Pages to Cloudflare (but considering the latest events I don&rsquo;t know if it&rsquo;s been a good choice…).</p>
<p>So I started to work a lot on it, first because I needed to learn how Hugo works and because in my mind I wanted to enhance it. I started to add my experience page, a page with the few talks I did. I studied how to customize some pages with Hugo partials, I created a dynamic SVG and I optimized for SEO and a lot of other stuff.
Basically I fell into a huge rabbit hole.
gif
<figure class="align-center "><a href="https://tenor.com/view/alice-rabbithole-falling-tumbling-bye-gif-5308157" target="_blank">
    <img loading="lazy" src="https://media1.tenor.com/m/E14SgWRxUoMAAAAC/alice-rabbithole.gif#center"/> </a><figcaption>
            <p>GIF by <a href="https://tenor.com/view/alice-rabbithole-falling-tumbling-bye-gif-5308157">Tenor</a></p>
        </figcaption>
</figure>
</p>
<p>I started to translate my Italian articles to English, because I think it&rsquo;s ugly to have mixed languages on my blog. Not having constant access to my laptop made it really hard and 2 weeks were few (in the meanwhile, like two/three months ago I bought a new laptop… because I&rsquo;m missing x86_64 arch but primarily I wanted to come back to Linux, maybe I can write about that in a future post). Hence I got overwhelmed.</p>
<figure class="align-center "><a href="https://tenor.com/view/relatable-stressed-gif-27439196" target="_blank">
    <img loading="lazy" src="https://media1.tenor.com/m/zIUDHjzgRwgAAAAC/relatable-stressed.gif#center"/> </a><figcaption>
            <p>GIF by <a href="https://tenor.com/view/relatable-stressed-gif-27439196">Tenor</a></p>
        </figcaption>
</figure>

<p>The holidays ended and I wasn&rsquo;t really convinced about the new blog design, and I thought.. I can work on it, in the evening or during the weekends… so if I&rsquo;m writing this post… you should already understand… I didn&rsquo;t touch it. I started to become a little bit frustrated about it… so I understood I needed to declutter.
Consequently I fell into the same rabbit hole… but this time with a very defined goal in my mind: to have the blog fully in English and as minimalistic as possible (fortunately I did some translation during the summer).</p>
<p>So now after this huge intro and this sort of personal retrospective I want to welcome you to my new blog, and I hope you like it. I promise you, I will try to be more productive… and stop procrastinating.</p>
<p>See you soon. Bye.</p>
]]></content:encoded></item><item><title>Centralizzare i Log in ambienti Multi-cluster con Loki: Architettura e Casi d'Uso</title><link>https://paranoiasystem.com/speaking/cndi-2025/</link><pubDate>Tue, 24 Jun 2025 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/speaking/cndi-2025/</guid><description>&lt;p&gt;🎫 Event Name: Cloud Native Days Italy 2025&lt;/p&gt;
&lt;p&gt;📍 Where: Bologna, Italy&lt;/p&gt;
&lt;p&gt;🕛 When: 24 June 2025&lt;/p&gt;
&lt;p&gt;🗣️ Language: ITA 🇮🇹&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In ambienti Kubernetes multi-cluster, correlare eventi e risolvere problemi è complesso: i servizi distribuiti generano enormi volumi di log frammentati tra cluster diversi, mettendo in difficoltà le soluzioni di logging tradizionali sia per prestazioni che per storage.&lt;/p&gt;
&lt;p&gt;Questo talk dimostra come Grafana Loki, una soluzione open source progettata per garantire il pieno controllo sui propri dati, permetta di costruire un sistema di logging centralizzato. Presenterò un caso reale di implementazione in una cluster mesh, evidenziando come la sua architettura basata su etichette e storage distribuito consenta di gestire efficacemente i log.&lt;/p&gt;</description><content:encoded><![CDATA[<p>🎫 Event Name: Cloud Native Days Italy 2025</p>
<p>📍 Where: Bologna, Italy</p>
<p>🕛 When: 24 June 2025</p>
<p>🗣️ Language: ITA 🇮🇹</p>
<hr>
<p>In ambienti Kubernetes multi-cluster, correlare eventi e risolvere problemi è complesso: i servizi distribuiti generano enormi volumi di log frammentati tra cluster diversi, mettendo in difficoltà le soluzioni di logging tradizionali sia per prestazioni che per storage.</p>
<p>Questo talk dimostra come Grafana Loki, una soluzione open source progettata per garantire il pieno controllo sui propri dati, permetta di costruire un sistema di logging centralizzato. Presenterò un caso reale di implementazione in una cluster mesh, evidenziando come la sua architettura basata su etichette e storage distribuito consenta di gestire efficacemente i log.</p>
<p>Durante la sessione verranno mostrate le tecniche di implementazione di Loki in ambiente multi-cluster, i pattern per correlare efficacemente i log tra servizi distribuiti e le strategie di ottimizzazione per gestire grandi volumi di dati, il tutto con un approccio cloud native.</p>
<p><a href="https://cloudnativedaysitaly.org/talk/centralizzare-i-log-in-ambienti-multi-cluster-con-loki-architettura-e-casi-duso">Scopri di più</a></p>
]]></content:encoded></item><item><title>Eleva il tuo codice: guida all'analisi statica con SonarQube</title><link>https://paranoiasystem.com/speaking/thecmmbay-2023-10-19/</link><pubDate>Thu, 19 Oct 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/speaking/thecmmbay-2023-10-19/</guid><description>&lt;p&gt;🎫 Event Name: Eleva il tuo codice: guida all&amp;rsquo;analisi statica con SonarQube&lt;/p&gt;
&lt;p&gt;📍 Where: Online&lt;/p&gt;
&lt;p&gt;🕛 When: 19 October 2023&lt;/p&gt;
&lt;p&gt;🗣️ Language: ITA 🇮🇹&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In un mondo in cui lo sviluppo del software è sempre più veloce e sempre più importante per ogni tipo di business, la qualità del codice e la gestione del debito tecnico sono diventati aspetti essenziali, e SonarQube, piattaforma leader nell&amp;rsquo;analisi statica del codice, di cui useremo la versione gratuita Community Edition durante il talk, rappresenta uno strumento chiave per affrontare queste sfide.&lt;/p&gt;</description><content:encoded><![CDATA[<p>🎫 Event Name: Eleva il tuo codice: guida all&rsquo;analisi statica con SonarQube</p>
<p>📍 Where: Online</p>
<p>🕛 When: 19 October 2023</p>
<p>🗣️ Language: ITA 🇮🇹</p>
<hr>
<p>In un mondo in cui lo sviluppo del software è sempre più veloce e sempre più importante per ogni tipo di business, la qualità del codice e la gestione del debito tecnico sono diventati aspetti essenziali, e SonarQube, piattaforma leader nell&rsquo;analisi statica del codice, di cui useremo la versione gratuita Community Edition durante il talk, rappresenta uno strumento chiave per affrontare queste sfide.</p>
<p>Esploreremo l&rsquo;importanza dell&rsquo;analisi statica del codice, i benefici che ne derivano e come SonarQube si inserisce in questo contesto. Forniremo una panoramica su come questo strumento può essere integrato nel ciclo di vita dello sviluppo del software, con una particolare attenzione su come utilizzarlo al meglio per migliorare la qualità del codice e ridurre il debito tecnico, e mettendo in evidenza i benefici per gli sviluppatori, i team di sviluppo e l&rsquo;intera organizzazione.</p>
<p>Nello specifico, approfondiremo i seguenti argomenti:</p>
<ul>
<li>Cosa è l&rsquo;analisi statica del codice e perché è importante</li>
<li>Come integrare l&rsquo;analisi statica del codice nel ciclo di vita dello sviluppo del software</li>
<li>Introduzione a SonarQube: funzionalità e vantaggi</li>
<li>Esempi pratici di utilizzo di SonarQube in un progetto reale</li>
<li>Best practice per l&rsquo;uso di SonarQube</li>
</ul>
<p><a href="https://thecmmbay.com/eventi/eleva-il-tuo-codice-guida-all-analisi-statica-con-sonarqube-z217w2676ok">Scopri di più</a></p>
]]></content:encoded></item><item><title>From Signing to Trust: Securing Docker Images with Cosign</title><link>https://paranoiasystem.com/posts/docker-cosign/</link><pubDate>Tue, 10 Oct 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/posts/docker-cosign/</guid><description>In this article, we explore how to enhance the security of Docker images using Cosign, a tool from the Sigstore project. We will discuss the importance of signing Docker images, how Cosign works, and provide a practical example of integrating it into a GitHub Action for automated image signing.</description><content:encoded><![CDATA[<p>In the vast and dynamic ecosystem of software development, security is a fundamental pillar that ensures the reliability and integrity of digital products. In particular, with the growing adoption of containers, the need to validate the authenticity and integrity of Docker images has become crucial. This is where <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> comes into play, a tool developed by the <a href="https://www.sigstore.dev/"><strong><em>Sigstore</em></strong></a> project, designed to simplify the signing and verification of Docker images. This practice ensures that the code you are about to deploy is exactly what was intended, free from malicious alterations. In this article, we will dive into the world of <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a>, exploring how it works, how it can be used to sign a Docker image, and why it is an essential element for improving software supply chain security. I will also illustrate a practical example, showing how I integrated <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> into a GitHub pipeline to automate the image signing process. For a detailed view and access to the source code, I invite you to visit my <a href="https://github.com/paranoiasystem/testcosign">GitHub repository</a>.</p>
<hr>
<h2 id="what-is-cosign">What is Cosign?</h2>
<p><a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a>, a tool from the <a href="https://www.sigstore.dev/"><strong><em>Sigstore</em></strong></a> project, was created with the goal of making the signing and verification of Docker images simple and secure. This tool is vital to ensure that the code deployed in production is the exact replica of the original code, free from malicious modifications. With just a few simple commands, <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> democratizes the use of public-key cryptography, making it accessible even to teams with only basic security expertise. Beyond signing and verification, <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> goes further by offering key and signature transparency, making it easier to verify signatures and ensuring that no changes to signed images go unnoticed. This robust functionality makes <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> an indispensable tool in the toolbox of any security-conscious DevOps team, providing a strong line of defense against software supply chain attacks.</p>
<h2 id="why-is-docker-image-signing-useful">Why is Docker Image Signing Useful?</h2>
<p>Signing Docker images is a crucial step toward building a secure software supply chain. This practice raises the barrier against potential threats, ensuring the authenticity and integrity of containers. It acts as a strong verification mechanism, ensuring that the code ready to run or deploy is exactly the original, immune from unauthorized or malicious modifications. Docker image signing is essential for preventing Man-in-the-Middle (MitM) attacks, where attackers might attempt to inject malicious code while images transit over the network. It also aids in audits and compliance, offering an immutable record of signed and verified images, thereby providing full traceability and clear accountability. This is particularly useful in regulated or high-security environments, where traceability and compliance are crucial. With the exponential growth of containerized environments, signing Docker images with <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> has become a key element in maintaining a secure and resilient software supply chain, allowing organizations to operate with greater confidence in the integrity of their systems.</p>
<h2 id="how-does-cosign-work">How Does Cosign Work?</h2>
<p><a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> works by generating a pair of cryptographic keys: a private key to sign Docker images and a public key to verify them. When you sign a Docker image with <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a>, both the image and the signature are stored in a container registry. Later, anyone wishing to verify the image can use the public key to confirm that it was signed with the corresponding private key and has not been altered. <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> can be easily integrated into CI/CD pipelines, enabling automatic signing and verification of images during the deployment process. Additionally, <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> can interface with the <a href="https://www.sigstore.dev/"><strong><em>Sigstore</em></strong></a> registry for even stronger signature transparency, offering a complete solution for managing Docker image security within the software supply chain.</p>
<h2 id="how-to-sign-a-docker-image-with-cosign">How to Sign a Docker Image with Cosign</h2>
<p>In this section, we’ll illustrate how to sign a Docker image with <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a> using a GitHub Action. Before getting started, make sure you have installed the latest version of <a href="https://docs.sigstore.dev/signing/quickstart/"><strong><em>Cosign</em></strong></a>. You can download the binary from GitHub or install it via Homebrew:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew install cosign
</span></span></code></pre></div><p>Then, create a token on GitHub and export it as an environment variable:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export GITHUB_TOKEN<span style="color:#f92672">=</span>&lt;token&gt;
</span></span></code></pre></div><p>Now, generate the keys we will use in the GitHub Action. Thanks to the previously exported token, the <a href="https://docs.sigstore.dev/signing/quickstart/"><em><strong>Cosign</strong></em></a> command will insert the generated keys into the project’s secrets, allowing them to be used in the action:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cosign generate-key-pair github://&lt;owner&gt;/&lt;project&gt;
</span></span></code></pre></div><p>Next, create the GitHub Action. Create a file called <code>docker-publish-and-sign.yml</code> in your project’s <code>.github/workflows</code> directory, and insert the following code:</p>
<script src="https://gist.github.com/paranoiasystem/c43b3bc7f0cd7986832aedc0da96b3ce.js"></script>

<p>This GitHub Action follows a precise sequence of operations to ensure the Docker image is securely built, published, and signed:</p>
<ul>
<li><strong>Checkout</strong>: Retrieves the source code from the GitHub repository.</li>
<li><strong>Set up Docker Buildx</strong>: Prepares the environment for building the image with Docker Buildx.</li>
<li><strong>Install Cosign</strong>: Installs <a href="https://docs.sigstore.dev/signing/quickstart/"><em><strong>Cosign</strong></em></a> in the runtime environment to enable image signing.</li>
<li><strong>Login to GitHub Container Registry</strong>: Logs in to the GitHub Container Registry (GHCR) to publish the Docker image.</li>
<li><strong>Build and Publish</strong>: Builds and publishes the Docker image to GHCR, using the GitHub run ID as the image tag.</li>
<li><strong>Sign the Image</strong>: Signs the Docker image using the private key, and the signature is stored in the registry.</li>
</ul>
<p>To verify the signed image, run the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cosign verify --key &lt;public-key&gt; &lt;image&gt;
</span></span></code></pre></div><h2 id="the-sigstore-project">The Sigstore Project</h2>
<p><a href="https://www.sigstore.dev/"><em><strong>Sigstore</strong></em></a> is an open-source project that aims to raise the bar for supply chain security. Its mission is to provide reliable and transparent tools for signing and verifying software artifacts. <a href="https://docs.sigstore.dev/signing/quickstart/"><em><strong>Cosign</strong></em></a> is one of the solutions offered by <a href="https://www.sigstore.dev/"><em><strong>Sigstore</strong></em></a>, providing a secure and transparent method for signing and verifying Docker images and other artifacts. The <a href="https://www.sigstore.dev/"><em><strong>Sigstore</strong></em></a> initiative, backed by an active and collaborative community, is constantly innovating to make the software supply chain more resilient to attacks and aligned with best security practices.</p>
<h2 id="conclusions">Conclusions</h2>
<p>The integrity of the software supply chain is a fundamental requirement for ensuring security in the modern era of software development. Tools like <a href="https://docs.sigstore.dev/signing/quickstart/"><em><strong>Cosign</strong></em></a>, supported by initiatives like <a href="https://www.sigstore.dev/"><em><strong>Sigstore</strong></em></a>, represent significant steps forward in creating a more robust and secure supply chain, giving DevOps professionals the tools they need to effectively mitigate risks associated with supply chain attacks.</p>
<hr>
<p>If you’ve followed this article to this point, you should now have a clear understanding of how to sign your Docker images and how to verify them. I hope this article has been helpful, and if you have any questions or suggestions, don’t hesitate to <a href="https://www.linkedin.com/in/marcoferraioli93/">contact me</a>.</p>
]]></content:encoded></item><item><title>Kubernetes and containerd: A Perfect Marriage</title><link>https://paranoiasystem.com/posts/k8s-containerd/</link><pubDate>Sat, 12 Aug 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/posts/k8s-containerd/</guid><description>In this article, we explore the integration of Kubernetes with containerd, a lightweight container runtime. We will discuss the benefits of using containerd in a Kubernetes environment and provide a step-by-step guide to setting it up.</description><content:encoded><![CDATA[<blockquote>
<p><strong>The procedure described here is no longer supported. The kubernetes package has changed repository. For more information, please refer to the official <a href="https://kubernetes.io/blog/2023/08/31/legacy-package-repository-deprecation/">documentation</a>.</strong></p>
</blockquote>
<p>In a world where containerization is becoming increasingly central, having a solid understanding of how to configure Kubernetes is essential. In this article, I’ll guide you step by step through installing a Kubernetes cluster using <code>containerd</code> as the runtime.<br>
And if you’re wondering, “Why containerd?”, the answer is simple: it’s lightweight, efficient, and perfectly integrated with Kubernetes.</p>
<hr>
<p>Recently, I received the <a href="https://www.zimaboard.com/">ZimaBoard</a>. Motivated by the excitement of experimenting, I immediately installed Proxmox and created a Kubernetes cluster with containerd as the runtime. And that’s how the idea for this article was born.</p>
<p>I started by creating two virtual machines. Here are the specifications:</p>
<ul>
<li>Operating system: Ubuntu 20.04</li>
<li>CPU: 2 vCPU</li>
<li>Memory: 4GB</li>
<li>Disk space: 20GB</li>
</ul>
<p>Before proceeding, let’s make sure our virtual machines can communicate with each other. Once verified, we’re ready to begin.</p>
<h2 id="installing-containerd">Installing containerd</h2>
<p>Containerd is the backbone of our cluster—the foundation on which all our containers will run. Let’s install it on our machines:</p>
<p><strong>Prepare for installation:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt-get update
</span></span><span style="display:flex;"><span>sudo apt-get install -y apt-transport-https ca-certificates curl
</span></span></code></pre></div><p><strong>Add Docker’s official GPG key:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo install -m <span style="color:#ae81ff">0755</span> -d /etc/apt/keyrings
</span></span><span style="display:flex;"><span>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
</span></span><span style="display:flex;"><span>sudo chmod a+r /etc/apt/keyrings/docker.gpg
</span></span></code></pre></div><p><strong>Add the official Docker repository to our sources list:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;deb [arch=&#34;</span><span style="color:#66d9ef">$(</span>dpkg --print-architecture<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34; signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;</span><span style="color:#66d9ef">$(</span>. /etc/os-release <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;</span>$VERSION_CODENAME<span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34; stable&#34;</span> | <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/null
</span></span></code></pre></div><p><strong>Finally, install containerd:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt-get update
</span></span><span style="display:flex;"><span>sudo apt-get install containerd.io -y
</span></span></code></pre></div><h2 id="installing-kubeadm-kubelet-and-kubectl">Installing kubeadm, kubelet, and kubectl</h2>
<p>These three components are the beating heart of Kubernetes. <code>kubeadm</code> helps us set up the cluster, <code>kubelet</code> ensures that all containers run correctly, and <code>kubectl</code> is our command-line interface for managing the cluster.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main&#34;</span> | sudo tee /etc/apt/sources.list.d/kubernetes.list
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt-get update
</span></span><span style="display:flex;"><span>sudo apt-get install -y kubelet kubeadm kubectl
</span></span><span style="display:flex;"><span>sudo apt-mark hold kubelet kubeadm kubectl
</span></span></code></pre></div><h2 id="disabling-swap">Disabling Swap</h2>
<p>Kubernetes prefers swap to be disabled, as it can interfere with pod scheduling, especially in low-memory scenarios.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo swapoff -a
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo nano /etc/fstab
</span></span></code></pre></div><p>(In the editor, comment out the line referring to swap by adding a <code>#</code> at the beginning of the line.)</p>
<h2 id="configuring-kernel-modules">Configuring Kernel Modules</h2>
<p>We need to enable some Linux kernel modules to make everything work correctly.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo modprobe overlay
</span></span><span style="display:flex;"><span>sudo modprobe br_netfilter
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;EOF | sudo tee /etc/modules-load.d/containerd.conf
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">overlay
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">br_netfilter
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">net.bridge.bridge-nf-call-iptables  = 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">net.ipv4.ip_forward                 = 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">net.bridge.bridge-nf-call-ip6tables = 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo sysctl --system
</span></span></code></pre></div><h2 id="configure-containerd">Configure containerd</h2>
<p>Let’s make sure containerd is properly configured to interact with Kubernetes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mkdir -p /etc/containerd
</span></span><span style="display:flex;"><span>containerd config default | sudo tee /etc/containerd/config.toml
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo systemctl restart containerd
</span></span><span style="display:flex;"><span>sudo systemctl enable containerd
</span></span></code></pre></div><h2 id="configuring-the-control-plane">Configuring the Control Plane</h2>
<p>Here comes the most exciting moment! We are about to initialize our Kubernetes cluster.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo systemctl enable kubelet
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo kubeadm init --pod-network-cidr<span style="color:#f92672">=</span>192.168.0.0/16
</span></span></code></pre></div><p>(Don’t forget to write down the join command shown in the output! We’ll use it to add other nodes to the cluster.)</p>
<h2 id="installing-calico-as-cni">Installing Calico as CNI</h2>
<p>Calico is one of the most popular Network Interfaces for Kubernetes. It helps manage communication between pods.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml
</span></span></code></pre></div><hr>
<p>If you’ve made it this far, you now have a fully functional Kubernetes cluster with <code>containerd</code> as the runtime.
I hope this article has been helpful, and if you have any questions or suggestions, don’t hesitate to <a href="https://www.linkedin.com/in/marcoferraioli93/">contact me</a>.</p>
]]></content:encoded></item><item><title>JSON RPC and JRPC: Revolutionizing Your Remote Procedure Calls</title><link>https://paranoiasystem.com/posts/jrpc/</link><pubDate>Thu, 18 May 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/posts/jrpc/</guid><description>In this article, we explore JSON RPC and JRPC, two protocols for remote procedure calls. We will discuss their unique features, use cases, and how they can be leveraged to build efficient and scalable distributed systems.</description><content:encoded><![CDATA[<h3 id="what-is-an-rpc">What is an RPC?</h3>
<p><strong><em>RPC</em></strong>, short for <strong><em>Remote Procedure Call</em></strong>, is a protocol that allows one piece of software to request a service exposed by another piece of software.<br>
These two pieces of software can reside on the same machine or on different machines, even across different networks.</p>
<p>In essence, an <strong><em>RPC</em></strong> call consists of invoking a function or procedure hosted on a server, a separate device, or inside a container.<br>
When an <strong><em>RPC</em></strong> call is made, the underlying system handles the entire communication process between the two devices, making the remote procedure virtually indistinguishable from a local one from the developer&rsquo;s perspective.</p>
<p><strong><em>RPC</em></strong> is fundamental in many situations, such as:</p>
<ul>
<li><strong>Distributed data storage systems</strong></li>
<li><strong>Web services</strong></li>
<li><strong>Distributed computing projects</strong></li>
<li><strong>Operating systems</strong></li>
<li><strong>Microservices</strong></li>
</ul>
<h3 id="the-value-of-rpc">The Value of RPC</h3>
<p>Adopting <strong><em>RPC</em></strong> offers numerous benefits, making it a strong choice in various contexts.<br>
First of all, it abstracts away the complexity of networking: <strong><em>RPC</em></strong> hides the details of the network system, allowing developers to focus on application logic.<br>
Additionally, <strong><em>RPC</em></strong> promotes a modular approach to software development, where each service can be developed, tested, and deployed independently.<br>
Finally, thanks to its nature, <strong><em>RPC</em></strong> facilitates interoperability between different technologies and programming languages, simplifying integration between various systems or components.</p>
<h3 id="json-rpc-an-innovation-in-rpc">JSON RPC: An Innovation in RPC</h3>
<p><a href="https://www.jsonrpc.org/"><strong><em>JSON RPC</em></strong></a> takes the concept of <strong><em>RPC</em></strong> to a new level, introducing flexibility and interactivity.<br>
This data transmission protocol uses the <strong><em>JSON</em></strong> (<strong><em>JavaScript Object Notation</em></strong>) format to encode <strong><em>RPC</em></strong> messages, making them lightweight, easy to read and write, and independent of the programming language being used.</p>
<p>The protocol follows precise rules: every <strong><em>RPC</em></strong> call is encoded as a <strong><em>JSON</em></strong> object that must include the following properties:</p>
<ul>
<li><strong>method</strong>: specifies the name of the method to invoke</li>
<li><strong>params</strong>: an array or object representing the method parameters</li>
<li><strong>id</strong>: a unique identifier for the call</li>
<li><strong>jsonrpc</strong>: specifies the version of the <a href="https://www.jsonrpc.org/"><strong><em>JSON RPC</em></strong></a> protocol</li>
</ul>
<p>The response, also encoded in <strong><em>JSON</em></strong>, returns either the result of the invoked method or error details in case of failure. It includes the following properties:</p>
<ul>
<li><strong>jsonrpc</strong>: specifies the version of the <a href="https://www.jsonrpc.org/"><strong><em>JSON RPC</em></strong></a> protocol</li>
<li><strong>id</strong>: a unique identifier for the call</li>
<li><strong>result</strong>: contains the result of the call, which may be an object. If an error occurs, this property will not be present</li>
<li><strong>error</strong>: returned in case of an error, with the following structure:
<ul>
<li><strong>code</strong>: a number indicating the type of error. You can check the list of possible error codes and their meaning at this <a href="https://www.jsonrpc.org/specification#error_object">link</a></li>
<li><strong>message</strong>: a short message describing the error</li>
<li><strong>data</strong>: an object providing additional details about the error, optional</li>
</ul>
</li>
</ul>
<p>For more insights and further details about the protocol, I encourage you to consult the official <a href="https://www.jsonrpc.org/"><strong><em>JSON RPC</em></strong></a> documentation.</p>
<h3 id="detailed-analysis-of-json-rpc">Detailed Analysis of JSON RPC</h3>
<p>The <a href="https://www.jsonrpc.org/"><strong><em>JSON RPC</em></strong></a> protocol stands out from other <strong><em>RPC</em></strong> solutions due to its flexibility and interoperability.<br>
It is not tied to a specific programming language or transport protocol.<br>
In fact, it can be used with any language and transported over any protocol, offering unprecedented flexibility.<br>
The protocol’s efficiency is further enhanced by its support for batch calls or notification calls, optimizing resource usage.</p>
<h3 id="jrpc-simplifying-the-use-of-json-rpc">JRPC: Simplifying the Use of JSON RPC</h3>
<p><strong><em>JRPC</em></strong> is a project I am developing with the goal of making the implementation of the <a href="https://www.jsonrpc.org/"><strong><em>JSON RPC</em></strong></a> protocol more straightforward and intuitive.<br>
This project consists of two key components: a <a href="https://github.com/webeetle/JRPC-Server">server library</a> and a <a href="https://github.com/webeetle/JRPC-Client">client library</a>, created to simplify the integration of the <a href="https://www.jsonrpc.org/"><strong><em>JSON RPC</em></strong></a> protocol into software applications.<br>
The server library efficiently manages <strong>RPC</strong> requests, while the client library facilitates the processing and handling of <strong>RPC</strong> calls.<br>
To further accelerate client-side implementation, I am also developing a <a href="https://github.com/paranoiasystem/jrpc-cli">CLI</a>.</p>
<p>Here’s a clear and concise example of how it works:</p>
<p>For the server, based on Fastify:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">jrpcServer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Server</span>({
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;jrpc-server&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">version</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;1.0.0&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">description</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;demo server&#39;</span>,
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">jrpcServer</span>.<span style="color:#a6e22e">addMethod</span>({
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;hello&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;description&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;A simple hello world method&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;params&#34;</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;name&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;description&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;The name of the person to say hello to&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;schema&#34;</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;type&#34;</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#34;string&#34;</span>,
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#34;null&#34;</span>
</span></span><span style="display:flex;"><span>                ]
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;result&#34;</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;result&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;description&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;The result of the hello world method&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;schema&#34;</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;string&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}, (<span style="color:#a6e22e">name?</span>: <span style="color:#66d9ef">string</span>)<span style="color:#f92672">:</span> <span style="color:#66d9ef">string</span> <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">name</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#39;Hello World!&#39;</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#e6db74">`Hello </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">name</span><span style="color:#e6db74">}</span><span style="color:#e6db74">!`</span>;
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">server</span>.<span style="color:#a6e22e">post</span>(<span style="color:#e6db74">&#39;/jrpc&#39;</span>, <span style="color:#66d9ef">async</span> (<span style="color:#a6e22e">request</span>, <span style="color:#a6e22e">reply</span>) <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> {<span style="color:#a6e22e">body</span>} <span style="color:#f92672">=</span> <span style="color:#a6e22e">request</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">result</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">jrpcServer</span>.<span style="color:#a6e22e">executeRequest</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">body</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">reply</span>.<span style="color:#a6e22e">send</span>(<span style="color:#a6e22e">result</span>);
</span></span><span style="display:flex;"><span>})
</span></span><span style="display:flex;"><span>...
</span></span></code></pre></div><p>For the client:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">DemoRpcMethods</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">hello</span>(<span style="color:#a6e22e">name?</span>: <span style="color:#66d9ef">string</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">Promise</span>&lt;<span style="color:#f92672">string</span>&gt;;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>    ...
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">client</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">JRPCClient</span>&lt;<span style="color:#f92672">DemoRpcMethods</span>&gt;(<span style="color:#e6db74">&#34;http://127.0.0.1:3000/jrpc&#34;</span>, <span style="color:#a6e22e">resolver</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">proxy</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">client</span>.<span style="color:#a6e22e">createProxy</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">await</span> <span style="color:#a6e22e">proxy</span>.<span style="color:#a6e22e">hello</span>());
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#66d9ef">await</span> <span style="color:#a6e22e">proxy</span>.<span style="color:#a6e22e">hello</span>(<span style="color:#e6db74">&#39;Demo&#39;</span>));
</span></span><span style="display:flex;"><span>})();
</span></span></code></pre></div><p>As you can see from the client code, it is enough to define an interface that describes the <em><strong>RPC</strong></em> methods, and the library takes care of the rest, eliminating the need to manually define the request payload.</p>
<p>Using the <a href="https://github.com/paranoiasystem/jrpc-cli">CLI</a> allows you to automatically generate the interface from the schema produced by the server, further simplifying the process.</p>
<p>For more details, visit my <a href="https://github.com/paranoiasystem/jrpc-article">GitHub</a> to see the full demo code.</p>
<h3 id="conclusion">Conclusion</h3>
<p>In conclusion, <em><strong>JRPC</strong></em> is my contribution to the community of developers working with <em><strong>JSON RPC</strong></em>.
I firmly believe that collaboration is the key to developing high-quality software, and for this reason, I invite everyone to contribute to the project.
Whether you have an idea for a new feature, a bug report, or a fix, every contribution is valuable and makes a difference.</p>
]]></content:encoded></item><item><title>About</title><link>https://paranoiasystem.com/about/</link><pubDate>Tue, 16 May 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/about/</guid><description>&lt;p&gt;Hello, I&amp;rsquo;m Marco Ferraioli, but you might know me as ParanoiaSystem.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m a big fan of technology, a developer, and someone who loves to create new things. I&amp;rsquo;ve been lucky to work in many different areas of technology, and each one has taught me something new. I&amp;rsquo;ve learned how technology changes the way we live and work, and I&amp;rsquo;m always amazed by its power and potential.&lt;/p&gt;
&lt;p&gt;I love programming, especially when it comes to working with cloud technologies like containerization and Kubernetes. I&amp;rsquo;m always looking for new ways to build better and more efficient systems using these tools.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Hello, I&rsquo;m Marco Ferraioli, but you might know me as ParanoiaSystem.</p>
<p>I&rsquo;m a big fan of technology, a developer, and someone who loves to create new things. I&rsquo;ve been lucky to work in many different areas of technology, and each one has taught me something new. I&rsquo;ve learned how technology changes the way we live and work, and I&rsquo;m always amazed by its power and potential.</p>
<p>I love programming, especially when it comes to working with cloud technologies like containerization and Kubernetes. I&rsquo;m always looking for new ways to build better and more efficient systems using these tools.</p>
<p>I&rsquo;m also really interested in how we design software and systems. I believe that good design and clean code are crucial for successful software. I enjoy learning about different design patterns, like hexagonal architecture, which can help us build more reliable and easy-to-maintain systems.</p>
<p>In my spare time, I like to experiment with things like Internet of Things (IoT), home automation, and electronics. I love playing with microcontrollers like Arduino and ESP32, and using them to make my home smarter and more responsive.</p>
<p>One of my hobbies is 3D printing. I find it amazing how we can turn a digital design into a real, physical object. It&rsquo;s a great example of how technology is bringing the digital and physical worlds closer together.</p>
<p>On this blog, I&rsquo;ll be sharing my experiences, discoveries, and thoughts about technology. Whether it&rsquo;s a new cloud solution I&rsquo;ve found, a design pattern I&rsquo;ve been studying, an IoT project I&rsquo;ve been working on, or a new 3D print, I&rsquo;ll be talking about it here.</p>
<p>I invite you to join me as I explore the world of technology. Whether you&rsquo;re a tech enthusiast yourself or just curious, I hope you&rsquo;ll find something here that inspires and interests you.</p>
<p>Welcome to my world,
Marco Ferraioli A.K.A. ParanoiaSystem</p>
]]></content:encoded></item><item><title>Automatic Management of AWS ECR Credentials in a Kubernetes Cluster</title><link>https://paranoiasystem.com/posts/k8s-aws-ecr-secret-updater/</link><pubDate>Tue, 16 May 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/posts/k8s-aws-ecr-secret-updater/</guid><description>In this article, we discuss the challenges of managing AWS ECR credentials in a Kubernetes environment and present a solution for automating the process.</description><content:encoded><![CDATA[<p>In the course of my work with <strong><em>AWS ECR (Elastic Container Registry)</em></strong>, I ran into a problem: The repository access key expires every six hours. Working with a non-AWS Kubernetes test cluster, I had to constantly update these credentials manually, a repetitive and tedious process.</p>
<p>From this experience came the idea to create a tool that automated this process: <strong><em><a href="https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater">k8s-aws-ecr-secret-updater</a></em></strong>. This tool is a Kubernetes cronjob, designed to automatically update the AWS ECR repository access credentials.</p>
<h2 id="cronjob-configuration">Cronjob Configuration</h2>
<p>The YAML code to create the cronjob consists of several parts, which I will now analyze piece by piece:</p>
<h4 id="a-role-that-has-permission-to-get-create-and-delete-secrets-and-get-and-update-serviceaccounts">A Role that has permission to get, create, and delete secrets and get and update ServiceAccounts.</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Role</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">rbac.authorization.k8s.io/v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">rules</span>:
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">apiGroups</span>: [<span style="color:#e6db74">&#34;&#34;</span>]
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">resources</span>: [<span style="color:#e6db74">&#34;secrets&#34;</span>]
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">verbs</span>: [<span style="color:#e6db74">&#34;get&#34;</span>, <span style="color:#e6db74">&#34;create&#34;</span>, <span style="color:#e6db74">&#34;delete&#34;</span>]
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">apiGroups</span>: [<span style="color:#e6db74">&#34;&#34;</span>]
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">resources</span>: [<span style="color:#e6db74">&#34;serviceaccounts&#34;</span>]
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">verbs</span>: [<span style="color:#e6db74">&#34;get&#34;</span>, <span style="color:#e6db74">&#34;patch&#34;</span>]
</span></span></code></pre></div><p>A key component of this configuration is the <strong><em>k8sawsecrsecretupdater</em></strong> role. This role is fundamental for authorization within the Kubernetes namespace, allowing the cronjob to perform specific operations on certain resources.</p>
<p>In particular, the <strong><em>k8sawsecrsecretupdater</em></strong> role has the following permissions:</p>
<ol>
<li>It has permissions to get (<strong><em>get</em></strong>), create (<strong><em>create</em></strong>), and delete (<strong><em>delete</em></strong>) <strong><em>Secrets</em></strong>. This is crucial because the cronjob needs to be able to create and delete AWS ECR credentials, which are stored as secrets in Kubernetes.</li>
<li>It has permissions to get (<strong><em>get</em></strong>) and update (<strong><em>patch</em></strong>) <strong><em>ServiceAccounts</em></strong>. The cronjob needs to be able to manage service accounts in order to associate the AWS ECR credentials with the service that runs the cronjob.</li>
</ol>
<p>Creating a specific role for these operations ensures that the cronjob has exactly the permissions it needs to do its job, without granting it access to unnecessary resources. This approach is in line with the principle of least privilege, a common security practice that limits access to resources only to what is strictly necessary to perform a specific task. This helps to minimize the potential impact of a possible attack.</p>
<h4 id="serviceaccount-to-be-used-by-the-job-and-cronjob">ServiceAccount to be used by the job and cronjob.</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">ServiceAccount</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span></code></pre></div><h4 id="rolebinding-to-associate-the-role-with-the-serviceaccount">RoleBinding to associate the Role with the ServiceAccount.</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">RoleBinding</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">rbac.authorization.k8s.io/v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">subjects</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">kind</span>: <span style="color:#ae81ff">ServiceAccount</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">roleRef</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Role</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">apiGroup</span>: <span style="color:#ae81ff">rbac.authorization.k8s.io</span>
</span></span></code></pre></div><h4 id="job-that-creates-the-secret">Job that creates the secret.</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">batch/v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Job</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">backoffLimit</span>: <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">template</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">serviceAccountName</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">restartPolicy</span>: <span style="color:#ae81ff">Never</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">image</span>: <span style="color:#ae81ff">ghcr.io/paranoiasystem/k8s-aws-ecr-secret-updater:latest</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">imagePullPolicy</span>: <span style="color:#ae81ff">Always</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">env</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_ACCOUNT</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">value</span>: <span style="color:#e6db74">&#39;YourAwsAccountID&#39;</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_ACCESS_KEY_ID</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">value</span>: <span style="color:#ae81ff">YourAccessKeyID</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_SECRET_ACCESS_KEY</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">value</span>: <span style="color:#ae81ff">YourSecretAccessKey</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_REGION</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">value</span>: <span style="color:#ae81ff">YourRegion</span>
</span></span></code></pre></div><h4 id="cronjob-that-runs-the-job-every-6-hours">CronJob that runs the Job every 6 hours.</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">batch/v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">CronJob</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">schedule</span>: <span style="color:#e6db74">&#34;0 */6 * * *&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">successfulJobsHistoryLimit</span>: <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">failedJobsHistoryLimit</span>: <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">jobTemplate</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">template</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">serviceAccountName</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">restartPolicy</span>: <span style="color:#ae81ff">Never</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>          - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">k8sawsecrsecretupdater</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">image</span>: <span style="color:#ae81ff">ghcr.io/paranoiasystem/k8s-aws-ecr-secret-updater:latest</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">imagePullPolicy</span>: <span style="color:#ae81ff">Always</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">env</span>:
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_ACCOUNT</span>
</span></span><span style="display:flex;"><span>              <span style="color:#f92672">value</span>: <span style="color:#e6db74">&#39;YourAwsAccountID&#39;</span>
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_ACCESS_KEY_ID</span>
</span></span><span style="display:flex;"><span>              <span style="color:#f92672">value</span>: <span style="color:#ae81ff">YourAccess</span>
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_SECRET_ACCESS_KEY</span>
</span></span><span style="display:flex;"><span>              <span style="color:#f92672">value</span>: <span style="color:#ae81ff">YourSecretAccessKey</span>
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">AWS_REGION</span>
</span></span><span style="display:flex;"><span>              <span style="color:#f92672">value</span>: <span style="color:#ae81ff">YourRegion</span>
</span></span></code></pre></div><h2 id="creating-the-docker-image">Creating the Docker Image</h2>
<p>The cronjob uses a specific Docker image to perform its task. This Docker image is built from the following Dockerfile:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-dockerfile" data-lang="dockerfile"><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span> <span style="color:#e6db74">alpine</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">LABEL</span> org.opencontainers.image.description <span style="color:#e6db74">`</span>Docker image <span style="color:#66d9ef">for</span> refresh AWS ECR credentials in kubernetes cluster<span style="color:#e6db74">`</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">RUN</span> apk update <span style="color:#f92672">&amp;&amp;</span> apk add --update --no-cache <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    git <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    bash <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    curl <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    openssh <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    python3 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    py3-pip <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    py-cryptography <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    wget <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    curl <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    jq <span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Install kubectl</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">RUN</span> curl -LO <span style="color:#e6db74">&#34;https://dl.k8s.io/release/</span><span style="color:#66d9ef">$(</span>curl -L -s https://dl.k8s.io/release/stable.txt<span style="color:#66d9ef">)</span><span style="color:#e6db74">/bin/linux/amd64/kubectl&#34;</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">RUN</span> chmod +x ./kubectl<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">RUN</span> mv ./kubectl /usr/local/bin/kubectl<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Install AWSCLI</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">RUN</span> pip install --upgrade pip <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    pip install --upgrade awscli<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">WORKDIR</span> <span style="color:#e6db74">/scripts</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">COPY</span> scripts/ /scripts<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">ENTRYPOINT</span> [<span style="color:#e6db74">&#34;bash&#34;</span>, <span style="color:#e6db74">&#34;/scripts/entrypoint.sh&#34;</span>]<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>In the Dockerfile, starting from an Alpine base image, the necessary tools are installed, including git, bash, curl, openssh, python3, py3-pip, py-cryptography, wget, curl, jq. Also, kubectl and AWSCLI are installed for interaction with Kubernetes and AWS, respectively.</p>
<p>Subsequently, the working directory is set to /scripts and the contents of the local /scripts directory are copied. Finally, an ENTRYPOINT is defined that starts the entrypoint.sh script when the container is run.</p>
<h2 id="execution-of-the-script">Execution of the Script</h2>
<p>When the cronjob is run, it starts the bash script contained in the Docker image. This script checks for the existence of a secret called <code>&quot;regcred&quot;</code>. If it exists, it deletes it and creates a new one. If it doesn&rsquo;t exist, it creates it. Below is the script:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>create_secret<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  kubectl create secret docker-registry regcred <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    --docker-server<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>AWS_ACCOUNT<span style="color:#e6db74">}</span>.dkr.ecr.<span style="color:#e6db74">${</span>AWS_REGION<span style="color:#e6db74">}</span>.amazonaws.com <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    --docker-username<span style="color:#f92672">=</span>AWS <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>    --docker-password<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>aws ecr get-login-password --region <span style="color:#e6db74">${</span>AWS_REGION<span style="color:#e6db74">}</span><span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Check if the secret exists</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> kubectl get secret regcred; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># If it exists, delete it</span>
</span></span><span style="display:flex;"><span>  kubectl delete secret regcred
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># Create the secret again</span>
</span></span><span style="display:flex;"><span>  create_secret
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># If it doesn&#39;t exist, create it</span>
</span></span><span style="display:flex;"><span>  create_secret
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><h2 id="installing-k8s-aws-ecr-secret-updater-on-kubernetes">Installing k8s-aws-ecr-secret-updater on Kubernetes</h2>
<p>To use the <strong><em><a href="https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater">k8s-aws-ecr-secret-updater</a></em></strong> in your Kubernetes environment, you need to follow some simple steps.</p>
<p>Let&rsquo;s start by cloning the project&rsquo;s GitHub repository onto your local system:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>git clone https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater
</span></span></code></pre></div><p>Next, you need to open and edit the <strong><em>install.yaml</em></strong> file present in the repository. In this file, you will need to set the following values:</p>
<ul>
<li><strong>AWS_ACCOUNT</strong>: your AWS account ID.</li>
<li><strong>AWS_ACCESS_KEY_ID</strong>: your AWS access key.</li>
<li><strong>AWS_SECRET_ACCESS_KEY</strong>: your AWS secret access key.</li>
<li><strong>AWS_REGION</strong>: the AWS region where your ECR is located.</li>
</ul>
<p>Once you have made these changes, save and exit the install.yaml file.</p>
<p>Now, to install the <strong><em><a href="https://github.com/paranoiasystem/k8s-aws-ecr-secret-updater">k8s-aws-ecr-secret-updater</a></em></strong> in your Kubernetes cluster, you need to execute the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>kubectl apply -n &lt;destination_namespace&gt; -f install.yaml
</span></span></code></pre></div><p>Remember to replace <strong>destination_namespace</strong> with the Kubernetes namespace where you want to install the cronjob.</p>
<h2 id="conclusions">Conclusions</h2>
<p>This tool eliminates the need for manual updating of credentials, saving time and reducing the risk of errors. I hope this article and the tool I created can be of help to anyone dealing with a similar issue in managing AWS ECR credentials in a Kubernetes cluster.</p>
]]></content:encoded></item><item><title>Minicorso Docker: Docker Compose</title><link>https://paranoiasystem.com/speaking/minicorso-docker-3-thecmmbay-2023-02-01/</link><pubDate>Wed, 01 Feb 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/speaking/minicorso-docker-3-thecmmbay-2023-02-01/</guid><description>&lt;p&gt;🎫 Event Name: Minicorso Docker: Docker Compose&lt;/p&gt;
&lt;p&gt;📍 Where: Online&lt;/p&gt;
&lt;p&gt;🕛 When: 1 February 2023&lt;/p&gt;
&lt;p&gt;🗣️ Language: ITA 🇮🇹&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In un mondo tecnologico in continua evoluzione, è sempre più importante essere in grado di scalare e adattare rapidamente i sistemi alle crescenti richieste degli utenti.&lt;/p&gt;
&lt;p&gt;I Container offrono una soluzione efficace a questo problema, poiché permettono di isolare il software e farlo eseguire in modo indipendente su diversi sistemi operativi e hardware. Ciò consente alle applicazioni basate sui Container di passare facilmente tra gli ambienti di sviluppo, test e produzione.&lt;/p&gt;</description><content:encoded><![CDATA[<p>🎫 Event Name: Minicorso Docker: Docker Compose</p>
<p>📍 Where: Online</p>
<p>🕛 When: 1 February 2023</p>
<p>🗣️ Language: ITA 🇮🇹</p>
<hr>
<p>In un mondo tecnologico in continua evoluzione, è sempre più importante essere in grado di scalare e adattare rapidamente i sistemi alle crescenti richieste degli utenti.</p>
<p>I Container offrono una soluzione efficace a questo problema, poiché permettono di isolare il software e farlo eseguire in modo indipendente su diversi sistemi operativi e hardware. Ciò consente alle applicazioni basate sui Container di passare facilmente tra gli ambienti di sviluppo, test e produzione.</p>
<p>Tra le migliori implementazioni della tecnologia dei Container c’è Docker, che offre una serie di funzionalità utili, a cui sarà difficile rinunciare dopo averle imparate ed utilizzate.</p>
<h2 id="docker-compose">Docker Compose</h2>
<p>In questo talk esploreremo Docker Compose, capiremo di cosa di tratta, come e quando usarlo.</p>
<p>Inoltre, partendo da un’applicazione reale la faremo girare, insieme, su Docker.</p>
<p>Nel dettaglio:</p>
<ul>
<li>Docker Compose</li>
<li>Compose file</li>
<li>Come scrivere un Docker Compose file</li>
<li>Esempio pratico di applicazione reale che gira su Docker</li>
</ul>
<p><a href="https://thecmmbay.com/eventi/minicorso-docker-docker-compose-024j94welrz">Scopri di più</a></p>
]]></content:encoded></item><item><title>Minicorso Docker: Volumi e Network di Docker</title><link>https://paranoiasystem.com/speaking/minicorso-docker-2-thecmmbay-2023-01-25/</link><pubDate>Wed, 25 Jan 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/speaking/minicorso-docker-2-thecmmbay-2023-01-25/</guid><description>&lt;p&gt;🎫 Event Name: Minicorso Docker: Volumi e Network di Docker&lt;/p&gt;
&lt;p&gt;📍 Where: Online&lt;/p&gt;
&lt;p&gt;🕛 When: 25 January 2023&lt;/p&gt;
&lt;p&gt;🗣️ Language: ITA 🇮🇹&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In un mondo tecnologico in continua evoluzione, è sempre più importante essere in grado di scalare e adattare rapidamente i sistemi alle crescenti richieste degli utenti.&lt;/p&gt;
&lt;p&gt;I Container offrono una soluzione efficace a questo problema, poiché permettono di isolare il software e farlo eseguire in modo indipendente su diversi sistemi operativi e hardware. Ciò consente alle applicazioni basate sui Container di passare facilmente tra gli ambienti di sviluppo, test e produzione.&lt;/p&gt;</description><content:encoded><![CDATA[<p>🎫 Event Name: Minicorso Docker: Volumi e Network di Docker</p>
<p>📍 Where: Online</p>
<p>🕛 When: 25 January 2023</p>
<p>🗣️ Language: ITA 🇮🇹</p>
<hr>
<p>In un mondo tecnologico in continua evoluzione, è sempre più importante essere in grado di scalare e adattare rapidamente i sistemi alle crescenti richieste degli utenti.</p>
<p>I Container offrono una soluzione efficace a questo problema, poiché permettono di isolare il software e farlo eseguire in modo indipendente su diversi sistemi operativi e hardware. Ciò consente alle applicazioni basate sui Container di passare facilmente tra gli ambienti di sviluppo, test e produzione.</p>
<p>Tra le migliori implementazioni della tecnologia dei Container c’è Docker, che offre una serie di funzionalità utili, a cui sarà difficile rinunciare dopo averle imparate ed utilizzate.</p>
<h2 id="volumi-e-network-di-docker">Volumi e Network di Docker</h2>
<p>In questo talk affronteremo i concetti di volume e network di Docker.</p>
<p>I volumi ci consentono di effettuare la persistenza dei dati e altre cose interessanti, che scoprirete durante la lezione.</p>
<p>I network, invece, ci consentono di creare reti virtuali all’interno delle quali far comunicare i nostri container.</p>
<p>In particolare:</p>
<ul>
<li>Volumi Docker</li>
<li>Come creare e usare un volume</li>
<li>Tipi di volume</li>
<li>Network Docker</li>
<li>Come creare una network</li>
<li>Tipologie di rete</li>
<li>Come usare una rete</li>
</ul>
<p><a href="https://thecmmbay.com/eventi/minicorso-docker-volumi-e-network-di-docker-pvxeqvqjo19">Scopri di più</a></p>
]]></content:encoded></item><item><title>Minicorso Docker: le basi di Docker</title><link>https://paranoiasystem.com/speaking/minicorso-docker-1-thecmmbay-2023-01-18/</link><pubDate>Wed, 18 Jan 2023 00:00:00 +0000</pubDate><guid>https://paranoiasystem.com/speaking/minicorso-docker-1-thecmmbay-2023-01-18/</guid><description>&lt;p&gt;🎫 Event Name: Minicorso Docker: le basi di Docker&lt;/p&gt;
&lt;p&gt;📍 Where: Online&lt;/p&gt;
&lt;p&gt;🕛 When: 18 January 2023&lt;/p&gt;
&lt;p&gt;🗣️ Language: ITA 🇮🇹&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In un mondo tecnologico in continua evoluzione, è sempre più importante essere in grado di scalare e adattare rapidamente i sistemi alle crescenti richieste degli utenti.&lt;/p&gt;
&lt;p&gt;I Container offrono una soluzione efficace a questo problema, poiché permettono di isolare il software e farlo eseguire in modo indipendente su diversi sistemi operativi e hardware. Ciò consente alle applicazioni basate sui Container di passare facilmente tra gli ambienti di sviluppo, test e produzione.&lt;/p&gt;</description><content:encoded><![CDATA[<p>🎫 Event Name: Minicorso Docker: le basi di Docker</p>
<p>📍 Where: Online</p>
<p>🕛 When: 18 January 2023</p>
<p>🗣️ Language: ITA 🇮🇹</p>
<hr>
<p>In un mondo tecnologico in continua evoluzione, è sempre più importante essere in grado di scalare e adattare rapidamente i sistemi alle crescenti richieste degli utenti.</p>
<p>I Container offrono una soluzione efficace a questo problema, poiché permettono di isolare il software e farlo eseguire in modo indipendente su diversi sistemi operativi e hardware. Ciò consente alle applicazioni basate sui Container di passare facilmente tra gli ambienti di sviluppo, test e produzione.</p>
<p>Tra le migliori implementazioni della tecnologia dei Container c’è Docker, che offre una serie di funzionalità utili, a cui sarà difficile rinunciare dopo averle imparate ed utilizzate.</p>
<h2 id="le-basi-di-docker">Le basi di Docker</h2>
<p>In questo talk esploreremo le basi di Docker: partiremo dal concetto di container, lo paragoneremo con le Virtual Machine, capiremo quali sono le differenze, i motivi per cui Docker è nato, i problemi che risolve e quando conviene utilizzarlo o meno.</p>
<p>Dopo aver installato insieme Docker, andremo ad analizzare la sua architettura ed inizieremo a prendere confidenza con la sua CLI (Command-line interface).</p>
<p>Nello specifico:</p>
<ul>
<li>Cosa sono i container</li>
<li>Differenza con le Virtual Machine</li>
<li>Un pò di storia dei container</li>
<li>Installazione di Docker</li>
<li>Docker CLI</li>
<li>Comandi di base</li>
<li>Le immagini Docker</li>
</ul>
<p><a href="https://thecmmbay.com/eventi/minicorso-docker-le-basi-di-docker-4vdj84w7n3k">Scopri di più</a></p>
]]></content:encoded></item></channel></rss>