All posts by Thiyagu

Boost Application Reliability with Kubernetes postStart Hooks (Real-World Examples Inside)

Introduction

Hooks allow developers to run custom logic at critical points in a container’s lifecycle. These hooks help with initialization and graceful shutdown, ensuring applications are reliable, performant, and consistent. In this article, we’ll explore lifecycle hooks in Kubernetes, with a focus on the postStart hook, real-world use cases, and practical examples using Windows IIS containers.

Types of Hooks in Kubernetes

Kubernetes offers two primary lifecycle hooks for containers:

postStart Hook:

Triggered immediately after a container is started.

Commonly used for initializing services, setting up configurations, or performing other preparatory tasks before the application is fully operational. PostStart Hook provides us ability to perform some task before the pod is completely initialized. This hook is executed immediately after a container is created. However, there is no guarantee that the hook will execute before the container ENTRYPOINT command. This is useful for scenarios where you want to perform some setup before the main container in the pod starts running.

preStop Hook:

Triggered just before a container is terminated.

Often used to gracefully shut down services, close connections, or clean up resources to ensure data integrity and prevent resource leaks. This is particularly useful for applications that need to gracefully shut down, ensuring that ongoing processes complete before the container stops. Examples of tasks include closing database connections, finalizing transactions, or notifying external systems about impending shutdown.

In this post, we are going to discuss more deep in to the postStart Hook

Use Case : When and Where is the postStart Hook Required?

The postStart lifecycle hook is useful in scenarios where specific tasks need to be performed before the main application in a container becomes functional. Some common use cases include:

Environment Setup: Copying necessary files or templates. Modifying configuration files dynamically based on the environment.

Application Warm-up: Performing application-specific warm-up tasks to reduce the latency of initial requests.

Service Initialization: Setting up dependencies or configurations required by the application. Starting background services or processes necessary for the container’s operation.

Example Scenario

Consider a scenario where an ASP.NET application hosted on IIS requires a startup script (startup.ps1) to configure IIS settings, initialize application-specific environment configuration substitution, or perform other preparatory tasks. Using the postStart hook ensures that these configurations are executed as soon as the container starts.

Configuring the postStart Lifecycle Hook

Here’s an example Kubernetes pod specification that uses the postStart lifecycle hook to execute a PowerShell script: In the provided example, the postStart hook logs a message to C:\poststart.log in a Windows IIS container, confirming successful initialization. By leveraging postStart hooks, you can add flexibility and control to your containerized applications, ensuring they are fully prepared to handle their workloads upon startup.

For this example, i had explain with simple logging the message in the poststart. Based on requirement, you can have .ps1 (startup.ps1)/configuration file to execute during the container creation.

Example 1: Create Simple log file in PostStart

STEP 1: Create the pod using below YAML

Save the below YAML as iis-pod and run the below kubectl cmd to create the pods in AKS, as shown in the STEP 2

kind: Pod
metadata:
name: iis-pod
spec:
containers:
- name: iis-container
image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
lifecycle:
postStart:
exec:
command:
- cmd
- /c
- echo PostStart hook executed > C:\poststart.log
ports:
- containerPort: 80
#Execute the YAML to create the pod
kubectl create -f iis-pod.yaml

STEP 2: Check the pod status

Execute the below Kubectl comments to ensure pod is running successfully.

# Command to get pods’ status:

kubectl get pods

# Command to view the details of Pod:

kubectl describe pod iis-pod

STEP 3: Get in to the pod to verify poststart.log file

The postStart hook executes the specified command and the text “PostStart hook executed” is written to the file C:\poststart.log. The container initializes and becomes ready to handle requests on port 80

Explanation of the Configuration (Command Breakdown)

  • The exec : field specifies the command to be executed:
  • cmd: Specifies the Windows Command Prompt as the executor.
  • /c: Tells the Command Prompt to execute the provided command and then terminate.
  • echo PostStart hook executed > C:\poststart.log: Writes the text “PostStart hook executed” into the file C:\poststart.log. If the file does not exist, it is created automatically. If it exists, the content is overwritten.
  • Port 80 : The container exposes port 80, which is the default HTTP port for IIS.
# Enter in to the pod using Kubectl
kubectl exec -n default iis-pod -it -- powershell

Example 2: Create Warmup in PostStart

The postStart hook waits 5 seconds for IIS to initialize. It sends an HTTP GET request to http://localhost to ensure the default page is accessible and finally the HTTP response is saved to C:\warmup.log, which can be inspected for debugging or verification.

Explanation of the Configuration (Command Breakdown)

  • Start-Sleep -Seconds 5; : Introduces a short delay to ensure IIS has started before making a request.
  • Invoke-WebRequest -Uri http://localhost: Sends an HTTP request to the IIS default page hosted on the same container.
  • Out-File -FilePath C:\warmup.log -Force; : Saves the HTTP response to the file C:\warmup.log. The -Force option ensures the file is created or overwritten if it exists.
  • Error Handling: A try block handles successful execution, and the catch block logs errors if the warm-up process fails.
  • Ports 80: The container exposes port 80, which is used by IIS to serve the application.
apiVersion: v1
kind: Pod
metadata:
name: iis-pod-warmup
spec:
containers:
- name: iis-container
image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
lifecycle:
postStart:
exec:
command:
- powershell
- '-Command'
- >
try {
Start-Sleep -Seconds 5; # Wait for IIS to start
Invoke-WebRequest -Uri http://localhost -UseBasicParsing | Out-File -FilePath C:\warmup.log -Force;
Write-Host "Warm-up request completed successfully.";
} catch {
Write-Error "Warm-up request failed: $_";
}
ports:
- containerPort: 80

Output

Conclusion

Kubernetes lifecycle hooks like postStart give developers greater control over container startup behavior. Whether you’re initializing services, warming up applications, or preparing IIS environments, hooks can significantly improve reliability and user experience.

 

