Working with Namespaces and Services in Kubernetes

Table of contents

What are Namespaces and Services in k8s:

Namespaces in Kubernetes

Namespaces in Kubernetes logically separate resources within a cluster. They help organize workloads, especially in large environments where multiple teams or projects share the same cluster.

Key Features of Namespaces:

  1. Logical Isolation: Separate resources for different teams, applications, or environments (e.g., dev, staging, prod).

  2. Resource Quotas: Define CPU, memory, and storage limits for different namespaces.

  3. Scoped Access Control: Apply Role-Based Access Control (RBAC) to limit access within specific namespaces.

  4. Unique Naming within a Namespace: Resources like pods, services, and deployments must have unique names only within their namespace, allowing duplication across different namespaces.

Common Namespace Commands:

  • List all namespaces

      kubectl get namespaces
    
  • Create a new namespace

      kubectl create namespace my-namespace
    
  • Delete a namespace

      kubectl delete namespace my-namespace
    
  • Run commands in a specific namespace

      kubectl get pods -n my-namespace
    

By default, Kubernetes includes namespaces like:

  • default: Where resources are created if no namespace is specified.

  • kube-system: Contains system-related components (e.g., CoreDNS, API server).

  • kube-public: Readable by everyone, typically used for public information.

  • kube-node-lease: Stores heartbeat information for node monitoring.


Services in Kubernetes

A Service in Kubernetes is an abstraction that enables stable networking for a set of Pods. Since Pods are ephemeral, their IP addresses change when they restart, and services provide a consistent way to access them.

Types of Services:

  1. ClusterIP (Default)

    • Exposes the service internally within the cluster.

    • Not accessible from outside.

    • Example:

        apiVersion: v1
        kind: Service
        metadata:
          name: my-service
        spec:
          selector:
            app: my-app
          ports:
            - protocol: TCP
              port: 80
              targetPort: 8080
      
  2. NodePort

    • Exposes the service on each node’s IP at a static port.

    • Accessible externally using NodeIP:NodePort.

    • Example:

        apiVersion: v1
        kind: Service
        metadata:
          name: my-service
        spec:
          type: NodePort
          selector:
            app: my-app
          ports:
            - port: 80
              targetPort: 8080
              nodePort: 30000
      
  3. LoadBalancer

    • Integrates with cloud providers to expose the service via an external load balancer.

    • Used in cloud-based Kubernetes deployments.

    • Example:

        apiVersion: v1
        kind: Service
        metadata:
          name: my-service
        spec:
          type: LoadBalancer
          selector:
            app: my-app
          ports:
            - port: 80
              targetPort: 8080
      
  4. ExternalName

    • Maps a service to an external DNS name instead of routing traffic to a set of pods.

    • Example:

        apiVersion: v1
        kind: Service
        metadata:
          name: my-external-service
        spec:
          type: ExternalName
          externalName: example.com
      

Common Service Commands:

  • List all services

      kubectl get services
    
  • Describe a service

      kubectl describe service my-service
    
  • Expose a deployment as a service

      kubectl expose deployment my-deployment --type=ClusterIP --port=80 --target-port=8080
    

Service Discovery:

  • Services can be discovered within the cluster via DNS resolution (if CoreDNS is enabled).

  • Applications running inside the cluster can reach a service using its name (e.g., my-service.default.svc.cluster.local).

Task 1:

  • Create a Namespace for your Deployment

  • Use the command kubectl create namespace <namespace-name> to create a Namespace

  • Update the deployment.yml file to include the Namespace

  • Apply the updated deployment using the command: kubectl apply -f deployment.yml -n <namespace-name>

  • Verify that the Namespace has been created by checking the status of the Namespaces in your cluster.

Step 1: Create a Namespace

Run the following command to create a new namespace:

kubectl create namespace my-namespace

Replace my-namespace with your desired namespace name.

To verify the creation, list all namespaces:

kubectl get namespaces

Step 2: Update the deployment.yml File

Modify your deployment.yml to specify the namespace:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  namespace: my-namespace  # Add this line
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: nginx
          ports:
            - containerPort: 80

Make sure the namespace the field is added under metadata.


Step 3: Apply the Deployment to the Namespace

