This topic describes how to configure TLS for a VMware SQL with MySQL for Kubernetes instance.
VMware MySQL Operator is configured to require an encrypted connection for client communication.
The VMware MySQL Operator TLS configuration provides various options:
By default, the VMware MySQL Operator configures a self-signed ClusterIssuer
for issuing MySQL instance TLS certificates. See Using the Default provided TLS.
Administrators can also customize the Certificate Authority (CA) to comply with an organization’s CA. See Configuring a Custom TLS Issuer.
MySQL server administrators can override the default or the custom CA, by using a per instance TLS key pair. See Explicitly Configure a MySQL instance for TLS.
Note: From Tanzy MySQL 1.3.0, only TLSv1.2 and TLSv1.3 connections are supported
The MySQL Operator deploys the instances with TLS from the self-signed ClusterIssuer
configured during Operator install.
By default, the Operator will create a ClusterIssuer
named vmware-sql-with-mysql-operator-ca-certificate-clusterissuer
and will retrieve MySQL instance certificates issued via this resource.
To verify that your MySQL Operator is using the default settings, with no ClusterIssuer
customization, fetch the helm values:
helm --namespace=OPERATOR-NAMESPACE get values RELEASE-NAME
where: - OPERATOR-NAMESPACE
is the namespace where the operator is installed - RELEASE-NAME
is the name of the release for the helm installation
For example:
helm --namespace=vmware-mysql-for-kubernetes-system get values my-mysql-operator
The output should be similar to:
USER-SUPPLIED VALUES:
null
When installing the MySQL instances using the default MySQL Operator settings, the instance secret is named with the convention ${INSTANCE_NAME}-mysql-tls
. For example, if you used the default mysql.yaml
provided with the release, and created an instance:
kubectl apply --filename=config/samples/mysql.yaml
mysql.with.sql.tanzu.vmware.com/mysql-sample created
the instance would be called mysql-sample
and the default TLS secret would be mysql-sample-mysql-tls
. To view the secret, use:
kubectl get secret mysql-sample-mysql-tls --template='{{ index .data "ca.crt" | base64decode }}'
This returns an output similar to:
-----BEGIN CERTIFICATE-----
MIIDOzCCAiOgAwIBAgIRANSXXz7zVfItmCCvv/ZmOGAwDQYJKoZIhvcNAQELBQAw
NzE1MDMGA1UEAxMsdGFuenUtc3FsLXdpdGgtbXlzcWwtb3BlcmF0b3ItY2EtY2Vy
............
-----END CERTIFICATE-----
To override the default ClusterIssuer
follow the steps in Configuring a Custom TLS issuer. To explicitly configure an instance with a custom spec.tls.secret.name
and TLS key pair, see Explicitly Configure a MySQL instance for TLS.
This procedure describes how to configure a custom Certificate Authority (CA) and custom certificates using cert-manager. When you complete these steps, your VMware MySQL Operator will use the custom CA for any MySQL instance certificates.
Before you configure TLS using a custom CA authority, you must have access permissions to install or upgrade the VMware MySQL Operator using Helm.
Verify that cert-manager was configured during Installing the MySQL Operator prerequisites:
kubectl get all --namespace=CERT-MANAGER-NAMESPACE
where CERT-MANAGER-NAMESPACE
is the namespace where cert-manager is installed
Create a Kubernetes Secret for the CA certificate. For example, create a my-CA-secret.yaml
with values similar to:
apiVersion: v1
kind: Secret
metadata:
name: my-ca-certificate
namespace: CERT-MANAGER-NAMESPACE
type: kubernetes.io/tls
data:
tls.crt: this is a CA public key
tls.key: this is the CA private key
where CERT-MANAGER-NAMESPACE
is the namespace where cert-manager is installed
and apply with:
kubectl apply -f my-CA-secret.yaml
Note: The specific namespace for this secret depends on whether cert-manager was deployed with a specific --cluster-resource-namespace
option. Cert-manager defaults to the namespace cert-manager
to reference ClusterIssuer
resources such as CA certificate keypairs. See the cert-manager docs for details.
Create a CA issuer in cert-manager using a ClusterIssuer
resource and associate it with the CA Secret created in step 2. For information about the cert-manager Issuer
types, see Issuer Configuration in the cert-manager documentation.
Note: The MySQL instance TLS secret requires the ca.crt
key. The ACME Issuer does not provide a ca.crt
key, therefore VMware does not recommend using it.
Create a ClusterIssuer
resource using a yaml
file, for example my-cluster-issuer.yaml
, similar to:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: my-ca-certificate-clusterissuer
spec:
ca:
secretName: my-ca-certificate
Apply the Secret using:
kubectl apply -f my-cluster-issuer.yaml
For certificate creation troubleshooting see the cert-manager documentation.
Create or update the MySQL Operator to use the custom TLS issuer by using a command similar to:
helm --namespace=OPERATOR-NAMESPACE upgrade --install RELEASE-NAME CHART --set=certManagerClusterIssuerName=my-ca-certificate-clusterissuer
where: - OPERATOR-NAMESPACE
is the namespace where the operator is installed - RELEASE-NAME
is the name of the release for the helm installation - CHART
is a reference to the helm chart
For example:
helm --namespace=vmware-mysql-for-kubernetes-system upgrade --install my-mysql-operator /tmp/vmware-sql-with-mysql-operator --set=certManagerClusterIssuerName=my-ca-certificate-clusterissuer
Note: If you need to use more than one CA issuer, either see Explicitly Configure a MySQL instance for TLS or run another MySQL Operator in a different Kubernetes cluster.
To verify the custom ClusterIssuer
setup, use:
helm --namespace=OPERATOR-NAMESPACE get values RELEASE-NAME
where: - OPERATOR-NAMESPACE
is the namespace for the operator - RELEASE-NAME
is the name of the release for the helm installation
USER-SUPPLIED VALUES:
certManagerClusterIssuerName: my-ca-certificate-clusterissuer
To configure a MySQL instance for TLS without using the ClusterIssuer
through the Operator, you must first create a TLS Secret in the same namespace as the MySQL instance. There are several ways to create the Secret. This topic describes two methods:
After creating the secret, you add the name of the secret to your copy of the mysql.yaml
file, and configure the instance with the updated file, as described in Configure MySQL for TLS below.
For general information about TLS secrets, see the Kubernetes documentation.
Before you configure TLS for a MySQL instance, you must have:
Access and permissions to the MySQL instance.
The Kubernetes Command Line Interface (kubectl) installed: For more information, see the Kubernetes documentation.
This procedure describes how to create the TLS Secret using kubectl. To create the TLS Secret using cert-manager instead, see Create TLS Secret with cert-manager below.
Generate a certificate and private key using a certificate manager, such as OpenSSL or certstrap.
When creating the certificate, supply the server hostname for the subject alternative names (SANs). The server hostname is the DNS name that you use when connecting your app to the MySQL instance:
INSTANCE-NAME.DEVELOPMENT-NAMESPACE
, for example, mysql-sample.my-namespace
.spec.serviceType
as LoadBalancer
:Create the TLS Secret by running:
kubectl -n DEVELOPMENT-NAMESPACE create secret generic TLS-SECRET-NAME \
--type kubernetes.io/tls \
--from-file=tls.crt=PATH-TO-CERTIFICATE \
--from-file=tls.key=PATH-TO-PRIVATE-KEY \
--from-file=ca.crt=PATH-TO-CERTIFICATE-AUTHORITY
Where: + DEVELOPMENT-NAMESPACE
is the namespace for the MySQL instance. + TLS-SECRET-NAME
is the name you choose for the TLS Secret. + PATH-TO-CERTIFICATE
is the file path to the certificate created in the step above. + PATH-TO-PRIVATE-KEY
is the file path to the private key created in the step above. + PATH-TO-CERTIFICATE-AUTHORITY
is the file path to the certificate authority that signed the certificate.
For example:
kubectl -n my-namespace create secret generic mysql-tls-secret \
--type kubernetes.io/tls \
--from-file=tls.crt=/path/server.crt \
--from-file=tls.key=/path/server.key \
--from-file=ca.crt=/path/server_ca.crt
After completing the steps above, you add the secret to the instance by following the instructions in Configure MySQL for TLS below.
This procedure describes how to create the TLS Secret using cert-manager.
To create the TLS Secret through the kubectl instead, see Create the TLS Secret Manually above.
Verify that cert-manager was configured during Installing the MySQL Operator prerequisites:
kubectl get all --namespace=cert-manager
Use cert-manager to create either a cluster-wide ClusterIssuer
resource or a namespace-local Issuer
resource in the same namespace as your MySQL instance.
For information about the Issuer
types, see the cert-manager documentation.
Note: Because the MySQL instance requires that the TLS secret include the ca.crt
key, VMware does not recommend the ACME Issuer.
Choose and record a name for the TLS secret name, for example, mysql-tls-secret
. Use this name as the spec.secretName
when you create the Certificate
resource below.
Create a certificate request YAML. For instructions, see the cert-manager documentation. The following table suggests values for the YAML parameters.
Enter: | As this parameter in the YAML: |
---|---|
your TLS secret name from step 3 above, for example, mysql-tls-secret |
spec.secretName |
the name of your ClusterIssuer or Issuer created in step 2 above |
spec.issuerRef.name |
the DNS name or the fully qualified DNS name that you use to connect to apps deployed in the same Kubernetes cluster as the MySQL instance:
|
spec.dnsNames |
the external IP address of the load balancer that you use to connect to apps deployed outside the cluster. To find the address, see step 4 of Access the MySQL Server from an External IP Address . | spec.ipAddresses |
any additional DNS names that clients use to access the MySQL instance through a TLS connection | spec.dnsNames |
any additional URIs that clients use to access the MySQL instance through a TLS connection you might have configured to access your MySQL | spec.uris |
any additional IP addresses that clients use to access the MySQL instance through a TLS connection | spec.ipAddresses |
For information about troubleshooting certificate creation, see the cert-manager documentation.
Verify that the TLS secret created has the ca.crt
key by running:
kubectl -n DEVELOPMENT-NAMESPACE get secret TLS-SECRET-NAME -o jsonpath="{.data['ca\.crt']}"
Where: * DEVELOPMENT-NAMESPACE
is the namespace for the MySQL instance. * TLS-SECRET-NAME
is the name you chose for the TLS Secret.
For example:
kubectl -n my-namespace get secret mysql-tls-secret -o jsonpath="{.data['ca\.crt']}"
To configure TLS for the MySQL instance, using the precreated secret, follow these steps:
In your copy of the mysql.yaml
for the MySQL instance, specify spec.tls.secret.name
as the name of the TLS Secret created in the namespace.
Create or update the MySQL instance by running:
kubectl apply -f FILENAME -n DEVELOPMENT-NAMESPACE
Where: + FILENAME
is the name of the configuration file for your MySQL resource. + DEVELOPMENT-NAMESPACE
is the namespace for the MySQL instance.
This section shows how to connect to a MySQL instance configured with a load balancing service, spec.serviceType.LoadBalancer
, from an off-cluster machine running the MySQL command-line client.
In the procedure below, you give the client the certificate of the CA that signed the MySQL TLS certificate. The client uses this CA to authenticate the MySQL server-provided TLS certificate.
To connect the MySQL command-line client to the MySQL instance over TLS:
Obtain the certificate of the CA that signed the MySQL server’s TLS certificate.
The CA certificate is stored in the TLS secrets ca.crt
field, base64 encoded. Save that certificate to a local file ca.crt by running:
kubectl -n DEVELOPMENT-NAMESPACE get secret TLS-SECRET-NAME -o jsonpath="{.data['ca\.crt']}" | base64 -d > ca.crt
where TLS-SECRET-NAME
is the secret from Using the Default provided TLS or the custom configured secret in Configuring a Custom TLS Issuer or Explicitly Configure a MySQL instance for TLS.
For example:
kubectl -n my-namespace get secret mysql-tls-secret -o jsonpath="{.data['ca\.crt']}" | base64 -d > ca.crt
Create a MySQL username and password to test your connection with. You need to connect as a non-root user because MySQL instances prohibit root connection from remote machines.
For an example of creating a database, user, and password for connection testing, see Connecting Apps to MySQL Instances.
Obtain the IP address that your MySQL instance is listening on for connections. Load-balanced instances expose their IP address through their status.loadBalancer.ingress
property:
kubectl get service INSTANCE-NAME -o jsonpath={.status.loadBalancer.ingress[].ip}
Connect your local MySQL command-line client to your MySQL instance by running:
mysql --user=<USERNAME> --password=<PASSWORD> --host=<IP_ADDRESS> --ssl-mode=VERIFY_CA --ssl-ca=<CA-CERTPATH>
Where: * USERNAME
is the username you created above, for example, bn_wordpress
. * PASSWORD
is the password for the user you created above, for example, hunter2
. * IP-ADDRESS
is the external IP address from step 3 above. * CA-CERTPATH
is the pathname to the certificate file saved in step 1 above, for example, ./ca.crt
.
For example:
mysql --user=bn_wordpress --password=hunter2 --host=192.168.64.200 --ssl-mode=VERIFY_CA --ssl-ca=./ca.crt <br>
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
...
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.<br>
mysql>