Target Kubernetes nodes using Ansible

Target Kubernetes nodes using Ansible

This week I needed to update the NTP settings on a Kubernetes cluster. I could have used an Ansible inventory (as decribed here), but instead choose to make a dynamic Ansible inventory, by querying the nodes from Kubernetes.

You can find the full playbook described here if you like.

Update Kubernetes using Ansible

Creating a dynamic Ansible inventory

The playbook I’ll use contains two Ansible plays. The first will query the Kubernetes nodes in the cluster and add those to the Ansible inventory, basically creating a dynamic inventory. The second will use the inventory to copy out the new NTP configuration and restart the NTP service.

Get Kubernetes nodes using Ansible

The first step is to query Kubernetes for the nodes in the cluster, for which I’ll use the lookup module. Then I’ll use the Ansible add_host module to add the hosts to my (now dynamic) Ansible inventory.

- name: Get Kubernetes nodes
  hosts: localhost
  tasks:
    - name: Get Kubernetes nodes
      set_fact:
        nodes: "{{ lookup('k8s', api_version='v1', kind='node') }}"
    - name: Add host to inventory
      add_host:
        hostname: "{{ item }}"
        groups:
        - Nodes
      with_list: "{{ nodes | json_query('[*].status.addresses[0].address') }}"

The first play shown above runs against the local host. Therefor the local Kubernetes credentials (./kube/config) will be used to connect to the Kubernetes cluster.

In the first task I set the variable nodes by using lookupto query the Kubernetes module for all nodes. This will return a great amount of detail about the Kubernetes nodes. However, we’re only interested in the IP addresses of the nodes, so we’ll need to extract those.

In the add_host module I use a with_list option to loop through the nodes variable and query the IP address using json_query. This json_query will return a list of IP addresses for my Kubernetes nodes, which the add_host will add to my inventory and also to the inventory group Nodes.

Update NTP servers

Now that I’ve dynamically created my Ansible Inventory, I can use the inventory to execute tasks against the hosts. In my case I’ll run the following tasks to update the NTP settings.

- name: Set NTP servers
  hosts: Nodes
  become: true
  tasks:
    - name: Make sure NTP is installed
      apt:
        name: ntp
        state: present
    - name: Copy NTP server configruation
      template: src=ntp.conf dest=/etc/ntp.conf
    - name: Stop NTP client
      service: name=ntp state=stopped
    - name: Sync time initialy
      shell: ntpd -gq
    - name: Make sure NTP is started up
      service: name=ntp state=started enabled=yes

As you can see on line 2, I’m targeting the Nodes group, which we created in our previous play. In the tasks, I do the following:

  • Install NTP using apt
  • Copy the ntp.conf from the template directory to the nodes
  • Stop the NTP client
  • Sync the node time using ntpd -gq which will also correct for large time offsets
  • Start the NTP client

That concludes the playbook.

Conclusion

We’ve seen how easy it is to create a dynamic Ansible inventory, by using a Ansible module (in this case the Kubernetes / k8s module) and use the output to create our dynamic inventory. We can then use that inventory to execute our regular playbook.

Hope you’ve found this useful and see you in the next blog!

Leave a Reply

Your email address will not be published.