<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>2025-05 on Funky Si's Test</title><link>https://blog-test.funkysi1701.com/2025/05/</link><description>Recent content in 2025-05 on Funky Si's Test</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><managingEditor>funkysi1701@gmail.com (Simon Foster)</managingEditor><webMaster>funkysi1701@gmail.com (Simon Foster)</webMaster><lastBuildDate>Mon, 26 May 2025 20:00:00 +0000</lastBuildDate><atom:link href="https://blog-test.funkysi1701.com/2025/05/index.xml" rel="self" type="application/rss+xml"/><item><title>Deploy this blog with Helm charts</title><link>https://blog-test.funkysi1701.com/posts/2025/deploying-hugo-with-helm/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 26 May 2025 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2025/deploying-hugo-with-helm/</guid><category term="Kubernetes">Kubernetes</category><category term="Helm">Helm</category><category term="DevOps">DevOps</category><category term="Hugo">Hugo</category><category term="Blog">Blog</category><category term="Deployment">Deployment</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/helm-hugo.png"/><description>&lt;p&gt;Helm allows you to package your Kubernetes resources, manage configuration, and deploy updates with a single command.&lt;/p&gt;
&lt;p&gt;In this post, I’ll share how I used Helm to deploy my Hugo blog, making it easy to manage updates and spin up new environments. Full disclosure: My blog currently runs on an Azure Static Web App, but now that I know how to deploy to a Kubernetes cluster, I have the option to switch if needed.&lt;/p&gt;
&lt;h2 id="why-use-helm"&gt;Why Use Helm?&lt;a class="anchor ms-1" href="#why-use-helm" aria-label="Permalink: Why Use Helm?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Helm is the package manager for Kubernetes. It lets you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Template&lt;/strong&gt; your Kubernetes YAML files for reuse and configuration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Version&lt;/strong&gt; your deployments for easy rollbacks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Share&lt;/strong&gt; your charts with others or use community charts.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="creating-a-helm-chart-for-hugo"&gt;Creating a Helm Chart for Hugo&lt;a class="anchor ms-1" href="#creating-a-helm-chart-for-hugo" aria-label="Permalink: Creating a Helm Chart for Hugo"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, I scaffolded a new Helm chart:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm create hugo-blog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This creates a directory structure with templates for deployments, services, and ingress.&lt;/p&gt;
&lt;h3 id="customizing-the-chart"&gt;Customizing the Chart&lt;a class="anchor ms-1" href="#customizing-the-chart" aria-label="Permalink: Customizing the Chart"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I edited &lt;code&gt;values.yaml&lt;/code&gt; to set my image and service details:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;image&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;repository&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;mydockerhubusername/hugo-blog&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Docker image repository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tag&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;latest&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Use the latest tag for the image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pullPolicy&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;IfNotPresent&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Pull the image only if it’s not already present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;service&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;NodePort&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Expose the service on a specific port&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Internal port for the service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;nodePort&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30081&lt;/span&gt; &lt;span style="color:#75715e"&gt;# External port for accessing the service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="deploying-the-blog"&gt;Deploying the Blog&lt;a class="anchor ms-1" href="#deploying-the-blog" aria-label="Permalink: Deploying the Blog"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To deploy the blog, I ran:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install my-hugo-blog ./hugo-blog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Helm rendered the templates and created the necessary Kubernetes resources.&lt;/p&gt;
&lt;h3 id="updating-the-blog"&gt;Updating the Blog&lt;a class="anchor ms-1" href="#updating-the-blog" aria-label="Permalink: Updating the Blog"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When I rebuild and push a new Docker image, I can upgrade my deployment with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm upgrade my-hugo-blog ./hugo-blog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This triggers a rolling update in Kubernetes.&lt;/p&gt;
&lt;h3 id="creating-a-docker-image-of-my-blog"&gt;Creating a Docker Image of my Blog&lt;a class="anchor ms-1" href="#creating-a-docker-image-of-my-blog" aria-label="Permalink: Creating a Docker Image of my Blog"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This all assumes that I have a container image of my Hugo blog. Creating this was half the work.&lt;/p&gt;
&lt;p&gt;I had been using a docker-compose file to build my blog; however, this doesn&amp;rsquo;t copy my files into the container it creates a volume to share my files with the container. I needed a Dockerfile that would copy my source code into a container and then save it into a container registry.&lt;/p&gt;
&lt;p&gt;This is the Dockerfile I created. As you can see, it is a two-stage build. First, it takes the Hugo base image, copies my files into it, and builds Hugo. Then the NGINX web server is run, and the default web port 80 is exposed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Step 1: Build the Hugo site&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;floryn90/hugo:0.119.0&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;builder&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Set working directory inside the container&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;WORKDIR&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/src&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Copy site files to the container&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; . .&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Build the Hugo site&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; hugo --minify --config config.toml&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Step 2: Serve with nginx&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;nginx:alpine&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Remove the default nginx static files&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; rm -rf /usr/share/nginx/html/*&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Copy the generated site from the builder stage&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; --from&lt;span style="color:#f92672"&gt;=&lt;/span&gt;builder /src/public /usr/share/nginx/html&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Expose port 80&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXPOSE&lt;/span&gt; &lt;span style="color:#e6db74"&gt;80&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Start nginx&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CMD&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;-g&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;daemon off;&amp;#34;&lt;/span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="benefits"&gt;Benefits&lt;a class="anchor ms-1" href="#benefits" aria-label="Permalink: Benefits"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Repeatable Deployments:&lt;/strong&gt; Easily spin up new environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration Management:&lt;/strong&gt; Override values for different clusters or environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy Updates:&lt;/strong&gt; Upgrade with a single command.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Helm charts have made deploying my Hugo blog to Kubernetes a seamless and efficient process. With features like templating, versioning, and easy updates, Helm is a must-have tool for Kubernetes deployments.&lt;/p&gt;
&lt;p&gt;If you’re managing static sites or microservices, give Helm a try and see how it can simplify your workflow!&lt;/p&gt;
&lt;p&gt;Have you used Helm for static sites or blogs? Share your experience in the comments below!&lt;/p&gt;</description></item><item><title>Learning Kubernetes: A Beginner's Journey</title><link>https://blog-test.funkysi1701.com/posts/2025/learning-kubernetes/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 12 May 2025 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2025/learning-kubernetes/</guid><category term="Kubernetes">Kubernetes</category><category term="Docker">Docker</category><category term="Grafana">Grafana</category><category term="ContainerOrchestration">ContainerOrchestration</category><category term="DevOps">DevOps</category><category term="Microservices">Microservices</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/kubernetes.png"/><description>&lt;p&gt;I know nothing (or very little) about Kubernetes. It is high time I do something to learn more about it. Kubernetes is a powerful tool for managing containerized applications, and it&amp;rsquo;s becoming a must-have skill for developers and DevOps engineers. In this blog, I&amp;rsquo;ll share my journey as a beginner exploring Kubernetes, from running a simple Grafana pod to understanding the basics of &lt;code&gt;kubectl&lt;/code&gt;. Let&amp;rsquo;s dive in!&lt;/p&gt;
&lt;h2 id="what-is-kubernetes"&gt;What is Kubernetes?&lt;a class="anchor ms-1" href="#what-is-kubernetes" aria-label="Permalink: What is Kubernetes?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. If you want to run your containerized applications, you probably want to learn Kubernetes.&lt;/p&gt;
&lt;p&gt;I have worked at least two companies so far in my career that have made use of Kubernetes to run their microservice architecture. Let&amp;rsquo;s take a look at how to use it.&lt;/p&gt;
&lt;h3 id="why-learn-kubernetes"&gt;Why Learn Kubernetes?&lt;a class="anchor ms-1" href="#why-learn-kubernetes" aria-label="Permalink: Why Learn Kubernetes?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Kubernetes is widely used in modern software development for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Microservices&lt;/strong&gt;: Manage and scale multiple services independently.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI/CD Pipelines&lt;/strong&gt;: Automate deployments and rollbacks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Handle traffic spikes by scaling pods up or down.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="docker-desktop"&gt;Docker Desktop&lt;a class="anchor ms-1" href="#docker-desktop" aria-label="Permalink: Docker Desktop"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.docker.com/products/docker-desktop/" target="_blank" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt;
is a tool for running containers, but it also allows running of Kubernetes.&lt;/p&gt;
&lt;p&gt;I am not going to talk through installing docker desktop and getting a Kubernetes cluster set up, for that check out the &lt;a href="https://docs.docker.com/desktop/use-desktop/kubernetes/" target="_blank" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;
however I found it very straightforward.&lt;/p&gt;
&lt;h2 id="kubectl"&gt;kubectl&lt;a class="anchor ms-1" href="#kubectl" aria-label="Permalink: kubectl"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;kubectl is the command line tool for doing everything with Kubernetes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This prints out basic version information, if this works you know Kubernetes must be working.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl config get-contexts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl config use-context docker-desktop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command allows you to switch contexts, to use with docker desktop you want to use the docker-desktop context. At work we have dev and test contexts that can be selected in a similar way.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Context&lt;/strong&gt;: A Kubernetes context is a set of access parameters for a cluster. It allows you to switch between different clusters or environments (e.g., dev, test, production).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get all
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gives you a list of everything that is running in the default namespace, pods, services, deployments etc For a complete list, you can add the &amp;ndash;all-namespaces flag.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Namespace&lt;/strong&gt;: A namespace is a way to organize resources in a Kubernetes cluster, providing isolation between different projects or teams.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="hello-world"&gt;Hello World&lt;a class="anchor ms-1" href="#hello-world" aria-label="Permalink: Hello World"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now what is the equivalent of &amp;ldquo;Hello World&amp;rdquo; for Kubernetes? I think getting a container to run in Kubernetes is a pretty good test.&lt;/p&gt;
&lt;p&gt;Open up VS Code and create a yaml file called grafana.yaml&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;v1&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Specifies the API version for the resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Pod&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Defines the resource type as a Pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;grafana&lt;/span&gt; &lt;span style="color:#75715e"&gt;# The name of the pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;containers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;grafana&lt;/span&gt; &lt;span style="color:#75715e"&gt;# The name of the container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;grafana/grafana:12.0.0&lt;/span&gt; &lt;span style="color:#75715e"&gt;# The container image to use&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;containerPort&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt; &lt;span style="color:#75715e"&gt;# The port exposed by the container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file uses the Grafana container image, which I am familiar with (see &lt;a href="https://blog-test.funkysi1701.com/posts/2025/setting-up-grafana/"&gt;my previous blog posts&lt;/a&gt;
) It&amp;rsquo;s default port is 3000 which you can see is defined in this file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl apply &lt;span style="color:#f92672"&gt;-f&lt;/span&gt; grafana.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This deploys a pod, using the above yaml file.&lt;/p&gt;
&lt;p&gt;You can run the following to find out more about the pod.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl describe pod grafana
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From what I have discovered so far, Kubernetes runs in its own network. So going to localhost:3000 won&amp;rsquo;t work. But you can use port forward to get round this issue.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Port-Forwarding&lt;/strong&gt;: This allows you to access a pod&amp;rsquo;s service on your local machine by forwarding a port from the pod to your localhost.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl port-forward pod/grafana &lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if I try http://localhost:3000/login I see the login page for the Grafana container. A pretty good first test of using Kubernetes.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;Whats next?&lt;a class="anchor ms-1" href="#whats-next" aria-label="Permalink: Whats next?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I want to replace my local deployment of containers that is currently using a docker compose file with Kubernetes. I also want to learn more about &lt;a href="https://helm.sh/" target="_blank" rel="noopener noreferrer"&gt;Helm charts&lt;/a&gt;
as I believe these are an excellent way of packaging up changes to Kubernetes.&lt;/p&gt;
&lt;p&gt;Have you tried running a pod in Kubernetes? What challenges did you face, and how did you overcome them? Share your thoughts in the comments below!&lt;/p&gt;</description></item><item><title>Getting started with OpenTelemetry</title><link>https://blog-test.funkysi1701.com/posts/2025/getting-started-with-opentelemetry/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 05 May 2025 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2025/getting-started-with-opentelemetry/</guid><category term="OpenTelemetry">OpenTelemetry</category><category term="Observability">Observability</category><category term="Tracing">Tracing</category><category term="Metrics">Metrics</category><category term="Logging">Logging</category><category term="DotNet">DotNet</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/open-telemetry.png"/><description>&lt;h2 id="what-is-opentelemetry"&gt;What is OpenTelemetry?&lt;a class="anchor ms-1" href="#what-is-opentelemetry" aria-label="Permalink: What is OpenTelemetry?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;OpenTelemetry is an open-source observability framework that provides a unified way to collect, process, and export telemetry data such as &lt;strong&gt;traces&lt;/strong&gt;, &lt;strong&gt;metrics&lt;/strong&gt;, and &lt;strong&gt;logs&lt;/strong&gt;. It is designed to help developers monitor and debug distributed systems by providing insights into application performance and behavior.&lt;/p&gt;
&lt;p&gt;With OpenTelemetry, you can instrument your applications to gain visibility into how requests flow through your system, identify bottlenecks, and troubleshoot issues effectively.&lt;/p&gt;
&lt;h2 id="why-use-opentelemetry"&gt;Why Use OpenTelemetry?&lt;a class="anchor ms-1" href="#why-use-opentelemetry" aria-label="Permalink: Why Use OpenTelemetry?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are some key benefits of using OpenTelemetry:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Unified Observability&lt;/strong&gt;: Collect traces, metrics, and logs using a single framework.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vendor-Neutral&lt;/strong&gt;: Export telemetry data to any backend, such as Azure Monitor, Grafana, or Prometheus.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standardized APIs&lt;/strong&gt;: Use consistent APIs and SDKs across multiple programming languages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensibility&lt;/strong&gt;: Easily extend OpenTelemetry to meet your specific observability needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community-Driven&lt;/strong&gt;: Backed by a large and active open-source community.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="key-components-of-opentelemetry"&gt;Key Components of OpenTelemetry&lt;a class="anchor ms-1" href="#key-components-of-opentelemetry" aria-label="Permalink: Key Components of OpenTelemetry"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;OpenTelemetry consists of the following core components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Traces&lt;/strong&gt;: Capture the lifecycle of a request as it flows through your system. Traces help you understand dependencies and latency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metrics&lt;/strong&gt;: Collect numerical data, such as request counts, CPU usage, and memory consumption, to monitor system health.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logs&lt;/strong&gt;: Record discrete events, such as errors or state changes, to provide additional context for debugging.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="setting-up-opentelemetry-in-net"&gt;Setting Up OpenTelemetry in .NET&lt;a class="anchor ms-1" href="#setting-up-opentelemetry-in-net" aria-label="Permalink: Setting Up OpenTelemetry in .NET"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s how you can get started with OpenTelemetry in a .NET application:&lt;/p&gt;
&lt;h3 id="step-1-install-the-required-nuget-packages"&gt;Step 1: Install the Required NuGet Packages&lt;a class="anchor ms-1" href="#step-1-install-the-required-nuget-packages" aria-label="Permalink: Step 1: Install the Required NuGet Packages"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Run the following commands to install the OpenTelemetry libraries:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dotnet add package OpenTelemetry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dotnet add package OpenTelemetry.Extensions.Hosting
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dotnet add package OpenTelemetry.Exporter.Console
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="step-2-configure-opentelemetry-in-your-application"&gt;Step 2: Configure OpenTelemetry in Your Application&lt;a class="anchor ms-1" href="#step-2-configure-opentelemetry-in-your-application" aria-label="Permalink: Step 2: Configure OpenTelemetry in Your Application"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Add the following code to your Program.cs or Startup.cs file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; OpenTelemetry;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; OpenTelemetry.Trace;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; OpenTelemetry.Metrics;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; builder = WebApplication.CreateBuilder(args);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Add OpenTelemetry tracing and metrics&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.Services.AddOpenTelemetry()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithTracing(tracerProviderBuilder =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tracerProviderBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddAspNetCoreInstrumentation()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddHttpClientInstrumentation()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddConsoleExporter(); &lt;span style="color:#75715e"&gt;// Export traces to the console&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithMetrics(metricsProviderBuilder =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; metricsProviderBuilder
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddAspNetCoreInstrumentation()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddRuntimeInstrumentation()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddConsoleExporter(); &lt;span style="color:#75715e"&gt;// Export metrics to the console&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; app = builder.Build();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app.MapGet(&lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;, () =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Hello, OpenTelemetry!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app.Run();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="step-3-run-your-application"&gt;Step 3: Run Your Application&lt;a class="anchor ms-1" href="#step-3-run-your-application" aria-label="Permalink: Step 3: Run Your Application"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Start your application and observe the telemetry data in the console. You’ll see traces and metrics being logged as requests are processed.&lt;/p&gt;
&lt;h2 id="aspire-and-how-to-view-telemetry"&gt;Aspire and how to view Telemetry&lt;a class="anchor ms-1" href="#aspire-and-how-to-view-telemetry" aria-label="Permalink: Aspire and how to view Telemetry"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your .NET code is .Net 8 or higher you can use Aspire which configures OpenTelemetry for free! Check out &lt;a href="https://blog-test.funkysi1701.com/posts/2024/aspire"&gt;Getting started with .Net Aspire&lt;/a&gt;
. Once Aspire is setup, you will be able to see Logs, Traces and Metrics in the Aspire Dashboard.&lt;/p&gt;
&lt;p&gt;Another popular way to view your data is Grafana, where you can create custom dashboards. I have talked about adding &lt;a href="https://blog-test.funkysi1701.com/posts/2025/opentelemetry-logs/"&gt;Logs&lt;/a&gt;
to Grafana recently.&lt;/p&gt;
&lt;p&gt;There are lots of other ways to view your data, like Application Insights, DataDog, Jaeger, New Relic and many more.&lt;/p&gt;
&lt;p&gt;But you are not tied to one solution, you can send your data to more than one of these if you wish.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;OpenTelemetry simplifies observability by providing a unified framework for collecting traces, metrics, and logs. Whether you&amp;rsquo;re building microservices, monitoring distributed systems, or debugging performance issues, OpenTelemetry is a powerful tool to have in your arsenal.&lt;/p&gt;
&lt;p&gt;Start using OpenTelemetry today and gain deeper insights into your applications!&lt;/p&gt;
&lt;p&gt;Have you tried OpenTelemetry? Share your experiences and tips in the comments below!&lt;/p&gt;</description></item></channel></rss>