I am trying to get a postStart hook working in a container but it keeps failing. The error I get is the following:
kubelet[1057]: E0212 11:07:20.205922 1057 handlers.go:78] "Exec lifecycle hook for Container in Pod failed" err=<
kubelet[1057]: command 'curl -H 'Content-Type: application/json' -d '{ \"restarted\": True}' -X POST http://localhost:5000/restarted' exited with 2: curl: (2) no URL specified
kubelet[1057]: curl: try 'curl --help' or 'curl --manual' for more information
kubelet[1057]: > execCommand=[curl -H 'Content-Type: application/json' -d '{ \"restarted\": True}' -X POST http://localhost:5000/restarted] containerName="srsran-cu-du" pod="srsran/srsran-project-cudu-chart-78f658b865-pjvt2" message=<
kubelet[1057]: curl: (2) no URL specified
kubelet[1057]: curl: try 'curl --help' or 'curl --manual' for more information
kubelet[1057]: >
The hook in my manifest looks like this:
lifecycle:
postStart:
exec:
command: [ "curl", "-H", "'Content-Type: application/json'", "-d", "'{ \"restarted\": True}'", "-X", "POST http://localhost:5000/restarted" ]
which renders to curl -H 'Content-Type: application/json' -d '{ \"restarted\": True}' -X POST http://localhost:5000/restarted
.
If I run the curl command as it renders in the container directly its working fine. But when running it via the posStart hook it doesn't work. What am I doing wrong?
I have tried replacing the '
with \\\"
but that also didnt work.
When you use an array-form command:
, or pass a command as a container's args:
, you need to pass exactly one shell word per YAML list item. The most immediate cause of your error is that there are two words in the last list item, so curl
interprets this as a single parameter requesting an HTTP method POST http://...
including a space, and then there is no following parameter with the URL.
You will also possibly get an error from the Content-Type:
header: because you have a set of single quotes inside the double-quoted YAML string, curl
will see these quotes as part of the -H
argument, and it may send an invalid HTTP header or reject the header syntax itself.
Splitting this out into one argument per word, using YAML block sequence syntax, and using only YAML quoting and only where required, I might write:
command:
- curl
- -H
- 'Content-Type: application/json' # quotes required, else `key: value` looks like a mapping
- -d
- '{ "restarted": true }' # YAML single quoting; double quotes do not need to be escaped; some quoting required else this looks like a JSON object
- -X
- POST
- http://localhost:5000/restarted # note two separate words
Or you could repack this into an inline list ("flow sequence"), using the same quoting rules
command: [curl, -H, 'Content-Type: application/json', -d, '{ "restarted": true }', -X, POST, http://localhost:5000/restarted]
Again, note that there is only one set of quotes for the Content-Type:
header, and that POST
and http://...
are separate list items. You can quote the other words too if you'd like, but it's only required for the couple of things that could be mistaken for other YAML syntax.