Home > Software engineering >  Ansible task to filter out specific pod names from kubectl command output
Ansible task to filter out specific pod names from kubectl command output

Time:01-18

I am trying to create an ansible playbook to delete specific pods from k8s default namespace.

There are 2 lists:

  • pod_list (dynamically created with kubectl get pods command output)
  • pod_filter (pre-defined regular expressions, or just the beginning of the pod names)

The idea is to iterate over the pod_list and filter out the names that matches the patterns specified in pod_filter.

Playbook:

---
- name: Delete specific pods
  hosts: localhost

  vars:
    pod_filter:
      - hello # beginning of the pod name
      - mysql # beginning of the pod name
      - myui-557f994996-5vp8l # exact pod name

  tasks:
    - name: Get a list of all pods from the namespace
      #command: kubectl get pods --output=jsonpath='{.items[*].metadata.name}'  # Output is a single line
      command: kubectl get pods --no-headers -o custom-columns=":metadata.name" # Output is a column
      register: pod_list     

    - name: Iterate over pod names
      debug:
        msg: "{{ item }}"  
      # command: kubectl delete pod "{{ item }}"
      # pod_list.stdout_lines is a list, but pod_list.stdout is not.
      loop: "{{ pod_list.stdout_lines }}"
      when: item in pod_filter

The output is like:

$ ansible-playbook test.yaml

[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Delete specific pods] *******************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************
ok: [localhost]

TASK [Get a list of all pods from the namespace] ***********************************************************************************************************
changed: [localhost]

TASK [Iterate over pod names] ******************************************************************************************************************************
skipping: [localhost] => (item=hello-768bb8fcd-qptnl)
skipping: [localhost] => (item=mysql-66cdf96976-9jg2v)
ok: [localhost] => (item=myui-557f994996-5vp8l) => {
    "msg": "myui-557f994996-5vp8l"
}

PLAY RECAP *************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

The condition when: item in pod_filter succeeds only when the exact pod name is specified in the pod_filter list. It doesn't work if i specify only a part (beginning) of the pod names in the pod_filter list.

Ansible docs regarding Tests mentions about match:

match succeeds if it finds the pattern at the beginning of the string

What condition should be specified as when for this purpose? Should there be a nested loop iterate over the two lists?

CodePudding user response:

The condition should be : when: item is match(pod_filter|join('|')) which would effectively cat your regexes together into one.

Then task will look like this:

- name: Iterate over pod names and delete the filtered ones
  # debug:
  #   msg: "{{ item }}"  
  command: kubectl delete pod "{{ item }}"
  loop: "{{ pod_list.stdout_lines }}"
  when: item is match(pod_filter|join('|'))

CodePudding user response:

In addition to AnjanaAK's solution, you could also use the Kubernetes collection

https://docs.ansible.com/ansible/latest/collections/kubernetes/core/k8s_info_module.html#ansible-collections-kubernetes-core-k8s-info-module

Then use kubectl-like filtering. One of the examples provided in the documentation:

- name: Search for all Pods labelled app=web
  kubernetes.core.k8s_info:
    kind: Pod
    label_selectors:
      - app = web
      - tier in (dev, test)
  •  Tags:  
  • Related