Mastering Kubernetes for CKA: Services, Namespaces, and Imperative vs Declarative Approaches Simplified

vikash kumarvikash kumar
8 min read

Kubernetes adventurers! πŸ‘‹ Welcome back to our weekly journey through the exciting world of Kubernetes as we prepare for the Certified Kubernetes Administrator (CKA) exam. This week, we’re diving into some essential Kubernetes concepts: Services, Namespaces, and the differences between Imperative and Declarative approaches. Let's break these down in the simplest way possible with real-world examples. we're diving into the topics that are as essential as your morning coffee: Kubernetes Services!

Understanding Kubernetes Services

Services in Kubernetes provide a stable endpoint (an IP address and port) to access a set of Pods. They enable communication between different parts of your application or with the outside world. Let’s explore the different types of Services:

ClusterIP

ClusterIP is the default type of Service. It exposes the Service on an internal IP address, making it accessible only within the cluster. This is useful for internal communication within the cluster.

Example: Internal Web Service

Imagine you have a web application that needs to communicate with an internal database. You don’t want the database accessible from outside the cluster.

Real-world analogy: It's like having a staff-only cafeteria in your office building.

Imperative:

kubectl expose pod my-database-pod --port=5432 --name=my-database-service

Declarative:

apiVersion: v1
kind: Service
metadata:
  name: my-database-service
spec:
  selector:
    app: my-database
  ports:
    - protocol: TCP
      port: 5432
      targetPort: 5432

When to Use ClusterIP:

  • Internal microservices communication.

  • Databases or services that should not be exposed outside the cluster.

NodePort

NodePort exposes the Service on each Node’s IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. This is useful for exposing the application externally while still keeping the cluster private.

Example: External Access to a Web Application

You have a web application that needs to be accessible from outside the cluster.

Real-world analogy: It's like a drive-through window at a fast-food restaurant.

When to Use NodePort:

  • For development and testing environments where you need quick access to your application.

  • When you don't have a cloud load balancer or external load balancing requirement, on-premises cluster.

Now let's see how to create NodePort typer of service by imperative and declarative ways.

imperative way-

kubectl expose pod my-web-pod --type=NodePort --port=80 --name=my-web-service

Declarative:

apiVersion: v1
kind: Service
metadata:
  name: my-web-service
spec:
  type: NodePort
  selector:
    app: my-web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30007

LoadBalancer

LoadBalancer exposes the Service externally using a cloud provider’s load balancer. This is ideal for services that need to be accessible from the internet.

Example: Internet-Facing Application

You have an application that needs to be accessed by users over the internet.

Real-world analogy: It's like having a team of hosts at a fancy restaurant, directing guests to available tables.

When to Use LoadBalancer:

  • For production environments where you need to expose your application to the internet.

  • When you are using a cloud provider that supports load balancers (e.g., AWS, GCP, Azure).

Imperative:

kubectl expose pod my-app-pod --type=LoadBalancer --port=80 --name=my-app-service

Declarative:

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

The Power of Namespaces

Namespaces in Kubernetes provide a way to divide cluster resources between multiple users or teams. They help organize and manage resources in a more efficient way.

Think of Namespaces as different dining areas in a large, multi-cuisine restaurant complex:

  • The main dining hall (default namespace)

  • The pizza parlor (a namespace for your frontend services)

  • The sushi bar (a namespace for your backend services)

  • The staff cafeteria (system namespaces like kube-system)

Each area has its own resources, staff, and rules, but they're all part of the same restaurant complex.

Example: Multi-Team Environment

Your organization has multiple teams working on different projects. Namespaces can help keep their resources separate.

When to Use Namespaces:

Organization: To organize resources by project or team which will keep your kubernetes resources neatly sorted.

  • Isolation: Prevent conflicts between teams or projects.

  • Resource Sharing: Set resource quotas for different environments

  • Access Control: To manage access control using Role-Based Access Control (RBAC).

    Creating and Using Namespaces

    Let's see how to create and use namespaces:

