# 🌟 (Day-10) Pod Affinity in Kubernetes

### What is Pod Affinity in Kubernetes?

Pod affinity in Kubernetes is a feature that allows you to control how Pods are scheduled (placed) based on the location of other Pods. It helps you define rules so that certain Pods prefer to run near or on the same node (or group of nodes) as other Pods. This is useful for optimizing performance or ensuring that related Pods are placed together.

There are two types of affinity: **pod affinity** (where you want pods to be close to other pods) and **pod anti-affinity** (where you want to keep pods apart).

### 🔄 **Types of Affinity**

### 1\. **Pod Affinity (Attraction)**

* **Definition**: This specifies that certain pods should be scheduled close to each other.
    
* **Example**:
    
    * **Scenario**: You have a frontend service (e.g., a web application) and a backend service (e.g., an API) that need to communicate frequently.
        
    * **Usage**: You can set pod affinity to ensure that both the frontend and backend pods are scheduled on the same node. This reduces network latency and improves communication speed.
        

### 2\. **Pod Anti-Affinity (Separation)**

* **Definition**: This prevents certain pods from being scheduled on the same node as other specific pods.
    
* **Example**:
    
    * **Scenario**: You have a database application with multiple replicas for high availability. You want to make sure that not all replicas are on the same node.
        
    * **Usage**: You can use pod anti-affinity to spread the database replicas across different nodes. If one node fails, not all replicas go down, ensuring better availability.
        

### ⚙️ **Types of Affinity Rules**

* **Affinity (Preferred)**: Pods prefer to be scheduled on a node near or with other Pods, but it's not mandatory.
    
* **Anti-Affinity (Preferred)**: Pods prefer to avoid being scheduled on the same node as specific Pods but can still be scheduled there if needed.
    
* **Affinity (Required)**: Pods must be scheduled on a node with or near specific Pods.
    
* **Anti-Affinity (Required)**: Pods must not be scheduled on the same node as specific Pods.
    

### 🔍How Pod Affinity Works:

Affinity rules are defined in the pod’s YAML configuration. You can specify conditions based on labels.  
**Example**: A pod can be set to prefer running on the same node as another pod with a specific label.

### 🌈 **Key Features / Benefits of Pod Affinity**

* **Optimized Resource Usage**:  
    Pods can share resources like memory, disk, or CPU, reducing latency and increasing performance for interdependent services.
    
* **Improved Performance**:  
    Co-locating related pods (e.g., microservices) reduces network latency, enhancing internal communication.
    
* **Flexibility in Scheduling**:  
    Control how pods are placed in relation to others, leading to more efficient deployments.
    
* **Enhanced Availability**:  
    Anti-affinity rules distribute pods across different nodes, improving fault tolerance and availability.
    
* **Resiliency and Redundancy**:  
    Spread workloads across nodes to minimize simultaneous failures if a node goes down.
    
* **Topology-Aware Scheduling**:  
    Define affinity rules based on topology keys (like hostnames, zones, or regions) for better control of pod locations.
    

---

### 📌 **Use Cases for Pod Affinity**

* **Co-locating Interdependent Microservices**:  
    Place frontend and backend services on the same node to reduce communication latency.
    
* **Running Pods on Nodes with Specific Hardware**:  
    Schedule pods on nodes with required hardware features (e.g., GPUs or SSDs).
    
* **Stateful Applications (e.g., Databases)**:  
    Ensure high-performance, low-latency access to storage by colocating stateful applications with their resources.
    
* **High Availability and Fault Tolerance**:  
    Anti-affinity rules distribute replicas across nodes to avoid single points of failure.
    
* **Ensuring Security or Compliance**:  
    Maintain security boundaries by colocating or spreading apart specific workloads.
    

### 📝 **Example YAML for Pod Affinity**

```bash
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - frontend
          topologyKey: "kubernetes.io/hostname"
  containers:
  - name: my-app
    image: my-app-image
```

