Unable to run kubectl from ansible

4/3/2019

I'm trying to run a kubectl command from ansible.
Basically the command will tell me if at least one pod is running from a deployment.

kubectl get deploy sample-v1-deployment -o json -n sample | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"'

I tried to run it from a playbook but I'm getting

Unable to connect to the server: net/http: TLS handshake timeout

This is my playbook:

- hosts: master
  gather_facts: no
  become: true

  tasks:
    - name: test command
      shell: kubectl get deploy sample-v1-deployment -o json -n sample | jq '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status' | tr -d '"'
      register: result

This is the output from ansible:

changed: [k8smaster01.test.com] => {
    "changed": true,
    "cmd": "kubectl get deploy sample-v1-deployment -o json -n sample | jq '.status.conditions[] | select(.reason == \"MinimumReplicasAvailable\") | .status' | tr -d '\"'",
    "delta": "0:00:10.507704",
    "end": "2019-04-02 20:59:17.882277",
    "invocation": {
        "module_args": {
            "_raw_params": "kubectl get deploy sample-v1-deployment -o json -n sample | jq '.status.conditions[] | select(.reason == \"MinimumReplicasAvailable\") | .status' | tr -d '\"'",
            "_uses_shell": true,
            "argv": null,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "warn": true
        }
    },
    "rc": 0,
    "start": "2019-04-02 20:59:07.374573",
    "stderr": "Unable to connect to the server: net/http: TLS handshake timeout",
    "stderr_lines": [
        "Unable to connect to the server: net/http: TLS handshake timeout"
    ],
    "stdout": "",
    "stdout_lines": []
}

I can run the command manually on the master server without problems. I was also able to use k8s module to create different things on my kubernetes cluster.
I know there is a kubectl module on ansible, could it be the problem?

Thanks

-- radicaled
ansible
kubectl
kubernetes

2 Answers

4/3/2019

Looks like you can connect to your kube-apiserver on the master from a shell, but not from ansible. The error message indicates differences in the kubeconfig.

You can see the kube-apiserver endpoint configured on your ~/.kube/config like this:

$ kubectl config view --minify -o jsonpath='{.clusters[].cluster.server}'

It's typically something like this: https://<servername>:6443. You can try running the command from ansible to see if you get the same kube-apiserver.

Another thing is you can try is to print the value of the KUBECONFIG env variable from ansible to see if it's set to something different from ~/.kube/config

Hope it helps!

-- Rico
Source: StackOverflow

4/3/2019

I found a couple of workarounds.
One was to use the k8s_facts module

- name: Ensure running application
  k8s_facts:
    namespace: sample
    kind: Pod
    label_selectors:
      - app=sample-v1-app
  register: pod_list
  until: pod_list.resources[0].status.phase == 'Running'
  delay: 10
  retries: 3

Its simple and gets the works done.

The second workaround was to use the raw module instead of shell or command

- name: Get running status
  raw: kubectl get deploy sample-v1-deployment -o json -n sample | jq -r '.status.conditions[] | select(.reason == "MinimumReplicasAvailable") | .status'

I'm not sure about using raw. It looks like a hammer for a simple task.
But reading about the module makes me think this problem is related with the syntax (quotes, double quotes, |) more than the command it self.

Executes a low-down and dirty SSH command, not going through the module subsystem. This is useful and should only be done in a few cases. A common case is installing python on a system without python installed by default. Another is speaking to any devices such as routers that do not have any Python installed.

-- radicaled
Source: StackOverflow