1

goal and the issue

To have a container/Pod deployment that can be continously running. The command the container should execute is: /usr/local/bin/python3 and the args to the command are: "-c $'import time\\nwhile (True):\\n print(\".\");time.sleep(5);'". However, when I execute kubectl apply -f "PATH_TO_THE_KUBERNETES_YAML_FILE" the deployment errs with this Python exception: IndentationError: unexpected indent.

A screenshot of the error: enter image description here

The Pod deployment is used as the medium for calling Python code that interacts with the Certbot client as part of tasks when using LetsEncrypt certificates.

See the project here

So it should be possible to deploy the Pod >> do a kubectl exec ... into the container running as part of the Kubernetes deployment.

tried:

Various ways of defining the Kubernetes command args line.

  1. Via the exec Python option. E.g.: python3 -c exec(\"import time\nwhile True: print(\".\");time.sleep(5);\")
  2. Enclosing the code to execute with different combinations of ` and ".
  3. $'textwrap.dedent("""import time while True: print(".") time.sleep(5)""")'...
  4. tried using:

    args:
     - "-c $'import time\\nwhile (True):\\n print(\".\");time.sleep(5);'"
    

    as an alternative to args: ["-c $'import time\\nwhile (True):\\n print(\".\");time.sleep(5);'"]

  5. confirmed that the Python code itself works.

  6. both by using Python3 -c "..." directly and by calling it via a docker run command to a container from this Dockerfile
  7. I have done the usual Googling, Stack* search and so forth. I've also been on the official Kubernetes GitHub repo page and search through the issues there. Closed as well as open. And I have not seen any issue matching this one.
  8. Kubectl does not complain when doing ...apply -f YAML_FILE, in regards to the format of the YAML file and to the adherence of the Pod deployment specification.
  9. Tried with some bash code instead: ["/bin/bash", "-ecx", "while :; do printf '.'; sleep 5 ; done"]<-- that works.

further info

  • Python is v3.7.2
  • Kubernetes is v1.12.5-gke.10

It seems to be the combination of specifying the Python code in a Kubernetes Pod deployment YAML file ... that doesn't go well with Pythons requirement of significant whitespace and indentation. As you can read in the #tried section, it works when calling Python directly or via a Docker run/exec command.

How can I troubleshoot this?

Lars Bingchong
  • 323
  • 3
  • 12
  • Where does it say the unexpected indent come from? – wizzwizz4 Apr 01 '19 at 21:10
  • Why do you want to provide the complete code via `-c`? Why not just write it to a file and run the file? If you really want to run that code you can use `python -c $'import time\nwhile True: print("."); time.sleep(5);'`. No need to use new lines for the while suite since you can join simple statements by semicolons as described [in the docs](https://docs.python.org/3/reference/compound_stmts.html). – a_guest Apr 01 '19 at 22:16
  • @a_guest thank you for the suggestion. I've actually tried that. See bullet point 1 in my question. – Lars Bingchong Apr 02 '19 at 05:33
  • @wizzwizz4 - I added a screenshot of the error. It points to the start of the line. Which is not that helpful. – Lars Bingchong Apr 02 '19 at 07:04
  • @LarsBingchong Bullet point 1 reads `python3 -c exec(\"import time\nwhile True: print(\".\");time.sleep(5);\")` which is substantially different from what I suggested `python -c $'import time\nwhile True: print("."); time.sleep(5);'` as it contains an additional call to `exec` (why? did you check `man exec` to confirm it's doing what you want?) and some additional backslashes which I can't make sense of. You might also want to read `man python` and scroll down to section "Interpreter Interface"; an excerpt: *"when called with -c command, it executes the Python statement(s) given as command."*. – a_guest Apr 02 '19 at 07:25
  • @a_guest I tried the `exec` option as the other tries I have been through did not work. Again I think this is likely the combination of Kubernetes YAML for a POD deployment and Python. As it works when called directly on the cmdline or via a "regular" Docker container. To me that the statement is executed as a `command` is quite alright. Is there something in particular I should be observant on? – Lars Bingchong Apr 02 '19 at 08:06
  • @LarsBingchong To work around the issue (instead of solve it), have you tried removing the newline-space after the colon after the `while`? – wizzwizz4 Apr 02 '19 at 16:44
  • Hi @wizzwizz4 - I did `$'import time\nwhile True:print('.'); time.sleep(5);` and the same issue remains. Unfortunately :-). I just added a couple of extra tags to this question. So that people looking for Kubernetes issues/questions hopefully will also find it. – Lars Bingchong Apr 03 '19 at 06:09

1 Answers1

1

So I was able to get help on this on the Kubernetes Slack channel. It was a YAML syntax issue.

The following in the Pod deployment YAML file solved it

  args:
    - |-
      -c
      import time
      while True:
          print('.')
          time.sleep(5)

this works in combination with the Dockerfile's....

FROM larssb/certbot-dns-cloudflare-python3
LABEL author="https://github.com/larssb"

#
# Container config
#
WORKDIR /letsencryptit

#
# COPY IN DATA
#
COPY ./scripts /scripts/
COPY ./letsencryptit /letsencryptit/

#
# INSTALL
#
RUN pip install --upgrade google-api-python-client --disable-pip-version-check --no-cache-dir \
    && pip install --upgrade oauth2client --disable-pip-version-check --no-cache-dir \
    && pip install --upgrade sty --disable-pip-version-check --no-cache-dir \
    && chmod +x /scripts/deploy-hook-runner.sh

# Set an ENTRYPOINT to override the entrypoint specified in certbot/certbot
ENTRYPOINT ["/usr/local/bin/python3"]
CMD ["-c"]

ENTRYPOINT, as this is re-used by the Pod deployment. However, the Dockerfile's CMD is overwritten by the args property in the Pod deployment YAML file.

The args property explained in detail

  • The -c is a parameter to the Python binary
  • The rest is std. Python code, to have the container, deployed via the Pod deployment, continuously run so that it can be on standby for command calls to it via kubectl exec

The key

This part of the args property > - |-. It strips the line feed and any trailing blank lines. Making it possible to state a multi-line Python block of code

Documentation


Kudos to @wizzwizz4, @a_guest for your comments and suggestions. They helped me troubleshoot this, narrow in on a solution. Also a big thank you to Mr. @grampelberg on the Kubernetes Slack channel for assisting me and providing the solution.

Lars Bingchong
  • 323
  • 3
  • 12