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.
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 lookup
to 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!