Imperative:

kubectl create namespace dev-team
kubectl create namespace qa-team

Declarative:

apiVersion: v1
kind: Namespace
metadata:
  name: sushi-bar

Create a service in this namespace:

apiVersion: v1
kind: Service
metadata:
  name: sushi-service
  namespace: sushi-bar
spec:
  selector:
    app: SushiApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

List resources in a specific namespace:

kubectl get services -n sushi-bar

Set your default namespace:

kubectl config set-context --current --namespace=sushi-bar

Namespace Best Practices

  1. Use meaningful names (e.g., development, production, team-frontend)

  2. Don't use namespaces for version control (that's what Git is for!)

  3. Be cautious with cluster-wide resources (they don't belong to any namespace)

  4. Use resource quotas to prevent one namespace from hogging all the resources

Namespaces and DNS

Here's a cool trick: Services in different namespaces can communicate using DNS!

It's like having an intercom system between different areas of your restaurant!

Imperative vs Declarative: Two Ways to Manage Your Kubernetes Restaurant πŸ‘¨β€πŸ³πŸ‘©β€πŸ³ Choosing the Right Approach

When managing Kubernetes resources, you can use either an imperative or declarative approach.

Imperative Approach: The Hands-On Chef πŸ—£οΈ

The imperative approach involves running commands to create or update resources. It's quick and straightforward for simple tasks but can become complex and hard to track for larger configurations.

Analogy: This is like a head chef actively calling out orders in the kitchen: "Chop the onions! Sear the steak! Plate the dish!"

Example: Creating a Deployment

Imperative:

Creating a Deployment

kubectl create deployment nginx --image=nginx

Creating a service:

kubectl create service clusterip my-svc --tcp=5678:8080

Updating a deployment or increase the replicas of pods:

kubectl scale deployment my-deployment --replicas=5

Deleting a pod:

kubectl delete pod unhealthy-pod

Here's a comprehensive cheat sheet that covers the key concepts we've discussed and includes essential commands for both the CKA exam and daily Kubernetes administration tasks:

Core Concepts Quick Reference

  1. Services:

    • ClusterIP: kubectl create service clusterip my-svc --tcp=80:8080

    • NodePort: kubectl create service nodeport my-svc --tcp=80:8080

    • LoadBalancer: kubectl create service loadbalancer my-svc --tcp=80:8080

  2. Namespaces:

    • Create: kubectl create namespace my-namespace

    • List: kubectl get namespaces

    • Set default: kubectl config set-context --current --namespace=my-namespace

  3. Imperative vs Declarative:

    • Imperative: Direct commands (e.g., kubectl create ...)

    • Declarative: YAML files with kubectl apply -f file.yaml

Essential kubectl Commands

  1. Viewing Resources:

     kubectl get pods/services/deployments/nodes/namespaces
     kubectl describe pod/service/deployment pod-name
     kubectl get pods -o wide  # More details
     kubectl get all -n namespace-name  # All resources in a namespace
    
  2. Creating and Updating Resources:

kubectl create deployment my-deploy --image=nginx
kubectl scale deployment my-deploy --replicas=3
kubectl set image deployment/my-deploy nginx=nginx:1.19
kubectl edit deployment my-deploy
kubectl rollout status deployment/my-deploy
kubectl rollout undo deployment/my-deploy
  1. Deleting Resources:
kubectl delete pod/service/deployment resource-name
kubectl delete -f file.yaml
kubectl delete pods --all  # Delete all pods in current namespace
  1. Troubleshooting:
kubectl logs pod-name
kubectl logs -f pod-name  # Follow logs
kubectl exec -it pod-name -- /bin/bash
kubectl port-forward pod-name 8080:80
kubectl get events --sort-by=.metadata.creationTimestamp
  1. Labeling and Annotations:
kubectl label pods my-pod env=prod
kubectl annotate pods my-pod description='My description'
  1. Config and Context:

     kubectl config view
     kubectl config current-context
     kubectl config use-context my-context
    
  2. Resource Management:

     kubectl top nodes
     kubectl top pods
     kubectl cordon node-name  # Mark node as unschedulable
     kubectl drain node-name  # Drain node in preparation for maintenance
    
  3. YAML Generation (for learning and quick starts):

     kubectl create deployment my-deploy --image=nginx --dry-run=client -o yaml
     kubectl create service clusterip my-svc --tcp=80:8080 --dry-run=client -o yaml
    

    Declarative Approach: The Recipe-Driven Kitchen πŸ“

    The declarative approach involves writing configuration files that describe the desired state of your resources. Kubernetes ensures that the actual state matches the desired state, making it easier to manage complex environments.

Analogy: This is like having detailed recipes for each dish. The kitchen staff knows the end goal and works together to achieve it, regardless of the current state.

Examples:

  1. Creating or updating resources using a YAML file:

     kubectl apply -f my-resources.yaml
    

    Content of my-resources.yaml:

     apiVersion: v1
     kind: Service
     metadata:
       name: my-service
     spec:
       selector:
         app: MyApp
       ports:
         - protocol: TCP
           port: 80
           targetPort: 9376
     ---
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: my-deployment
     spec:
       replicas: 3
       selector:
         matchLabels:
           app: MyApp
       template:
         metadata:
           labels:
             app: MyApp
         spec:
           containers:
           - name: my-container
             image: my-image:latest
    

    Pros:

    • Easy to version control

    • Reproducible across environments

    • Self-documenting

    • Handles complex scenarios well

Cons:

  • Steeper learning curve

  • Can be overkill for very simple tasks

When to Use Each Approach

  • Imperative:

    • Learning and exploring Kubernetes

    • Quick fixes in development environments

    • Troubleshooting and debugging

  • Declarative:

    • Production environments

    • Continuous Integration/Continuous Deployment (CI/CD) pipelines

    • Managing complex applications

    • Ensuring consistency across multiple clusters

Remember, in the CKA exam, you'll need to be comfortable with both approaches. In real-world scenarios, a mix of both is often used, with a preference for declarative in production environments.

Bringing It All Together: Services, Namespaces, and Management Approaches

Now that we understand Services, Namespaces, and the two management approaches, let's see how they all work together:

  1. Use Services to expose your applications within and across Namespaces.

  2. Organize your Services and other resources into Namespaces for better management.

  3. Use the Imperative approach for quick tasks and learning.

  4. Use the Declarative approach for maintaining and scaling your production environment.

Wrapping Up

Kubernetes is a powerful platform that requires a solid understanding of its core concepts. This week, we explored Services, Namespaces, and the imperative vs. declarative approaches. Each concept plays a critical role in how you manage and scale your applications in a Kubernetes environment.

Stay tuned for next week’s post, where we’ll continue our Kubernetes journey. Happy Kubernetesing, and good luck with your CKA exam prep! πŸš€πŸŽ‰

0
Subscribe to my newsletter

Read articles from vikash kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

vikash kumar
vikash kumar

Hey folks! πŸ‘‹ I'm Vikash Kumar, a seasoned DevOps Engineer navigating the thrilling landscapes of DevOps and Cloud ☁️. My passion? Simplifying and automating processes to enhance our tech experiences. By day, I'm a Terraform wizard; by night, a Kubernetes aficionado crafting ingenious solutions with the latest DevOps methodologies πŸš€. From troubleshooting deployment snags to orchestrating seamless CI/CD pipelines, I've got your back. Fluent in scripts and infrastructure as code. With AWS ☁️ expertise, I'm your go-to guide in the cloud. And when it comes to monitoring and observability πŸ“Š, Prometheus and Grafana are my trusty allies. In the realm of source code management, I'm at ease with GitLab, Bitbucket, and Git. Eager to stay ahead of the curve πŸ“š, I'm committed to exploring the ever-evolving domains of DevOps and Cloud. Let's connect and embark on this journey together! Drop me a line at thenameisvikash@gmail.com.