Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

zarf_kubectl

Run a kubectl command through the kubectl zarf carries.

Write it as colonel_byte.zarf.zarf_kubectl. It runs zarf on the node the task is delegated to; nothing is installed on the cluster’s nodes.

Added in colonel_byte.zarf 0.88.0.

Runs zarf tools kubectl with the arguments given, against the cluster a kubeconfig names, and reports what it wrote to standard output.

The module is a compiled binary with zarf linked into it, and zarf vendors kubectl. It needs no zarf and no kubectl on the node, which is what it is for: a management node that drives an air-gapped cluster can read and apply resources without a kubectl of its own.

It is a passthrough and renders nothing into args. Zarf already vendors kubectl and already resolves which cluster to talk to, so projecting kubectl’s flags into Ansible parameters would be reimplementing kubectl in YAML. For declarative resource management prefer kubernetes.core.k8s, which this is not a replacement for.

Parameters

ParameterTypeRequiredFlagDescription
argslist of stryesNoneThe kubectl argument vector, as a list: ['get', 'pods', '-A']. A list rather than a command line, because a shell is what splits a command line into words and there is none here. A quoted selector stays one entry. Positional, so it renders no flag.
kubeconfigstrnoNoneThe kubeconfig of the cluster to act on. Zarf has no --kubeconfig flag, so it is passed as KUBECONFIG in the environment the command runs in. kubectl’s own --kubeconfig works too, in args.
wrapper_binarystrnoNoneThe module wrapper to run, resolved on the path when it holds no separator. The action plugin consumes this parameter; the wrapper never sees it.
parametersdictnoNoneFurther module parameters, merged into the ones given directly. A parameter given both directly and inside parameters is an error naming it. The action plugin consumes this key; the wrapper never sees it.

Notes

  • Set run_once: true and delegate_to on the task. One command runs against the whole cluster, so a play over the cluster’s own inventory would otherwise run it once per host.
  • The task always reports changed: true, with zarf.changedSignal set to unknown. The argument vector is kubectl’s, so the module knows the command succeeded and nothing about whether it altered anything. Set changed_when: false on a read.
  • Check mode reports the task as skipped, for the same reason: nothing here can tell a get from an apply.
  • Standard output comes back as zarf.output, with its trailing newline removed. Use -o json or -o yaml and from_json or from_yaml when a playbook has to read the result rather than show it.
  • A failure comes back as failed with kubectl’s own message in msg and its exit status in zarf.exitCode, including the failures kubectl would normally exit the process over – a cluster it cannot reach is one.
  • A command kubectl does not have is refused by name before anything runs, rather than printing kubectl’s help and reporting success.
  • kubectl plugins are not reachable, deliberately: the handler that resolves them can replace this process with the plugin, or exit it without a result.

Example

- name: Read the nodes of an air-gapped cluster without installing kubectl
  colonel_byte.zarf.zarf_kubectl:
    args:
      - get
      - nodes
      - -o
      - json
    kubeconfig: /etc/rancher/rke2/rke2.yaml
  delegate_to: localhost
  run_once: true
  changed_when: false
  register: nodes_result

- name: Report how many nodes are ready
  ansible.builtin.debug:
    msg: "{{ (nodes_result.zarf.output | from_json)['items'] | length }} nodes"

- name: Restart the zarf agent after rotating its certificate
  colonel_byte.zarf.zarf_kubectl:
    args:
      - rollout
      - restart
      - deployment/agent-hook
      - -n
      - zarf
    kubeconfig: /etc/rancher/rke2/rke2.yaml
  delegate_to: localhost
  run_once: true