Mastering the Kubernetes kubectl Patch Command with Examples in Azure AKS

Managing Kubernetes resources efficiently is essential for scalable cloud-native applications. The kubectl patch command lets you quickly update running Kubernetes resources — such as labels, container images, or replicas — without redeploying entire configurations. In this article, you’ll learn how to use kubectl patch within Azure Kubernetes Service (AKS), complete with practical examples.

What is the kubectl patch Command?

Patch is a command line option for updating Kubernetes API objects. You can use it to update a running configuration. You do this by supplying it with the section to update, instead of a completely new configuration, as you would with kubectl apply.

The command works by “patching” changes onto the current resource configuration. Unlike a kubectl replace operation, the patch operation only modifies specific fields in the resource configuration.

What can we do using Kubectl patch command?

With kubectl patch, you can quickly fix issues with updating the name, image, label, replicas, affinity/tolerations, environment variables, configaps, secrets, volumes, ports, etc. kubectl patch supports YAML and JSON formats. Using either format, you can drill into the specific field of the resource and change it to your desired value. Kubectl supports three different patching strategies: Strategic Merge (the default) and JSON Merge. You utilize these formats through the patching strategy.

“kubectl patch supports three strategies: Strategic Merge Patch (default), JSON Merge Patch, and JSON Patch. Each has different use cases depending on the complexity of your update.”

Sample deployment YAML file

Let’s say we have the following Nginx deployment YAML file, we originally had only one label (environment: prod), and we want to add a new label to specify the app we are running (app: nginx). We will use the –patch command to enter the new labels:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.14.2
          ports:
            - containerPort: 80

Example 1: Patch the label to the deployment

Method 1: Patch using Inline JSON 

In our case, we would like to add environment for the deployment as prod, for this we would run the following command to add the new labels:

kubectl patch deployment nginx-deployment --patch '{\"metadata\": {\"labels\": {\"environment\": \"prod\"}}}'

For the patch command to work, you must correctly include the map and lists in the original YAML file, so Kubernetes knows exactly where to go to add/update the new value properly.

We are going to discuss very simple example of using the kubectl patch command to update fields in your Kubernetes deployment file.

If you want to patch from the YAML file, you can create file with the required update and save as .YAML as shown in below and execute the file using kubectl.

Method 2: Patch using YAML file

“This patch file only contains the section you want to update, not the full deployment manifest.

#Save the file using below manifest (patch.yaml)
metadata:
  labels:
    environment: prod
#execute the command to apply the new changes in the existing pod
kubectl patch deployment nginx-deployment --patch-file ./thi/patch.yaml


You can run the following to check the YAML for the new updates:

#View the YAML in the notpad
kubectl edit deployment nginx-deployment
#View the YAML in the console itself
kubectl get deployment nginx-deployment -o yaml

In return, we get the following YAML file:

Example 2: Patch the label to the Pod level

In this same scenario, if we wanted to update the labels within the Pod template, you would have to drill into the spec field instead of the metadata.

Usually, you would drill into the metadata and spec fields for kubectl patch, but this would also work with other YAML fields, such as status or even a new custom field you created through a CRD (custom resource definition).

In the following example, we are attempting to add a new label environment: prod to the existing labels within the pod template, as the following:

#replace : Modifies the value of an existing field.
#add: Adds/replace a new field or value to an array.
#remove: Removes a field or an element from an array.
#copy: Copies the value of one field to another
#test: Verifies that a specific field has a certain value. The patch operation will fail if the condition is not met
#move: Moves a value from one location to another within the object
kubectl patch deployment nginx-deployment --type='json' --patch='[{"op": "add", "path": "/spec/template/metadata/labels/environment", "value":"prod"}]

The above cmd will be used for both adding new or updating the existing fields. To check if the deployment got the new labels, you can run the following:

kubectl get deployment nginx-deployment --show-labels

Example 3: Update Pod label and container image

We will attempt to update the image of the ingress from older version to new version and update the label value together . This will require us to drill further into the list (the – is a list and will use [ ] to tap into it from the kubectl patch command) instead of a map (uses { }):

kubectl patch deployment nginx-deployment --patch '{\"spec\": {\"template\": {\"metadata\": {\"labels\": {\"environment\": \"production\"}}, \"spec\": {\"containers\": [{\"name\": \"nginx\", \"image\": \"nginx:1.14.2\"}]}}}}'

Conclusion

The kubectl patch command is a versatile tool for managing Kubernetes resources, particularly in dynamic environments like Azure Kubernetes Service. It allows for targeted updates with minimal effort, making it ideal for quick fixes and operational adjustments. By mastering the kubectl patch command, AKS administrators can maintain agility and efficiency in managing their clusters.

Whether you are adding labels, scaling deployments, or updating container images, kubectl patch ensures you can implement changes quickly and confidently. Embrace this command to streamline your Kubernetes workflows and keep your AKS environment optimized.

“Next time you’re troubleshooting or making small updates in AKS, try kubectl patch instead of redeploying. What’s your favorite kubectl command? Drop it in the comments 👇”

Frequently Asked Questions (FAQ)

1. When should I use kubectl patch instead of kubectl apply?

Use kubectl patch when you want to make quick, targeted changes to a Kubernetes resource without redeploying the entire manifest. For example, updating a label, changing an image tag, or adding an environment variable can be done faster with kubectl patch. If you need to manage large or version-controlled manifests, kubectl apply is still the better choice.

2. Can I rollback a kubectl patch?

No, kubectl patch itself does not provide a rollback mechanism. Once applied, the changes are immediately reflected in the resource. To revert, you must either:

  • Manually patch again with the previous values, or

  • Redeploy the original manifest using kubectl apply -f <file.yaml>.
    Using GitOps or storing manifests in source control is recommended to track and revert changes easily.