Use the following command to apply the deployment in the namespace:

kubectl apply -f deployment.yml -n my-namespace

This ensures that your deployment is created within the specified namespace.


Step 4: Verify the Namespace and Deployment

  1. Check if the namespace exists:

     kubectl get namespaces
    
  2. Verify that the deployment is created in the namespace:

     kubectl get deployments -n my-namespace
    
  3. Check the running pods inside the namespace:

     kubectl get pods -n my-namespace
    
  4. Describe the deployment (optional but useful for debugging):

     kubectl describe deployment my-deployment -n my-namespace
    

Once verified, your deployment should successfully run within the specified namespace.

Load Balancing, and Networking in Kubernetes:

Load balancing in Kubernetes distributes traffic across multiple pods or nodes. Kubernetes provides built-in load-balancing mechanisms:

Internal Load Balancing

  • Handled by ClusterIP or NodePort services within the cluster.

  • Kubernetes Service selects pods based on Label Selectors.

External Load Balancing

  • The LoadBalancer service provides an external IP for applications.

  • In cloud environments, Kubernetes automatically provisions a cloud provider’s load balancer.

Ingress Controller

  • Used for advanced routing and load balancing.

  • Works as an alternative to LoadBalancer services.

  • Example of an Ingress resource:

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: my-ingress
      spec:
        rules:
        - host: myapp.example.com
          http:
            paths:
            - path: /
              pathType: Prefix
              backend:
                service:
                  name: my-clusterip-service
                  port:
                    number: 80
    
  • This routes traffic from myapp.example.com to the ClusterIP service.

Networking in Kubernetes

Kubernetes networking follows these principles:

  • Every Pod gets its IP address.

  • Pods within the same cluster can communicate without NAT.

  • Containers in the same Pod communicate via localhost.

  • Network Policies can restrict access between Pods.

Key Networking Components

  1. Pod-to-Pod Communication

    • Kubernetes assigns a unique IP to each pod.

    • Communication is direct, meaning pods can talk to each other without NAT.

  2. Pod-to-Service Communication

    • Services abstract multiple pods behind a single IP.

    • Kubernetes DNS resolves service names automatically.

  3. Ingress for External Access

    • Ingress controllers allow domain-based routing and SSL termination.
  4. Network Policies

    • Used to restrict or allow traffic between Pods.

    • Example:

        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: allow-specific
          namespace: my-namespace
        spec:
          podSelector:
            matchLabels:
              app: my-app
          policyTypes:
          - Ingress
          ingress:
          - from:
            - podSelector:
                matchLabels:
                  app: trusted-app
      
    • This allows only Pods labeled trusted-app to communicate with my-app.

Working with Services in Kubernetes:

In Kubernetes, Services are objects that provide stable network identities for Pods and abstract the details of Pod IP addresses. They enable Pods to receive traffic from other Pods, Services, and external clients.

Task-1:

  • Create a Service for your todo-app Deployment

  • Create a Service definition for your todo-app Deployment in a YAML file.

  • Apply the Service definition to your K8s (minikube) cluster using the kubectl apply -f service.yml -n <namespace-name> command.

  • Verify that the Service is working by accessing the todo-app using the Service's IP and Port in your Namespace.

Step 1: Create the service.yml file

Save the following content as service.yml:

apiVersion: v1
kind: Service
metadata:
  name: todo-app-service
  namespace: <namespace-name>  # Replace with your actual namespace
spec:
  selector:
    app: todo-app  # This should match the label of your Deployment
  ports:
    - protocol: TCP
      port: 80       # Service port
      targetPort: 8080  # The container port your app is running on
  type: NodePort  # Exposes the service on a port accessible externally

Step 2: Apply the Service definition

Run the following command to apply the Service:

kubectl apply -f service.yml -n <namespace-name>

Step 3: Get Service Details

To check if the Service is running, use:

kubectl get services -n <namespace-name>

It will show an output similar to this:

NAME               TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
todo-app-service   NodePort   10.96.24.112     <none>        80:30007/TCP   10s

Step 4: Access the Todo-App

Since we used NodePort, you can access your application using:

minikube service todo-app-service -n <namespace-name> --url

This command will return a URL like:

http://192.168.49.2:30007

