1
votes

I'm trying to write simple ansible playbook that would be able to execute some arbitrary command against the pod (container) running in kubernetes cluster.

I would like to utilise kubectl connection plugin: https://docs.ansible.com/ansible/latest/plugins/connection/kubectl.html but having struggle to figure out how to actually do that.

Couple of questions:

  1. Do I need to first have inventory for k8s defined? Something like: https://docs.ansible.com/ansible/latest/plugins/inventory/k8s.html. My understanding is that I would define kube config via inventory which would be used by the kubectl plugin to actually connect to the pods to perform specific action.
  2. If yes, is there any example of arbitrary command executed via kubectl plugin (but not via shell plugin that invokes kubectl on some remote machine - this is not what I'm looking for)

I'm assuming that, during the ansible-playbook invocation, I would point to k8s inventory.

Thanks.

3
Have a look at the k8s modulesZeitounator
Thanks for the pointer. While I'm able to execute some arbitrary k8s command like creating/deleting namespace or some other k8s object (using this plugin in Ansible), I don't see a way to actually connect to the specific pod/container in order to execute specific command inside the actual pod/container. Is there any way to do this?Bakir Jusufbegovic
Can't you do that using the dynamic inventory like on any other host ?Zeitounator
You almost never want to execute commands inside pods – if a node gets restarted and a pod gets rescheduled, your hand-run setup command won't get re-run. (Or if a HorizontalPodAutoscaler creates a new pod in response to load, or...) It's better to create a pod that can run totally autonomously.David Maze

3 Answers

1
votes

First install k8s collections

ansible-galaxy collection install community.kubernetes

and here is play-book, it will sort all pods and run a command in every pod

---
- 
  hosts: localhost

  vars_files: 
    - vars/main.yaml 

  collections:
    - community.kubernetes    

  tasks:     
    -
      name: Get the pods in the specific namespace
      k8s_info:
        kubeconfig: '{{ k8s_kubeconfig }}'
        kind: Pod
        namespace: test
      register: pod_list


    - 
      name: Print pod names
      debug:
         msg: "pod_list: {{ pod_list | json_query('resources[*].status.podIP')  }} "

    - set_fact:
        pod_names: "{{pod_list|json_query('resources[*].metadata.name')}}"

    - 
      k8s_exec:
        kubeconfig: '{{ k8s_kubeconfig }}'
        namespace: "{{ namespace  }}"
        pod: "{{ item.metadata.name }}"
        command: apt update
      with_items: "{{ pod_list.resources }}"
      register: exec
      loop_control:
        label: "{{ item.metadata.name }}"
0
votes

I would like to utilise kubectl connection plugin: https://docs.ansible.com/ansible/latest/plugins/connection/kubectl.html but having struggle to figure out how to actually do that.

The fine manual describes how one uses connection plugins, and while it is possible to use in in tasks, that is unlikely to make any sense unless your inventory started with Pods.

The way I have seen that connection used is to start by identifying the Pods against which you might want to take action, and then run a playbook against a unique group for that purpose:

- hosts: all
  tasks:
  - set_fact:
      # this is *just an example for brevity*
      # in reality you would use `k8s:` or `kubectl get -o name pods -l my-selector=my-value` to get the pod names
      pod_names:
      - nginx-12345
      - nginx-3456
  - add_host:
      name: '{{ item }}'
      groups:
      - my-pods
    with_items: '{{ pod_names }}'

- hosts: my-pods
  connection: kubectl
  tasks:
  # and now you are off to the races
  - command: ps -ef
  # watch out if the Pod doesn't have a working python installed
  # as you will have to use raw: instead
  # (and, of course, disable "gather_facts: no")
  - raw: ps -ef
0
votes

Maybe you can use like this...

 - shell: |

     kubectl exec -i -n {{ namespace }} {{ pod_name }} -- bash -c 'clickhouse-client --query "INSERT INTO customer FORMAT CSV"
 --user=test --password=test < /mnt/azure/azure/test/test.tbl'