3. What are common errors with kubectl patch?

Some common errors include:

  • Incorrect JSON/YAML syntax – forgetting quotes, brackets, or commas.

  • Missing path values – targeting the wrong field (e.g., metadata vs spec.template.metadata).

  • Unsupported patch type – not specifying --type=json when using JSON Patch operations.

  • Read-only fields – trying to patch fields like status or metadata.uid, which cannot be modified.

4. Does kubectl patch work for all Kubernetes resources?

Yes, kubectl patch works for most standard Kubernetes resources like Deployments, Pods, Services, ConfigMaps, and Secrets. However, some Custom Resource Definitions (CRDs) may not fully support all patch types depending on their schema.

5. Is kubectl patch safe to use in production?

Yes, but with caution. Since it makes live changes to resources, there is no automatic rollback. It is best used for small, urgent fixes in production. For long-term changes, update your manifests and use kubectl apply to keep your deployments consistent.

 

 

Update AKS Node Pools with Labels: A Comprehensive Guide Using Azure CLI

In today’s dynamic cloud environments, effectively managing your Azure Kubernetes Service (AKS) clusters is paramount. Labels offer a robust mechanism for organizing and optimizing your AKS resources, enabling efficient workload management and cost control. This comprehensive guide will delve into the az aks nodepool update command (azure aks nodepool update), demonstrating how to apply labels to your AKS node pools using the Azure CLI. We’ll explore practical use cases, essential prerequisites, and provide a step-by-step implementation guide.

What is the az aks nodepool update Command?

The az aks nodepool update command is an integral part of the Azure CLI toolkit. In essence, it empowers administrators to update specific properties of an existing AKS node pool. Moreover, utilizing labels with this command enables better management and resource allocation by categorizing node pools for specific workloads.

When to Use ?

This command proves particularly useful in the following scenarios:

  • Workload Segmentation: Assign specific workloads, such as .NET applications, to designated node pools. For example, you can label a node pool as “dotnet” to easily identify nodes suitable for .NET applications.
  • Cost Management: Apply labels to categorize node pools by environments (e.g., production, staging) to track costs more effectively. Consequently, this facilitates accurate cost allocation and budgeting.
  • Efficient Scheduling: Utilize Kubernetes label selectors in deployment manifests to target workloads to specific node pools. As a result, you can optimize resource utilization and improve application performance
  • Cluster Management: Enhance visibility and filtering when managing multiple node pools. In addition, labels simplify cluster management by providing a clear and organized structure.

Prerequisites

Before executing the az aks nodepool update command, ensure the following prerequisites are met:

       1. Azure CLI Installed:

Ensure the Azure CLI is installed and updated to the latest version. You can install it from the Azure CLI Documentation. Verify the installation using: az --version

Verify installation using:  az  –version

       2. Access Permissions:

You must possess the appropriate permissions to manage AKS resources. Typically, you’ll require the Azure Kubernetes Service Contributor or Owner role.

       3. Existing AKS Cluster and Node Pool:

An AKS cluster and the node pool you intend to label must already exist

      4. Resource Details:

Identify the resource group, cluster name, and node pool name.

How to Use the Command

To update labels on an AKS node pool using the Azure CLI, employ the following command:

az aks nodepool update \
  --resource-group <resource-group> \
  --cluster-name <aks-cluster-name> \
  --name <node-pool-name> \
  --labels <key=value>

For instance, to add a label nodepooltype=dotnet to the node pool prdnxpool01 in a production AKS cluster:

az aks nodepool update \
--resource-group rg-apps-prd-01 \
--cluster-name aks-dgtl-app-prd-we-01 \
--name prdnxpool01 \
--labels nodepooltype=dotnet

Command Breakdown

–resource-group: Specifies the resource group of the AKS cluster.
–cluster-name: The name of the AKS cluster.
–name: The name of the node pool to be updated.
–labels: Key-value pairs for the labels to apply to the node pool.

Validating the Update

Once the command executes successfully, you can verify the labels using the following method:

az aks nodepool show \
--resource-group rg-apps-prd-01 \
--cluster-name aks-dgtl-app-prd-we-01 \
--name prdnxpool01

OUTPUT

Conclusion:

In conclusion, effectively labeling AKS node pools is a critical practice for optimizing your Kubernetes workloads, improving resource utilization, and streamlining cluster management. The az aks nodepool update command within the Azure CLI provides a user-friendly and efficient method for applying and managing labels. By implementing the strategies outlined in this guide, you can enhance your AKS cluster’s performance, reduce operational overhead, and gain greater control over your Kubernetes deployments.

For more insights on Kubernetes and Azure, stay tuned to our blog!
Got questions or additional tips? Share them in the comments below!

 

Mastering Kubernetes HPA: How to Filter Horizontal Pod Autoscalers on Linux and Windows

Introduction to Horizontal Pod Autoscalers (HPAs)

In Kubernetes, a Horizontal Pod Autoscaler (HPA) is a critical resource that automatically scales the number of pods in a deployment, replica set, or stateful set based on observed CPU utilization, memory usage, or custom metrics. HPAs ensure that your applications can handle varying workloads efficiently by scaling out (adding more pods) during high demand and scaling in (removing pods) during low demand and another activity to monitor hpa by kubernetes hpa filtering.

When managing Kubernetes clusters, you often need to monitor and filter HPAs across multiple namespaces. For example, you might want to list all HPAs in specific namespaces or filter them based on certain criteria. On Linux, the grep command is commonly used for filtering text output. However, Windows does not natively support grep, so alternative methods are required.

In this article, we’ll explore how to filter kubectl get hpa output on both Linux and Windows systems (kubernetes hpa filtering) , using native tools and third-party utilities.

kubernetes hpa filtering

Filtering kubectl get hpa Output on Linux

