[{"content":"This is a Test Post This is a test post that I am using to test my My Notion → Hugo Publishing Setup\nI\u0026rsquo;m currently trying to get my blog setup to work a little differently. Instead of writing a post directly in Hugo, I want to be able to write it in Notion, mark it as published and let the rest happen automatically.\nWhat I\u0026rsquo;m Testing There are a few things I want to make sure are working together:\nNotion: where I\u0026rsquo;m writing and managing my posts\nNotion API: allowing my sync script to read the database and published posts\nPython sync script: converting the Notion content into Hugo Markdown\nGitHub Actions: running the sync automatically\nGit: committing and pushing the generated files\nHugo: taking those Markdown files and turning them into the actual blog\nImages: checking that images inside Notion are downloaded and placed in the right location\nFrontmatter: making sure things like title, date, description, tags, and slug make their way from Notion into Hugo correctly\nWhat I\u0026rsquo;m Hoping Happens Ideally, I should be able to write something in Notion, mark it as Ready, and then just wait.\nThe workflow should take care of the rest.\nI\u0026rsquo;m honestly pretty excited to see this work because I\u0026rsquo;ve spent quite some time to understand how this pipeline works.\nIf This Actually Works\u0026hellip; If this works properly, I\u0026rsquo;ll probably write a separate blog post about the whole setup.\nI will document how I put everything together: i.e. Notion → API → Python → GitHub Actions → Hugo\nThat will probably be more interesting than this test post anyway.\nFor now, though\u0026hellip;\n**This is me testing whether the system works as expected. **\n","permalink":"https://arnabnandi.com/posts/testing-notion-hugo-publishing-setup/","summary":"\u003ch2 id=\"this-is-a-test-post\"\u003eThis is a Test Post\u003c/h2\u003e\n\u003cp\u003eThis is a test post that I am using to test my My Notion → Hugo Publishing Setup\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;m currently trying to get my blog setup to work a little differently. Instead of writing a post directly in Hugo, I want to be able to write it in \u003cstrong\u003eNotion\u003c/strong\u003e, mark it as published and let the rest happen automatically.\u003c/p\u003e\n\u003ch3 id=\"what-im-testing\"\u003eWhat I\u0026rsquo;m Testing\u003c/h3\u003e\n\u003cp\u003eThere are a few things I want to make sure are working together:\u003c/p\u003e","title":"This is a Test Post"},{"content":"Hello World, I am Arnab!\nThis is my little corner of the internet where I write about things I am currently interested in. I would like to think of this as a place where I grow ideas, curate thoughts and put things down before they slip away.\nI’ll be honest, I’m not very good at sharing ideas. It doesn’t come naturally to me. Most of the time, I have a lot of things going on in my head but turning them into something that makes sense and putting them into words is a different story.\nBut I want to get better at it.\nSo I’m trying to spend a little more time sitting with what I learn, understanding things properly and writing them down. Maybe someone else will find something useful here or maybe I’ll come back months later and find something that reminds me of what I was learning back then.\nLately, a lot of that learning has been around open source. I’m currently contributing to a Kubernetes subproject, node-readiness-controller, and trying to understand everything around it i.e. how projects work, how people contribute and how much there is that I still don’t know.\nOutside of that, I am into reading books, fiction and non fiction. You can read about my current reads here.\nThis is me trying to make sense of some of it.\nAs for this place, it’s still a work in progress, like most good things are\u0026hellip;\nCome in, look around.\n","permalink":"https://arnabnandi.com/about/","summary":"\u003cp\u003eHello World, I am Arnab!\u003c/p\u003e\n\u003cp\u003eThis is my little corner of the internet where I write about things I am currently interested in. I would like to think of this as a place where I grow ideas, curate thoughts and put things down before they slip away.\u003c/p\u003e\n\u003cp\u003eI’ll be honest, I’m not very good at sharing ideas. It doesn’t come naturally to me. Most of the time, I have a lot of things going on in my head but turning them into something that makes sense and putting them into words is a different story.\u003c/p\u003e","title":"Welcome!"},{"content":"Introduction: Why I\u0026rsquo;m Writing This Hi! This is where I write about the lessons that I learn from open source contributions! This is not a polished \u0026ldquo;here\u0026rsquo;s how to contribute to open source\u0026rdquo; tutorial written by someone who has done it a hundred times.\nThe project is Minikube, the tool that lets you run a Kubernetes cluster on your local machine for development and testing. The contribution I worked on was adding Node Readiness Controller (NRC) as a Minikube addon, so that anyone in the world can type minikube start --addons=nrc and have it just work.\nIf you are new to open source, new to Kubernetes, or new to Go, I\u0026rsquo;ll try to explain every concept as I go. Nothing will be assumed. And I\u0026rsquo;ll be completely honest about where I got stuck because I think that\u0026rsquo;s the most useful thing I can share.\nWhat Is Minikube? And What Is an Addon? To be honest, I had previously worked with minikube and had basic knowledge about what it was. I’ll take a moment and introduce it, in case you are new to this.\nMinikube is a tool that runs a full Kubernetes cluster on your laptop, inside a Docker container or a virtual machine. Real Kubernetes clusters run on multiple physical servers in data centers. Minikube simulates all of that on a single machine so developers can test their applications locally without needing cloud infrastructure.\nAddons are optional features you can switch on or off inside your Minikube cluster. Examples include a web dashboard for your cluster, an ingress controller for routing traffic or a metrics server for monitoring. You enable them with a single command like minikube addons enable dashboard.\nWhen you enable an addon, Minikube reads a set of Kubernetes YAML files it has stored internally, applies them to the cluster, and the feature starts running. The list of known addons, and the YAML instructions for each one all live inside the Minikube source code itself.\nMy job was to add Node Readiness Controller to that list.\nWhat Is the Node Readiness Controller (NRC)? NRC is a Kubernetes controller built by the Kubernetes SIGs (Special Interest Groups) community. Its job is to make sure that nodes i.e. the machines in your cluster, are truly ready before any workloads land on them.\nHere\u0026rsquo;s the problem it solves: when a node joins a Kubernetes cluster, Kubernetes marks it as \u0026ldquo;Ready\u0026rdquo; fairly quickly. But \u0026ldquo;Ready\u0026rdquo; from Kubernetes perspective just means the node\u0026rsquo;s basic processes are running. It doesn\u0026rsquo;t mean the GPU driver is loaded, or the network agent has finished initializing, or whatever custom infrastructure dependency your workload needs.\nNRC fills that gap. It lets you define custom readiness rules i.e. \u0026ldquo;this node is only ready when condition X is true\u0026rdquo; and it automatically applies taints (essentially a \u0026ldquo;DO NOT SCHEDULE HERE\u0026rdquo; sticky note) to nodes that don\u0026rsquo;t yet meet those conditions. When the conditions are met, it removes the taint, and workloads can flow in.\nFor the Minikube addon specifically, the goal was to run NRC in a control-plane co-located model. This means NRC runs on the same node as Kubernetes own system components, and starts up before any user workloads. This makes it useful for testing device-driver readiness scenarios, GPU/TPU simulation, and other infrastructure-level readiness checks i.e. all things that Minikube is increasingly being used for.\nThe First Confusion: Which Repository Does This Go Into? This was genuinely the first thing I got confused about and I think it trips up a lot of beginners.\nNRC has its own GitHub repository at github.com/kubernetes-sigs/node-readiness-controller. It has its own source code, its own container image published to registry.k8s.io, and its own documentation. So my initial instinct was: \u0026ldquo;I should open a PR in the NRC repo.\u0026rdquo;\nIt did not take much time to figure out that it was a wrong idea.\nThe PR goes into Minikube\u0026rsquo;s repository (github.com/kubernetes/minikube). Here’s how I looked at it:\nNRC\u0026rsquo;s team has already done their work. They built the controller, compiled it into a container image, and published it to a public registry. That image is sitting on the internet right now, ready to be pulled.\nWhat doesn\u0026rsquo;t exist yet is Minikube knowing about NRC. Minikube has never heard of NRC. If you typed minikube start --addons=nrc today, it would fail immediately saying the addon doesn\u0026rsquo;t exist.\nMy PR is teaching Minikube about NRC. I\u0026rsquo;m not changing NRC at all. I\u0026rsquo;m adding Minikube\u0026rsquo;s instructions for how to deploy NRC when someone asks for it. Those instructions live in the Minikube repo.\nOnce this PR merges (🤞), whenever someone enables the NRC addon, Minikube reads the instructions I added, creates some Kubernetes objects in the cluster, and pulls NRC\u0026rsquo;s container image from registry.k8s.io. NRC\u0026rsquo;s own codebase is never touched.\nUnderstanding Minikube\u0026rsquo;s Addon Architecture Before writing a single line, I spent time reading how existing addons were structured. I figured this was a non-negotiable as you cannot write an addon without understanding the pattern.\nHere\u0026rsquo;s what I found. The Minikube codebase has a very specific two-layer system:\nLayer 1: The YAML files: Inside deploy/addons/, there is one folder per addon. Each folder contains Kubernetes manifest files i.e. YAML files describing what to create in the cluster. But these aren\u0026rsquo;t plain YAML. They use Go template syntax, with placeholders like {{.Images.SomeName}} that get filled in at runtime.\nLayer 2: The Go registration: In pkg/minikube/assets/addons.go, there is a large Go map where every addon is registered. Each entry points to the YAML files and provides metadata like the addon name, the container image to use, the registry it comes from, and documentation links.\nThere\u0026rsquo;s also a third piece: deploy/addons/assets.go which uses Go\u0026rsquo;s embed package to bake all the YAML files directly into the compiled Minikube binary. This is why you can install Minikube as a single binary and it works everywhere without needing external files, all the addon YAML is inside the binary itself.\nEvery addon is the product of all three pieces working together. If any one of them is wrong or inconsistent, the addon fails.\nWriting the Actual Files Step 1: Reading NRC\u0026rsquo;s Real Manifests First The most important thing I did before writing anything was go read NRC\u0026rsquo;s own source repository. Specifically, I looked at how NRC deploys itself, what Kubernetes objects it needs, what permissions it requires, what container image it uses, and what configuration flags it accepts.\nThis is not optional. You cannot write correct addon files for a project you haven\u0026rsquo;t read. Everything you write in Minikube is derived from what the project itself specifies. You\u0026rsquo;re not inventing how NRC works, you\u0026rsquo;re translating its existing deployment into Minikube\u0026rsquo;s format.\nNRC deploys with two sets of files:\nA CRD (Custom Resource Definition): this teaches Kubernetes about a new type of object called NodeReadinessRule A deployment manifest: this runs the actual NRC controller, along with its RBAC (permissions) setup I used these as my source of truth for the Minikube addon files.\nStep 2: Creating the Addon Directory mkdir deploy/addons/nrc One command. But knowing why this directory exists, what goes in it, and how it connects to the rest of the system\nStep 3: Writing the YAML Template Files I created two files:\ndeploy/addons/nrc/crds.yaml the CRD definition, copied from NRC\u0026rsquo;s release. No template syntax needed here because it has no container image reference. deploy/addons/nrc/nrc.yaml.tmpl the deployment, RBAC, and service account. This one uses template syntax for the image reference. The .tmpl extension on the second file is what tells Minikube\u0026rsquo;s build system \u0026ldquo;this file needs Go template rendering before it\u0026rsquo;s applied to the cluster.\u0026rdquo;\nThe critical line inside nrc.yaml.tmpl is the image reference:\nimage: {{.CustomRegistries.NrcController | default .Registries.NrcController}}{{.Images.NrcController}} This looks intimidating but it\u0026rsquo;s actually straightforward once you decode it: (Note: this is the reason why CI checks failed for me when I pushed my PR initially)\nTry .CustomRegistries.NrcController first: if the user has specified a custom registry (useful for air-gapped environments or private registries), use that If not, fall back to .Registries.NrcController the default registry I registered in the Go code Append .Images.NrcController the full image path with tag and sha256 digest The key name NrcController is just a string I chose, it must be identical in the template and in the Go registration maps.\nStep 4: The Go Registration In pkg/minikube/assets/addons.go, I added:\n\u0026#34;nrc\u0026#34;: NewAddon([]*BinAsset{ MustBinAsset(addons.NrcAssets, \u0026#34;nrc/crds.yaml\u0026#34;, vmpath.GuestAddonsDir, \u0026#34;crds.yaml\u0026#34;, \u0026#34;0640\u0026#34;), MustBinAsset(addons.NrcAssets, \u0026#34;nrc/nrc.yaml.tmpl\u0026#34;, vmpath.GuestAddonsDir, \u0026#34;nrc.yaml\u0026#34;, \u0026#34;0640\u0026#34;), }, false, \u0026#34;nrc\u0026#34;, \u0026#34;node-readiness-controller (SIGs)\u0026#34;, \u0026#34;\u0026#34;, \u0026#34;https://node-readiness-controller.sigs.k8s.io/\u0026#34;, map[string]string{ \u0026#34;NrcController\u0026#34;: \u0026#34;node-readiness-controller/node-readiness-controller:v0.3.0@sha256:5b3e69...\u0026#34;, }, map[string]string{ \u0026#34;NrcController\u0026#34;: \u0026#34;registry.k8s.io\u0026#34;, }, nil), And in deploy/addons/assets.go, I added the embed directive:\n// NrcAssets assets for nrc addon //go:embed nrc/* var NrcAssets embed.FS And in pkg/addons/config.go, I added the config entry so the addon appears in minikube addons list:\n{ name: \u0026#34;nrc\u0026#34;, set: SetBool, callbacks: []setFn{EnableOrDisableAddon}, }, The Pain Points None of the above went smoothly the first time. Let’s walk through some of the failures.\nFailure 1: The very first time I tried to run ./out/minikube addons list, the binary failed immediately:\npanic: Failed to define asset nrc/nrc.yaml.tmpl: open nrc/nrc.yaml.tmpl: file does not exist I had renamed the file in my Go code to use the .tmpl extension, but the actual file on disk was still called nrc.yaml. The Go embed system was looking for nrc.yaml.tmpl inside the embedded filesystem and couldn\u0026rsquo;t find it.\nThe fix was simply renaming the file on disk:\nmv deploy/addons/nrc/nrc.yaml deploy/addons/nrc/nrc.yaml.tmpl Simple fix, but it taught me that the filename in MustBinAsset(...), the filename on disk, and the embed directive in assets.go are all a three-way contract. All three must say the exact same thing. If any one of them diverges, you get a panic.\nFailure 2: ImagePullBackOff After getting past the panic, I enabled the addon and watched the pod go into ImagePullBackOff. I ran kubectl describe pod and saw this:\nPulling image \u0026#34;node-readiness-controller/node-readiness-controller:v0.3.0@sha256:...\u0026#34; Failed to pull image \u0026#34;node-readiness-controller/...\u0026#34;: pull access denied, repository does not exist The image it was trying to pull had no registry prefix. Instead of registry.k8s.io/node-readiness-controller/..., it was just node-readiness-controller/.... Docker interpreted that as a Docker Hub image, which doesn\u0026rsquo;t exist.\nThe root cause was in my template line. I had originally written:\nimage: {{.CustomRegistries.NrcController | default .ImageRepository}}{{.Images.NrcController}} The problem is .ImageRepository that\u0026rsquo;s Minikube\u0026rsquo;s global image repository override, not the default registry for this specific addon. In a normal minikube start without any flags, .ImageRepository is empty. So the registry prefix was resolving to an empty string, and the image path was being used alone.\nThe fix was to use .Registries.NrcController as the fallback instead, which is populated from the registries map I registered in Go:\nimage: {{.CustomRegistries.NrcController | default .Registries.NrcController}}{{.Images.NrcController}} Failure 3: Missing the Version Tag in the Image String This one was subtle. I had registered the image in addons.go as:\n\u0026#34;NrcController\u0026#34;: \u0026#34;node-readiness-controller/node-readiness-controller@sha256:5b3e69...\u0026#34;, Notice there\u0026rsquo;s no :v0.3.0 tag, just the digest. This is technically a valid image reference format (digest-only), but containerd and CRI-O, the two runtimes the CI tests use, can be stricter about this than Docker is. Some configurations reject digest-only references.\nEvery other image in Minikube\u0026rsquo;s addons.go follows the format image-path:tag@sha256:digest. The format exists for a reason that the tag makes the reference human-readable and widely compatible, while the digest ensures it\u0026rsquo;s immutable and pinned.\nThe fix:\n\u0026#34;NrcController\u0026#34;: \u0026#34;node-readiness-controller/node-readiness-controller:v0.3.0@sha256:5b3e69...\u0026#34;, CI Failures: What They Were and What They Meant Once I pushed my PR, three CI tests failed: (Note: In most Kubernetes repositories, CI isn’t triggered automatically for new contributors, you typically need a maintainer to comment /ok-to-test. However, as an org member, CI ran immediately on PR creation, which definitely speeds things up.)\npull-minikube-docker-containerd-linux-x86 Required: true pull-minikube-kvm-docker-linux-x86 Required: true pull-minikube-docker-crio-linux-x86 Required: false These are end-to-end integration tests that actually start a real Minikube cluster in CI and run the addon through its full lifecycle. They run across different combinations of container runtimes (containerd, Docker, CRI-O) and drivers (Docker, KVM).\nThe two marked Required: true are merge blockers and the PR cannot be merged while they\u0026rsquo;re red.\nAll three were failing because of the image reference issues described above (missing registry prefix, missing version tag). Once I fixed those locally, verified with kubectl describe pod that the pod was reaching Running state, and pushed the fixes, it retriggered the CI\nMinikube\u0026rsquo;s CI system (Prow) picks it up and retriggers only the required failing tests.\nThe Control-Plane Co-location Model One part of the PR that I want to explain clearly because it\u0026rsquo;s conceptually important: the way NRC is deployed on the control-plane node specifically.\nIn a Kubernetes cluster, there are two kinds of nodes. The control-plane node runs Kubernetes\u0026rsquo; own system components i.e. the API server, the scheduler, the controller manager. The worker nodes run user workloads. By default, Kubernetes prevents user workloads from landing on the control-plane node by applying a \u0026ldquo;taint\u0026rdquo; essentially a label that says \u0026ldquo;nothing should be scheduled here unless it explicitly tolerates this taint.\u0026rdquo;\nFor NRC to run before any user workloads, it needs to be on the control-plane node. To achieve this, the deployment YAML needs two specific fields:\ntolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule nodeSelector: node-role.kubernetes.io/control-plane: \u0026#34;\u0026#34; The toleration says \u0026ldquo;I accept the control-plane taint, so I\u0026rsquo;m allowed to run there.\u0026rdquo; The nodeSelector says \u0026ldquo;I specifically require running on a control-plane node.\u0026rdquo; Together they ensure NRC lands on the control-plane node and nowhere else.\nAdditionally, the priorityClassName: system-cluster-critical field gives NRC the same scheduling priority as core system components like CoreDNS. This ensures that even under resource pressure, NRC stays running and isn\u0026rsquo;t evicted.\nThe Minikube Addon Official Guide: And What It Doesn\u0026rsquo;t Tell You Minikube has an official guide for adding addons at minikube.sigs.k8s.io/docs/contrib/addons/. I read it carefully and it\u0026rsquo;s genuinely useful, it tells you which files to touch and which commands to run.\nBut it assumes a lot of background knowledge. It says \u0026ldquo;add your manifest YAMLs\u0026rdquo; without explaining what format they need to be in, or what labels are required, or why. It mentions the embed directive without explaining what embedding even means. It says \u0026ldquo;run make \u0026amp;\u0026amp; make test\u0026rdquo; without explaining what the output means or what to do if it fails.\nThe guide is correct. It\u0026rsquo;s just dense. Everything it says is true and important. But for someone new to Go, new to Kubernetes, and new to open source codebases of this scale, the gap between reading the guide and knowing what to actually do is significant.\nWhat helped me most was reading real, working addons in the codebase. I opened deploy/addons/metrics-server/ and stared at it until I understood every line. I found the metrics-server entry in addons.go and decoded every argument to NewAddon(...).\nRaising the PR After all the local testing passed the pod was Running, the addon appeared in minikube addons list, the disable/enable cycle worked cleanly, I pushed the branch and opened the PR.\nThe PR description matters. Reviewers are busy people. A good description tells them what the PR does, why it exists, how you tested it, and what they should pay attention to. I included:\nWhat the addon does Why it belongs in Minikube The control-plane co-location detail and why it matters My testing steps and their results Links to the NRC project Closing Thoughts I want to be honest about something: this contribution is not technically complex. It\u0026rsquo;s a handful of YAML files, a few lines of Go to register them, and an embed directive. Experienced contributors could probably do this in a couple of hours.\nFor me it took much longer because I was learning while doing. I am not proficient in Go (Golang). I didn\u0026rsquo;t know how Minikube\u0026rsquo;s template rendering worked.\nEvery one of those things is now something I know.\nOpen source projects like Kubernetes and Minikube can feel impossibly large and intimidating from the outside. The codebase is enormous. The concepts are deep. The community is full of people who have been doing this for years.\nBut every one of those people also had a first PR. Every one of them also got confused about something that now seems obvious to them. The project exists because people decided to start somewhere and figure it out as they went.\nI am very much still figuring things out. But I have a PR open against a real project that real people use. And that is a start.\nIf you are thinking about making your first open source contribution and you\u0026rsquo;re not sure where to begin, find a project you use, find an issue labeled good first issue, read the existing code more than you read the documentation, and be patient with yourself when things break. They will break. That\u0026rsquo;s where the learning is.\nThank you for reading.\n","permalink":"https://arnabnandi.com/posts/01-minikube-addon/","summary":"\u003ch2 id=\"introduction-why-im-writing-this\"\u003eIntroduction: Why I\u0026rsquo;m Writing This\u003c/h2\u003e\n\u003cp\u003eHi! This is where I write about the lessons that I learn from open source contributions! This is not a polished \u0026ldquo;here\u0026rsquo;s how to contribute to open source\u0026rdquo; tutorial written by someone who has done it a hundred times.\u003c/p\u003e\n\u003cp\u003eThe project is \u003cstrong\u003eMinikube,\u003c/strong\u003e the tool that lets you run a Kubernetes cluster on your local machine for development and testing. The contribution I worked on was adding \u003cstrong\u003eNode Readiness Controller (NRC)\u003c/strong\u003e as a Minikube addon, so that anyone in the world can type \u003ccode\u003eminikube start --addons=nrc\u003c/code\u003e and have it just work.\u003c/p\u003e","title":"Adding a Minikube Addon from Scratch"},{"content":"I started a little notebook on the internet.\nI turned a year older on 14th April, and I randomly had the thought that maybe I should buy myself a domain. It felt like a nice idea.\nLately, I have been spending a lot of time on open source, Kubernetes, learning new stuff, and job hunting. It has been good, but at the same time it has also been mentally exhausting. Too many things to think about, too many things I want to figure out.\nThis had been in my backlog for a while.\nI wanted a place where I could put things down without overthinking them too much. Things I am learning, things that excite me, random thoughts, things from life, or just something I do not want to forget later.\nIt took me some time to get used to how Hugo works, and setting everything up was honestly confusing and a lot of trial and error. But somehow it all came together into a working website, where all the links work, I hope.\nSome posts might be technical. Some might just be thoughts from a random evening. Some might simply exist because I felt like writing them. Some may just exist because they mattered to me in that moment.\nI do not know exactly what this space will become yet. Maybe notes, maybe stories, maybe technical deep dives, maybe just thoughts from long days. For now, it is simply a place where I can put things down and come back to them later.\n-Arnab\n","permalink":"https://arnabnandi.com/posts/00-hello-world/","summary":"\u003cp\u003eI started a little notebook on the internet.\u003c/p\u003e\n\u003cp\u003eI turned a year older on 14th April, and I randomly had the thought that maybe I should buy myself a domain. It felt like a nice idea.\u003c/p\u003e\n\u003cp\u003eLately, I have been spending a lot of time on open source, Kubernetes, learning new stuff, and job hunting. It has been good, but at the same time it has also been mentally exhausting. Too many things to think about, too many things I want to figure out.\u003c/p\u003e","title":"Hello, World!"}]