First, the yaml file is right,because I can use them directley create a mysql cluster in kubernetes.
but when I try to create a mysql cluster by kubernetes api for java, an error occured
The commond in yaml file cannot be recognized by the process.
The key component of the yaml file is as follows
initContainers:
- name: init-mysql
image: mysql:5.7.33
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
command:
- bash
- "-c"
- |
set -ex
[[ $(hostname) =~ -([0-9] )$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
echo [mysqld] > /mnt/conf.d/server-id.cnf
echo server-id=$((100 $ordinal)) >> /mnt/conf.d/server-id.cnf
if [[ ${ordinal} -eq 0 ]]; then
cp /mnt/config-map/master.cnf /mnt/conf.d
else
cp /mnt/config-map/slave.cnf /mnt/conf.d
fi
volumeMounts:
- name: conf
mountPath: /mnt/conf.d
- name: config-map
mountPath: /mnt/config-map
and the java code is as follows
........
........
.withInitContainers(new V1ContainerBuilder()
.withName("init-mysql")
.withImage("mysql:5.7.33")
.withEnv(env)
.withCommand("bash",
"\"-c\"",
"|",
"set -ex",
"[[ $(hostname) =~ -([0-9] )$ ]] || exit 1",
"ordinal=${BASH_REMATCH[1]}",
"echo [mysqld] > /mnt/conf.d/server-id.cnf",
"echo server-id=$((100 $ordinal)) >> /mnt/conf.d/server-id.cnf",
"if [[ ${ordinal} -eq 0 ]]; then",
" cp /mnt/config-map/master.cnf /mnt/conf.d",
"else",
" cp /mnt/config-map/slave.cnf /mnt/conf.d",
"fi"
)
.withVolumeMounts(new V1VolumeMountBuilder()
.withName("conf")
.withMountPath("/mnt/conf.d")
.build(),
new V1VolumeMountBuilder()
.withName("config-map")
.withMountPath("/mnt/config-map")
.build()
)
.build(),
......
......
The java code and the yaml file look the same, but when I execute it, an error occured. The result for kubectl logs is as follows
bash: "-c": No such file or directory
so I think it may be caused by the uncorrect params of withCommand function.
How can I fix it.Thank you.
CodePudding user response:
In your Java code, you are explicitly including double quotes in the string, withCommand("bash", "\"-c\"", ...)
. That's causing the container command to execute something similar to bash '"-c"' ...
where the quotes are part of the argument. In turn, that doesn't start with a hyphen, so bash interprets it as a script to run, but when there isn't a local file named exactly "-c"
including the quotes as part of the filename, you get that error.
The answer to your immediate question is just to remove those extra quotes
.withCommand("bash",
"-c", // no extra quotes here
...)
There's a second half of your question about the YAML syntax: why does what you show work? I believe it would also work to remove the double quotes here
command:
- bash
- -c
- ...
The trick here is that YAML has three different kinds of inline strings ("flow scalars"). Plain strings have no quotes but allow no escaping either; single-quoted strings have 'single quotes'
but very limited escaping options; and double-quoted strings have "double quotes"
and also can represent any string through escaping. Block scalars provide a further kind of string for multi-line text.
These are all the same:
- the same
- 'the same'
- "the same"
- "the\u0020same"
- >-
the same
In some cases you need a particular quoting style to work around YAML syntax issues. In your case, the -c
option looks somewhat similar to the YAML - item
list syntax (though the list syntax requires a space after the hyphen) so perhaps the original YAML author chose to quote it to make it unambiguous. It shouldn't be required here though.
The YAML parser will remove the quotes before the application sees them. In the Kubernetes case, this means the quotes around "-c"
are removed at the YAML layer and the actual command list contains [bash, -c, ...]
with no quotes.