Linux systems natively support the grep command, which is a powerful tool for filtering text. Here’s how you can use grep to filter kubectl get hpa output.

Example: Filter HPAs in Specific Namespaces

Suppose you want to list all HPAs in the namespace1 and namespace2 namespaces. You can use the following command:

kubectl get hpa -A -o wide | grep -E 'namespace1|namespace2'

kubectl get hpa -A -o wide | grep -E 'customer|identity'

Explanation:

  • kubectl get hpa -A -o wide: Fetches all HPAs across all namespaces (-A) and displays them in a wide format (-o wide).
  • grep -E ‘namespace1|namespace2’: Filters the output to show only lines containing namespace1 or namespace2.

Filtering kubectl get hpa Output on Windows

Windows does not natively support grep, but you can achieve similar functionality using PowerShell or by installing Unix-like tools.

Option 1: Use PowerShell’s Select-String

PowerShell has a built-in command called Select-String that works similarly to grep.

Example: Filter HPAs for all Namespaces

Fetches all HPAs across all namespaces.

kubectl get hpa -A
kubectl get hpa -A -o wide

Example: Filter HPAs in Specific Namespaces

kubectl get hpa -A -o wide | Select-String -Pattern 'namespace1|namespace2'

kubectl get hpa -A -o wide | Select-String -Pattern 'customer|identity'

Select-String -Pattern ‘namespace1|namespace2’: Filters the output to show only lines containing namespace1 or namespace2.

Option 2: Use findstr & Where-object (Native Windows Command)

Windows has a built-in command called findstr that can be used for basic text filtering.

Example: Filter HPAs in Specific Namespaces

kubectl get hpa -A -o wide | findstr "namespace1 namespace2"

kubectl get hpa -A -o wide | Where-Object { $_ -match 'customer|identity' }

findstr “namespace1 namespace2”: Filters the output to show only lines containing namespace1 or namespace2.

Using grep in Window’s Machine

Windows does not natively support grep, but you can achieve similar functionality using PowerShell or by installing Unix-like tools as shown in below.

choco install grep

Post installation, you can use the grep in you window machine. Ensure you are installing grep by opening the PowerShell console in the Admin mode to have successful installation.

Conclusion

For US-based teams, mastering kubectl HPA filtering and monitoring is essential for cost-efficient, high-performance Kubernetes clusters. By combining Linux/Windows command-line tools with enterprise-grade observability platforms, organizations can achieve seamless autoscaling aligned with industry best practices

 

Step-by-Step Guide: How to Create & Manage Custom Kubernetes Namespaces using Kubectl

Namespace are a foundational concept in Kubernetes that enable logical isolation of resources within a cluster. They allow teams, projects, or environments (e.g., dev, staging, prod) to share the same cluster without interfering with each other. By default, Kubernetes includes system namespaces like default, kube-system, and kube-public, but creating custom namespaces is essential for organizing workloads securely and efficiently. This article explains how to create, manage, and use custom namespaces using kubectl, with detailed examples and best practices.

What Is Kubernetes Namespace?

By using Namespaces, you can separate your cluster into different groups that are isolated from one another. For instance, you can create two separate Namespaces for an application — one for development and one for production. The development Namespace can be used for testing, debugging, and experimentation purposes, while the production Namespace can be used for hosting the stable and publicly accessible version of the application.

When you create a Namespace, any Kubernetes objects such as Pods, Deployments, and DaemonSets that you launch in it will exist exclusively within that Namespace. More importantly, all operations you perform, such as scaling and deleting resources, will only affect the objects in that specific Namespace.

Why Use Kubernetes Namespace?

Imagine a cluster hosting hundreds of applications, each with its own Deployments, ConfigMaps, and Secrets. Without Namespaces, managing these resources becomes chaotic:

Risk of Accidental Changes: Modifying or deleting the wrong resource is easy.

Lack of Visibility: Resources from different teams or projects clutter the same space.

Shared Resource Limits: A single team could monopolize cluster resources.

Namespaces solve these issues by:

  • Grouping Resources: Organize resources by team (e.g., frontend, backend), environment (dev, prod), or function (monitoring, logging).
  • Enforcing Policies: Apply Role-Based Access Control (RBAC) and resource quotas per Namespace.
  • Simplifying Management: Isolate troubleshooting and operations to specific contexts.

Prerequisites

Before creating a Namespace, ensure you have:

  1. A Running Kubernetes Cluster or mini kube for local setups.
  2. kubectl Installed: Configured to communicate with your cluster.

All commands in this guide are tested on Azure Kubernetes cluster

How to Create a Custom Kubernetes Namespace?

With the prerequisites taken care of, creating a custom Namespace in Kubernetes is a simple process. Here’s how you can do it:

Step 1: Check available Namespaces

Open a terminal and run the following command to list all the Namespaces in your cluster:

kubectl get namespaces

This will list all the Namespaces in your cluster, along with their status and age:

You will see a list of Namespaces shown in the console. Note that the Namespaces you’ll see besides the “default” Namespace will vary depending on your cluster configuration. For example, if you run the “kubectl get namespaces” command on a Kubernetes cluster, you’ll get the following output:

You may notice that in addition to the “default” Namespace, some Namespaces appear in both outputs while others are unique to each one. These additional Namespaces are not relevant to our discussion, so you can ignore them. However, understanding the “default” Namespace is important.

By default, all Kubernetes resources are created in the “default” Namespace if no Namespace is specified. The “default” Namespace is created automatically when Kubernetes is installed.

Step 2: Create a Custom Namespace

Run the following command to create a new Kubernetes Namespace called “production”. You can name your Namespace anything you like.

The output shows that the “staging” Namespace has been created successfully. We can verify this by executing the “kubectl get namespaces” command. As you can see, the new Namespace named “staging” is now listed along with the other Namespaces in the cluster. We can now use this Namespace to deploy applications related to lower environment and manage resources.