In this example, the pod will only be scheduled on nodes that already have a pod with the label `app: frontend` on the same node (topologyKey: [`kubernetes.io/hostname`](http://kubernetes.io/hostname)).

### 🔀 **Example YAML for Pod Anti-Affinity**

**Ensuring High Availability for Stateful Applications**

For a database application (e.g., a stateful set for a MongoDB replica set), you may want to prevent multiple database instances from being scheduled on the same node. This ensures that if a node fails, not all database instances will be affected.

#### YAML Configuration:

```bash
yamlCopy codeapiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  serviceName: "mongodb"
  replicas: 3
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: mongodb
                topologyKey: "kubernetes.io/hostname"
      containers:
      - name: mongodb
        image: mongo
```

#### Explanation:

In this StatefulSet configuration, the `preferredDuringSchedulingIgnoredDuringExecution` rule allows the scheduler to prefer placing MongoDB instances on different nodes. The `weight` indicates the importance of this rule, with higher values preferred over lower ones. If nodes are unavailable, the pods may still be scheduled on the same node, but this configuration aims to maximize availability.

# 🚀 Let's Get Into Kubernetes Pod Affinity Hands-On!

In this hands-on exercise, you'll learn how to create Kubernetes pods with pod affinity. Follow the steps below to set up your environment and observe how pod affinity works.

**🔍Check the Number of Nodes in the Cluster**

```bash
kubectl get nodes
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727797200077/733bf709-fab2-4d81-8589-6b30d8bbb2a0.png align="left")

📝 **Create the First Pod YAML. Note that the label used is app: nginx**

```bash
vi aff-pa-pod1.yaml
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727797550254/2d0f9ec6-fec2-4393-992a-070ab67c6d04.png align="left")

🚀**Apply the YAML configuration**

```bash
kubectl apply -f aff-pa-pod1.yaml
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727797588819/20dd2f13-9646-4514-9c8d-a39e937d2e0a.png align="left")

🔍**Check Pod Status and Node**

To see the details of the pod, including the node on which it is scheduled, use:

```bash
kubectl get pods -o wide
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727797633684/ae0581ca-63e0-437c-a8b0-102a410f42ca.png align="left")

📝**Create the Second Pod YAML with Pod Affinity**

```bash
vi aff-pa-pod2.yaml
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727798466795/90890c06-69fd-40c2-9667-0d5ef5c58a94.png align="left")

🚀**Apply the Second Pod YAML**

```bash
kubectl apply -f aff-pa-pod2.yaml
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727798438348/a0ddf285-fc37-4bc7-949b-6ed53f6afce2.png align="left")

🔍**Verify the Node for the Second Pod**

Check which node the pod is scheduled on. You'll see that the pod is on the same node as the one created earlier.

```bash
kubectl get pods -o wide
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727798586974/93016bd0-d387-4632-8355-c4e08d4a852d.png align="left")

### Why are Both Pods on the Same Node?

Both `pa-nginx-pod1` and `pa-nginx-pod2` were scheduled on the same node (`i-0d1e1adfe3c21a721`). This happened because of the following reasons:

1. **Affinity Rules**: The affinity rules may not strictly prevent two pods from being on the same node, especially if you used `preferredDuringSchedulingIgnoredDuringExecution` for node affinity. This setting allows Kubernetes to prioritize a node that matches the affinity, but it can still place multiple pods on the same node if necessary.
    
2. **Resource Availability**: Kubernetes ensures that pods are scheduled based on available resources. If the node has enough resources to handle both pods, they will be placed there to ensure that the pods run smoothly.
    
3. **Topology Key**: If you specified affinity with `topologyKey` (such as [`kubernetes.io/hostname`](http://kubernetes.io/hostname)), Kubernetes schedules pods on nodes based on the hostname, which might result in both being placed on the same node.
    

### 🧹Task 3: Clean-up

Delete the pods created in the previous task.

```bash
kubectl delete -f aff-pa-pod1.yaml
```

```bash
kubectl delete -f aff-pa-pod2.yaml
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727799090839/e098cc32-40d1-443a-992e-7063022b4d6f.png align="left")

### Conclusion

Pod affinity in Kubernetes is a powerful tool for optimizing pod placement, enhancing performance, and ensuring high availability. By defining affinity and anti-affinity rules, you can tailor your application's deployment to meet specific requirements, improving both resource utilization and fault tolerance.

As you continue to explore Kubernetes, consider delving into advanced topics such as **custom scheduling strategies** and **resource quotas**, which can further refine how you manage your applications. Happy clustering!
