Home > other >  how to ues kubernetes api for java to create mysql cluster
how to ues kubernetes api for java to create mysql cluster

Time:08-04

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.

  • Related