How to Create a Deployment in a Custom Namespace?

In the previous section, we created a custom Namespace named “staging”.

Now, let we create a Deployment that runs an “nginx” web server inside this Namespace. We can use the “kubectl create deployment” command for creating deployment. However, we need to specify the Namespace using the “-n” or “–namespace” flag, as shown below. Else it will create the deployment in the default namespace.

In this command, we have specified the “nginx” image and the “staging” Namespace using the “-n” flag. We have also given the deployment the name “mynginx”.

kubectl create deployment mynginx --image=nginx -n=production

The output shows that the deployment has been created successfully and you can check the status of the deployment using kubectl get cmdlet with the “-n” flag to list the Deployments in the “production” Namespace.

kubectl get deployment -n staging

As you can see, the “mynginx” Deployment is now running inside the “production” Namespace.

How to Delete a Custom Kubernetes Namespace?

In above steps, we have created a custom Namespace called “staging”, let’s see how we can delete it.

Deleting a Namespace is a simple operation in Kubernetes but we need to more careful before doing this action as it will delete all the resources like deployment/pods will get deleted. We can use the “kubectl delete namespace” command followed by the name of the Namespace we want to delete. Run the following command to delete the “staging” Namespace:

[su_highlight background=”#ffffff” color=”#f91355″]Deleting a namespace removes all resources within it, including Pods, Deployments, ConfigMaps, and Services. Use this command with caution.[/su_highlight]

kubectl delete namespace staging

Here is the output we get after executing the command:

To verify that the “staging” Namespace has been successfully deleted, we can list the available Namespaces in our cluster using the kubectl get namespace command as shown in above step (Step 1: Check available Namespaces):

What Happens When You Delete the Namespace in Kubernetes?

Remember that deleting a Namespace also deletes all the resources created inside it. In our case, we had created a Deployment called “mynginx” inside the “staging” Namespace. Now that we have deleted this Namespace, we have also deleted this “mynginx” Deployment.

Remember to be careful when deleting Namespaces, as it can result in the loss of important resources. Always double-check before performing such operations.

  1. Cascade Deletion: Kubernetes terminates all resources inside the namespace.
    • Pods are gracefully shut down.
    • PersistentVolumes (if not retained) are deleted.
    • Services, Deployments, and Secrets are removed.
  2. Irreversible Action: Once deleted, resources cannot be recovered unless backed up externally.
  3. Finalizers: Some resources may delay deletion if they have finalizers (e.g., waiting for storage cleanup).

Summary

Deleting a namespace is a powerful but irreversible operation. Always verify resources inside the namespace, use dry-run simulations, and ensure backups exist. If a namespace gets stuck, manually removing finalizers can resolve the issue. By following these practices, you minimize the risk of accidental data loss in your Kubernetes cluster.

To limit CPU, memory, or Pod counts per namespace in Kubernetes, you can use Resource Quotas and Limit Ranges. Resource Quotas define hard limits for resource consumption within a namespace, while Limit Ranges enforce minimum and maximum resource constraints on individual Pods or containers. We will discuss more about this deep drive in upcoming article.

Linux Sed Command: The Fastest Way to Find & Replace Text (Real-World DevOps Use Case)

Introduction:

The sed command, a powerful stream editor in Linux/Unix, is a cornerstone for text manipulation. This guide will delve into the intricacies of using sed to search and replace strings within files. We’ll explore various scenarios, from replacing single occurrences to global substitutions, and even handling case-insensitive replacements. Whether you’re a seasoned system administrator or a budding developer, this comprehensive tutorial will equip you with the knowledge to effectively wield the sed command for your text processing needs. We will discuss more about how to Search and Replace String Using the sed.

My Requirement & solution:

We are maintaining the application in Linux machine (in AKS pods) and as a Devops team, we Got a requirement to replace some config values based on the environment (value need to be maintain in the AKS environment variable). To manage this, we thought to create one startup script in the docker image which will execute during the new image deployment ,where we used the sed command to achieve the find & replace of config value based on environments. Based on my experience i though to write this article (Search and Replace String Using the sed Command in Linux/Unix) immediately which will be helpful like me who are new to the Linux Operating system/Bash commands. 

What Is the Sed Command in Linux?

The SED command in Linux stands for Stream Editor and it helps in operations like selecting the text, substituting text, modifying an original file, adding lines to text, or deleting lines from the text. Though most common use of SED command in UNIX is for substitution or for find and replace.

By using SED you can edit files even without opening them, which is much quicker way to find and replace something in file, than first opening that file in VI Editor and then changing it.

[su_highlight color=”#2F1C6A”]Syntax: sed OPTIONS… [SCRIPT] [INPUTFILE…][/su_highlight]

  • Options control the output of the Linux command.
  • Script contains a list of Linux commands to run.
  • File name (with extension) represents the file on which you’re using the sed command.

[su_quote]Note: We can run a sed command without any option. We can also run it without a filename, in which case, the script works on the std input data.[/su_quote]

Key Advantages of Using sed

  • Efficiency: sed allows for in-place editing, eliminating the need to manually open and modify files in a text editor.
  • Flexibility: It supports a wide array of editing commands, enabling complex text manipulations.
  • Automation: sed can be easily integrated into scripts for automated text processing tasks.

Search and Replace String Using the sed

Replace First Matched String

The below example, the script will replace the first found instance of the word test1 with test2 in every line of a file

    sed -i 's/test1/test2/' opt/example.txt

The command replaces the first instance of test1 with test2 in every line, including substrings. The match is exact, ignoring capitalization variations. -i tells the sed command to write the results to a file instead of standard output.

Search & Global Replacement (all the matches)

To replace every string match in a file, add the g flag to the script (To replace all occurrences of a pattern within each line). For example

    sed -i 's/test1/test2/g' opt/example.txt

The command globally replaces every instance of test1 with test2 in the /example.txt.

The command consists of the following:

  • -i tells the sed command to write the results to a file instead of standard output.
  • s indicates the substitute command.
  • / is the most common delimiter character. The command also accepts other characters as delimiters, which is useful when the string contains forward slashes.
  • g is the global replacement flag, which replaces all occurrences of a string instead of just the first.
    “input file” is the file where the search and replace happens. The single quotes help avoid meta-character expansion in the shell.

Search and Replace All Cases

To find and replace all instances of a word and ignore capitalization, use the I parameter:

#I: The case-insensitive flag.    
sed -i 's/test1/tes2/gI' opt/example.txt

The command replaces all instances of the word test1 with test2, ignoring capitalization.

Conclusion 

The sed command is an invaluable tool for text manipulation in Linux/Unix environments. By mastering its basic usage and exploring its advanced features, you can streamline your text processing tasks and significantly improve your system administration and development workflows. This tutorial has provided a foundational understanding of sed’s search and replace capabilities. For further exploration, consider delving into more advanced sed scripting techniques and exploring its other powerful features.

I hope you found this tutorial helpful. What’s your favorite thing you learned from this tutorial? Let me know on comments!

Linux Secrets: How to List Environment Variables (Beginners to Pros)

An environment variable is a dynamic object that defines a location to store some value. We can change the behavior of the system and software using an environment variable. Environment variables are very important in computer programming. They help developers to write flexible programs.

There are Different ways to List Environment Variables in Linux. We can use the env, printenv, declare, or set command to list all variables in the system. In this Post , we’ll explain how to use Different ways to List Environment Variables in Linux.

You can also learn how to A Step-by-Step Guide to Set Environment Variables in Linux

Using printenv Command

The printenv command displays all or specified environment variables. To list all environment variables, simply type:

printenv

We can specify one or more variable names on the command line to print only those specific variables. Or, if we run the command without arguments, it will display all environment variables of the current shell.

For example, we can use the printenv command followed by HOME to display the value of the HOME environment variable:

printenv HOME
/root

In addition, we can specify multiple environment variables with the printenv command to display the values of all the specified environment variables:

Let’s display the values of the HOME and SHELL environment variables:

printenv HOME SHELL
/root
/bin/bash

Using env Command

The env command is similar to printenv but is primarily used to run a command in a modified environment. env is another shell command we can use to print a list of environment variables and their values. Similarly, we can use the env command to launch the correct interpreter in shell scripts.

We can run the env command without any arguments to display a list of all environment variables:

env

Using set Command

The set command lists all shell variables, including environment variables and shell functions. It displays more than just environment variables, so the output will be more comprehensive:

set is yet another command-line utility for listing the names and values of each shell variable. Although the set command has other uses, we can display the names and values of all shell variables in the current shell simply by running it without any options or arguments:

set

Using export -p Command

The export -p command shows all environment variables that are exported to the current shell session:

export -p

Using the declare Command

declare is another built-in command used to declare a shell variable and display its values. For example, let’s run the declare command without any option to print a list of all shell variables in the system: The declare -x command lists environment variables along with some additional information, similar to export -p:

declare -x

Using the echo Command

echo is also used to display values of the shell variable in Linux. For example, let’s run the echo command to display the value of the $HOSTNAME variable:

echo $HOSTNAME

Conclusion

There are multiple ways to list and manage environment variables in Linux, ranging from command-line utilities to graphical tools. Each method provides a different level of detail and flexibility, allowing users to choose the one that best fits their needs.

Incorporating these methods into your blog post will provide a comprehensive guide for readers looking to understand and manage environment variables in Linux.

 

Dockerfile Mastery: Step-by-Step Guide to Building & Deploying Node.js Containers

Introduction

Docker has revolutionized how developers build, ship, and run applications by simplifying dependency management and environment consistency. At the core of Docker’s workflow is the Dockerfile, a script that defines how to assemble a container image. This article walks you through creating a custom Docker image from a local Dockerfile, deploying it as a container, and understanding real-world use cases. Whether you’re new to Docker or refining your skills, this guide offers practical steps to streamline your workflow.

Why Use a Dockerfile?

A Dockerfile automates the creation of Docker images, ensuring repeatability across environments. Instead of manually configuring containers, you define instructions (e.g., installing dependencies, copying files) in the Dockerfile. This approach eliminates “it works on my machine” issues and speeds up deployment.

Create a Docker Image for simple Node.js App

Step 1: Create a Dockerfile

Let’s build a Docker image for a simple Node.js server.

1. Project Setup

Create a directory for your project:

mkdir node-docker-app && cd node-docker-app

2. Add two files:

server.js (a basic Express server): This is the main application file where the Express server is set up. It defines the routes and how the server should respond to requests (e.g., GET / sends “Hello from Docker example from dotnet-helpers !”). It is essential for the application’s functionality.

const express = require('express');  
const app = express();  
app.get('/', (req, res) => res.send('Hello from Docker example from dotnet-helpers !'));  
app.listen(3000, () => console.log('Server running on port 3000'));

package.json (dependencies file): This file is needed to manage the application’s dependencies (in this case, express). It ensures that Docker can install the correct version of the dependencies when the application is built, ensuring the server runs without issues.

{  
  "name": "node-docker-app",  
  "dependencies": {  
    "express": "^4.18.2"  
  }  
}

3. Write the Dockerfile

Create a file named Dockerfile (no extension) with these instructions:

# Use the official Node.js 18 image as a base  
FROM node:18-alpine  
# Set the working directory in the container  
WORKDIR /app  
# Copy package.json and install dependencies  
COPY package.json .  
RUN npm install  
# Copy the rest of the application code  
COPY . .  
# Expose port 3000 for the app  
EXPOSE 3000  
# Command to start the server  
CMD ["node", "server.js"]
  • FROM specifies the base image.
  • WORKDIR sets the container’s working directory.
  • COPY transfers local files to the container.
  • RUN executes commands during image build.
  • EXPOSE documents which port the app uses.
  • CMD defines the command to run the app.

 

Step 2: Build the Docker Image

Run this command in your project directory:

docker build -t node-app:latest .
  • -t tags the image (name:tag format).
  • The . at the end tells Docker to use the current directory as the build context.

Docker executes each instruction sequentially as shown below and caching layers for faster rebuilds (for next build).

Step 3: Attach Image & Run the Container

The docker run command is used to create and start a new container from a specified Docker image. It is one of the most commonly used Docker commands to launch applications in an isolated environment. It’s one of the most fundamental Docker commands — essentially bringing a container to life!

Start a container from your image:

#syntax
docker run -d -p 3000:3000 --name <container-name> <image-name>
docker run -d -p 3000:3000 --name my-node-app node-app:latest
  • -d runs the container in detached mode.
  • -p 3000:3000 maps the host’s port 3000 to the container’s port 3000.
  • --name assigns a name to the container.

Verify it’s working by using CURL or in browser as shown below.

curl http://localhost:3000
# Output: Hello from Docker!

Output : Run in the console using curl

Run in the Browser

Step 4: Manage the Container

Stop the container: Gracefully stops the running container named my-node-app. If you want to shut down a running container without deleting it — useful for pausing an app or troubleshooting.

docker stop my-node-app

Remove the container: Deletes the container (but not the image). After stopping the container, if you don’t need it anymore — like cleaning up old containers.

docker rm my-node-app

Delete the image: Deletes the Docker image named node-app with the latest tag. If you want to clear up disk space or remove outdated images. Note, You cannot remove an image if there are running or stopped containers using it. Stop and remove the containers first:

docker rmi node-app:latest

If you build a new Docker image and want to update a running container to use this new image, Docker doesn’t allow you to “swap” the image directly — instead, you have to stop the running container and create a new one. Let’s go through the step-by-step process!

Optimization Tips

  1. Use .dockerignore
    Prevent unnecessary files (e.g., node_modules, local logs) from being copied into the image.
  2. Leverage Multi-Stage Builds
    Reduce image size by discarding build dependencies in the final image.
  3. Choose Smaller Base Images
    Use -alpine or -slim   variants to minimize bloat.

Conclusion

Creating Docker images from a Docker file standardizes development and deployment workflows, ensuring consistency across teams and environments. By following the steps above, you’ve packaged a Node.js app into a portable image and ran it as a container. This method applies to any language or framework—Python, Java, or even legacy apps.

Docker’s power lies in its simplicity. Once you master Docker files, explore advanced features like Docker Compose for multi-container apps or Kubernetes for orchestration. Start small, automate the basics, and scale confidently.

Exception Handling 101: Stop Script Failures in Their Tracks with Custom Try‑Catch Tricks

An error in a PowerShell script will prevent it from completing script execution successfully. Using error handling with try-catch blocks allows you to manage and respond to these terminating errors. In this post, we will discuss the basics of try/catch blocks and how to find or handle Custom Error Message in PowerShell.

Handling errors effectively in scripts can save a lot of troubleshooting time and provide better user experiences. In PowerShell, we have robust options to handle exceptions using try, catch, and finally blocks. Let’s dive into how you can use try-catch to gracefully handle errors and add custom error messages for better feedback.

Why Use Exception Handling in PowerShell?

Scripts can fail for many reasons: missing files, invalid input, or network issues, to name a few. With exception handling, you can capture these issues, inform users in a friendly way, and potentially recover from errors without crashing your script. Using try-catch, you can:

  • Catch specific errors.
  • Display user-friendly messages.
  • Log errors for debugging.

Syntax overview of Try/Catch

Like similar in other programming languages, the try-catch block syntax is very simple and syntax will be the same. It is framed with two sections enclosed in curly brackets (the first block is a try and the second is the catch block).

try {
# Functionality within try block
}
catch {
# Action to do with errors
}

The main purpose of using the try-catch block, we can start to manipulate the error output and make it more friendly for the user.

Example 1:

After executing the below script, the below error will be shown on the screen as output and it would occupy some space and the problem may not be immediately visible to the User. So you can use a try-catch block to manipulate the error output and make it more friendly.

without Try-Catch block

Get-content -Path “C:\dotnet-helpers\BLOG\TestFiled.txt” 

with Try Catch block

In the below script, we added the ErrorAction parameter with a value of Stop to the command. Not all errors are considered “terminating”, so sometimes we need to add this bit of code in order to properly terminate into the catch block.

try {
Get-content -Path “C:\dotnet-helpers\BLOG\TestFile.txt” -ErrorAction Stop
}
catch {
Write-Warning -Message “Can’t read the file, seem there is an issue”

}

Example 2:

Using the $Error Variable

In Example 1, we have displayed our own custom message instead of this you can display the specific error message that occurred instead of the entire red text exception block. When an error occurs in the try block, it is saved to the Automatic variable named $Error. The $Error variable contains an array of recent errors, and you can reference the most recent error in the array at index 0.

try{
Get-content -Path “C:\dotnet-helpers\BLOG\TestFiled.txt” -ErrorAction Stop
}
Catch{

Write-Warning -Message “Cant’t read the file, seem there is an issue”
Write-Warning $Error[0]

}

Example 3:

Using Exception Messages

You can also use multiple catch blocks in case if you want to handle different types of errors. For this example, we going to handle two different types of errors and planned to display different custom messages. The first CATCH is to handle if the path does not exist and the next CATCH is to handle if any error related to the driver not found.

Using try/catch blocks gives additional power in handling errors in a script and we can have different actions based on the error type. The catch block focuses on not only displaying error messages but we can have logic that will resolve the error and continue executing the rest of the script.

In this example, the file mentioned driver (G:\dotnet-helpers\BLOG\TestFiled.txt) does not exist in the execution machine, so it was caught by [System.Management.Automation.DriveNotFoundException] and executed the same CATCH block.

try{
Get-content -Path "G:\dotnet-helpers\BLOG\TestFiled.txt" -ErrorAction Stop
}
# It will execute if a specific file is not found in a specific Directory
Catch [System.IO.DirectoryNotFoundException] {
Write-Warning -Message "Can't read the file, seems there is an issue"
Write-Warning $Error[0]
}
# It will execute if the specified driver is not found in the specified path
Catch [System.Management.Automation.DriveNotFoundException]{
Write-Warning -Message "Custom Message: Specific driver is not found"
Write-Warning $Error[0]
}
#Execute for Un-Handled exception - This catch block will run if the error does not match any other catch block exception.
Catch{
Write-Warning -Message "Oops, An un-expected Error Occurred"
#It will return the exception message for the last error that occurred.
Write-host $Error[0].Exception.GetType().FullName
}

OUTPUT

 

Step-by-Step Guide: Creating Simple Docker Image from a Dockerfile

Docker has revolutionized how developers build, ship, and run applications by simplifying dependency management and environment consistency. At the core of Docker’s workflow is the Dockerfile, a script that defines how to assemble a container image. This article walks you through Create Docker Image from a local Docker file, deploying it as a container, and understanding real-world use cases. Whether you’re new to Docker or refining your skills, this guide offers practical steps to streamline your workflow.

Why use a Dockerfile?

A Dockerfile is a simple text file containing a series of commands and instructions used to build a Docker image. It’s the blueprint for your image, automating the creation process so that your app’s environment can be replicated anywhere. A Dockerfile automates the creation of Docker images, ensuring repeatability across environments. Instead of manually configuring containers, you define instructions (e.g., installing dependencies, copying files) in the Dockerfile. This approach eliminates “it works on my machine” issues and speeds up deployment.

Dockerfile commands have a wide range of purposes. Use them to:

  • Install application dependencies.
  • Specify the container environment.
  • Set up application directories.
  • Define runtime configuration.
  • Provide image metadata.

Prerequisites

  1. Command-line access.
  2. Administrative privileges on the system.
  3. Docker installed.

Create Docker Image from Dockerfile

Follow the steps below to create a Dockerfile, build the image, and test it with Docker.

Step 1: Create Project Directory

Creating a Docker image with Dockerfile requires setting up a project directory. The directory contains the Dockerfile and stores all other files involved in building the image.

To make simple, you can create required docker file inside the  project directory as shown below.

Create a directory by opening the Terminal and using the mkdir command, for this example i used powershell 

mkdir dockerapp

Replace <directory> with the name of the project.

Step 2: Create Dockerfile

The contents of a Dockerfile depend on the image that it describes. The section below explains how to create a Dockerfile and provides a simple example to illustrate the procedure:

1. Navigate to the project directory:

cd <directory>

2. Create a Dockerfile using a text editor of your choice. Here i created using PowerShell cmdlet as shown below else you can create file manually inside your directory

New-Item -Path . -Name "Dockerfile" -ItemType "File"

3. Add the instructions for image building. For example, the code below creates a simple Docker image that uses Ubuntu as a base, runs the apt command to update the repositories, and executes an echo command that prints the words Hello World in the output: Please place this docker file command inside the file which we create in above step.

FROM ubuntu
MAINTAINER test-user
RUN apt update
CMD ["echo", "Hello World"]

Once you finish adding commands to the Dockerfile, save the file and exit.

Note: After running of the above image, you will have “Hello World” as output (refer the last image of this article).

SyntaxDescription
FROM <image>Specifies an existing image as a base.
MAINTAINER <name>Defines the image maintainer.
RUN <command>Executes commands at build time.
CMD <command> <argument>Sets the default executable.
ENTRYPOINT <command>Defines a mandatory command.
LABEL <key>=<value>Adds metadata to the image.
ENV <key>=<value>Sets environment variables.
ARG <key>[=<default-value>]Defines build-time variables.
COPY <source> <destination>Copies files into the image.

 

Step 3: Build Docker Image

Use the following procedure to create a Docker image using the Dockerfile created in the previous step.

1. Run the following command to build a docker image, replacing <image> with an image name and <path> with the path to Dockerfile:

docker build -t <image> <path>

The -t option allows the user to provide a name and (optionally) a tag for the new image. When executing the command from within the project directory, use (.) as the path:

docker build -t <image> .

Docker reads the Dockerfile’s contents and executes the commands in steps as shown in below snap shot.

2. Verify that the new image is in the list of local images by entering the following command or you can check inside the docker dashboard as shown below.

docker images

The output shows the list of locally available images.

Step 4: Test Docker Image

To test the new image, use docker run to launch a new Docker container based on it: Ensure the container need to attach to run the docker image.

docker run --name <container> <image>

The example below uses the myfirstapp image to create a new container named myfirstappcontainer:

docker run --name myfirstappcontainer myfirstapp

Docker creates a container and successfully executes the command listed in the image’s Dockerfile.

Conclusion:

Understanding Docker’s core commands, such as docker run --name, is essential for efficiently managing containers. The example provided (docker run --name myfirstappcontainer myfirstapp) illustrates how to launch a container directly tied to a specific image, ensuring the execution of predefined Dockerfile instructions.

This approach streamlines development and deployment by enforcing container-image linkage at runtime. The article reinforces the importance of Docker in modern DevOps practices, offering actionable insights for creating images, handling containers, and integrating these tools into broader development workflows. By mastering these concepts, developers can enhance reproducibility, scalability, and automation in their projects.