Open this URL in your browser or use curl to verify:

curl http://192.168.49.2:30007

This should return the app’s homepage or API response.

Task-2:

  • Create a ClusterIP Service for accessing the todo-app from within the cluster

  • Create a ClusterIP Service definition for your todo-app Deployment in a YAML file.

  • Apply the ClusterIP Service definition to your K8s (minikube) cluster using the kubectl apply -f cluster-ip-service.yml -n <namespace-name> command.

  • You can verify that the ClusterIP Service is working by accessing the to-do app from another Pod in the cluster in your Namespace.

Step 1: Create cluster-ip-service.yml

Save the following content as cluster-ip-service.yml:

apiVersion: v1
kind: Service
metadata:
  name: todo-app-clusterip-service
  namespace: <namespace-name>  # Replace with your actual namespace
spec:
  selector:
    app: todo-app  # Ensure this matches the label of your Deployment
  ports:
    - protocol: TCP
      port: 80       # The port to expose within the cluster
      targetPort: 8080  # The port on the todo-app container
  type: ClusterIP  # Default service type for internal cluster communication

Step 2: Apply the ClusterIP Service Definition

Run the following command:

kubectl apply -f cluster-ip-service.yml -n <namespace-name>

Step 3: Verify the Service

Check if the Service is running:

kubectl get services -n <namespace-name>

Expected output:

NAME                          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
todo-app-clusterip-service    ClusterIP   10.96.32.125   <none>        80/TCP    10s

Step 4: Access the Todo-App from Another Pod

To test if the Service is reachable within the cluster:

  1. Run a test Pod inside the same Namespace:

     kubectl run test-pod --image=busybox --restart=Never -n <namespace-name> -- sleep 3600
    
  2. Access the Pod’s shell:

     kubectl exec -it test-pod -n <namespace-name> -- sh
    
  3. Use curl or wget to access the Service:

     curl http://todo-app-clusterip-service:80
    

    If your app is running correctly, this should return an expected response.

  4. Exit the Pod:

     exit
    
  5. Cleanup the test Pod (optional):

     kubectl delete pod test-pod -n <namespace-name>
    

Task-3:

  • Create a LoadBalancer Service for accessing the todo-app from outside the cluster

  • Create a LoadBalancer Service definition for your todo-app Deployment in a YAML file.

  • Apply the LoadBalancer Service definition to your K8s (minikube) cluster using the kubectl apply -f load-balancer-service.yml -n <namespace-name> command.

  • Verify that the LoadBalancer Service is working by accessing the todo-app from outside the cluster in your Namespace.

Step 1: Create load-balancer-service.yml

Save the following content as load-balancer-service.yml:

apiVersion: v1
kind: Service
metadata:
  name: todo-app-loadbalancer-service
  namespace: <namespace-name>  # Replace with your actual namespace
spec:
  selector:
    app: todo-app  # Ensure this matches the label of your Deployment
  ports:
    - protocol: TCP
      port: 80       # The external port exposed by the service
      targetPort: 8080  # The port on the todo-app container
  type: LoadBalancer  # Exposes the service externally using a cloud provider's LB

Step 2: Apply the LoadBalancer Service Definition

Run the following command:

kubectl apply -f load-balancer-service.yml -n <namespace-name>

Step 3: Verify the Service

Check if the Service is running:

kubectl get services -n <namespace-name>

Expected output:

NAME                              TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
todo-app-loadbalancer-service     LoadBalancer   10.96.55.200     <pending>     80:31234/TCP   10s

In Minikube, the EXTERNAL-IP the field usually stays as <pending> because Minikube does not provide a cloud-based load balancer. Instead, use the following command:

minikube service todo-app-loadbalancer-service -n <namespace-name> --url

This will return a URL similar to:

http://192.168.49.2:31234

Step 4: Access the Todo-App from Outside the Cluster

Open the provided URL in a web browser or use curl to test:

curl http://192.168.49.2:31234

Alternative (Using Port Forwarding if LoadBalancer Doesn't Work in Minikube)

If minikube service doesn't work, you can use port forwarding as an alternative:

kubectl port-forward svc/todo-app-loadbalancer-service -n <namespace-name> 8080:80

Then access the app at:

http://localhost:8080