Prefetch Technologies // Keeping your cache lines cozy

Running an ansible task on one node in a group

I've been using Ansible to provision and upgrade my Kubernetes clusters. As part of bootstraping my hosts ansible installs flannel, kube-router, kube-dns and in some cases kured. The deployment manifests that are used to create these resources need to be kubectl create'ed on a single node. When I was reasoning through the best way to approach this problem two ideas came to mind:

  • Run kubectl create on one of the controllers
  • Use delegate_to: localhost to apply the manifests

Both options work but the second one brings up an interesting question. If my inventory contains a list of controllers:

[kubcontrollers]
kubcontroller1.homefetch.net
kubcontroller2.homefetch.net
kubcontroller3.homefetch.net

How do I ensure that my kubectl create command runs on just one node? I did some experimenting and this is actually pretty easy to do. First, I created a new group with the first node in the kubcontrollers group:

[kubmaster]
kubcontroller1.homefetch.net

Then in my playbook I checked to see if the name in inventory_hostname is in the kubmaster group. If so, I run kubectl create on just that node. Here is the YAML I created to get this working:

- name: Check to see if the flannel deployment manifest exists
  stat:
    path: "{{ kubernetes_directory }}/{{ flannel_deployment_manifest }}"
  register: flannel_config_exists
  tags: flannel

- name: Create the flannel deployment manifest if it doesn't exist
  template:
    src: {{ flannel_deployment_manifest_template }}
    dest: "{{ kubernetes_directory }}/{{ flannel_deployment_manifest }}"
    owner: root
    group: root
    mode: 0600
  register: flannel_config_changed
  tags: flannel

- name: Creating the initial flannel pods with kubectl create
  shell: "{{ KUBECTL_BINARY }} create -f {{ kubernetes_directory }}/{{
flannel_deployment_manifest }}"
  args:
    chdir: "{{ kubernetes_directory }}"
  when: >
        inventory_hostname in groups['kubmaster'] and
        flannel_config_exists.stat.exists == False and
        flannel_config_changed.changed
  tags: flannel

Jesse Keating's Mastering Ansible and Jeff Geerling's Ansible for DevOps sure have come in handy during the development of my Kubernetes installation and upgrade playbooks. Loves me some ansible!