Run Three WeSQL-Server Nodes in EKS
This document describes how to deploy a WeSQL-Server cluster (including one data node and two logger nodes) on Amazon EKS.
Prerequisites
Before we get started, let’s get a few prerequisites out of the way:
- Prepare an AWS S3 bucket for WeSQL backups and logging. You can apply a S3 Bucket for testing purpose.
- Install kubectl and ensure it is in your
PATH
. - Install the MySQL client locally.
- Prepare a Amazon EKS Kubernetes cluster.
Deploying the Cluster
1. Create the Configuration Files
Use kubectl
to create a ConfigMap with your WeSQL-Server configuration.
You need to replace the objectstore_provider
, objectstore_region
, and objectstore_bucket
with your AWS S3 bucket info.
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: wesql-server-config
data:
MYSQL_CUSTOM_CONFIG: |
[mysqld]
objectstore_provider=aws
objectstore_region=us-west-1
objectstore_bucket=wesql-storage
repo_objectstore_id=sysbench
branch_objectstore_id=main
log-bin=binlog
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
binlog_format=ROW
skip_name_resolve=ON
EOF
Since we need to expose MySQL's service address through AWS Load Balancer (NLB), and the NLB will periodically perform health checks on the port, we need to enable skip_name_resolve to avoid errors like this:
ERROR 1129 (HY000): Host '192.168.47.47' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
2. Create the Secret
Use kubectl
to create a secret with your AWS S3 credentials. Replace YOUR_S3_ACCESS_KEY
, YOUR_S3_SECRET_KEY
, and YOUR_MYSQL_ROOT_PASSWORD
with your actual AWS S3 credentials and desired MySQL root password.
kubectl create secret generic wesql-server-secret \
--namespace default \
--type Opaque \
--from-literal=WESQL_OBJECTSTORE_ACCESS_KEY=${YOUR_S3_ACCESS_KEY} \
--from-literal=WESQL_OBJECTSTORE_SECRET_KEY=${YOUR_S3_SECRET_KEY} \
--from-literal=MYSQL_ROOT_PASSWORD=${YOUR_MYSQL_ROOT_PASSWORD}
3. Prepare a Kubernetes Cluster
Make sure you have a Kubernetes cluster running. You can check the status of the cluster by running the following command:
kubectl cluster-info
Example Output (Amazon EKS):
Kubernetes control plane is running at https://<eks-endpoint>.eks.amazonaws.com
CoreDNS is running at https://<eks-endpoint>.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
4. Deploy the WeSQL-Server Cluster
Deploy the WeSQL-Server cluster by running:
kubectl apply -f https://raw.githubusercontent.com/wesql/deploy/refs/heads/main/artifact/wesql-server.yaml
Check the status of the pods to ensure the WeSQL-Server pods are running:
kubectl get pods
Example Output:
NAME READY STATUS RESTARTS AGE
mycluster-wesql-0-0 1/1 Running 0 17s
mycluster-wesql-1-0 1/1 Running 0 17s
mycluster-wesql-2-0 1/1 Running 0 17s
5. Set Up Port Forwarding (Optional)
If you prefer to access the cluster locally, forward the MySQL port to your machine:
kubectl port-forward pod/mycluster-wesql-0-0 3306:3306
mysql -h127.0.0.1 -uroot -p${YOUR_MYSQL_ROOT_PASSWORD}
Accessing the Cluster via the Public Network
To access your WeSQL-Server cluster from the internet, you need to expose the service externally by creating a public LoadBalancer. This allows you to connect to your database from outside the Kubernetes cluster.
1. Deploy the Public Service
Apply the public service configuration using kubectl
:
kubectl apply -f https://raw.githubusercontent.com/wesql/deploy/refs/heads/main/public-service/wesql-server-public-service.yaml
Content of wesql-server-public-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mycluster-wesql-server-public-service
namespace: default
labels:
app.kubernetes.io/component: wesql
app.kubernetes.io/instance: mycluster
spec:
type: LoadBalancer
ports:
- name: wesql
port: 3306
protocol: TCP
targetPort: wesql
selector:
app.kubernetes.io/component: wesql
app.kubernetes.io/instance: mycluster
2. Verify the LoadBalancer Creation
After applying the public service, Kubernetes will request your cloud provider (AWS) to provision a LoadBalancer. This process may take a few minutes.
Check the status of the service to get the external IP address or hostname:
kubectl get svc mycluster-wesql-server-public-service
Example Output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mycluster-wesql-public-service LoadBalancer 10.100.248.146 a1b2c3d4e5f6.us-west-1.elb.amazonaws.com 3306:30900/TCP 2m
Note: The
EXTERNAL-IP
field shows the DNS name of the LoadBalancer. It may take a few minutes for theEXTERNAL-IP
to be assigned.
3. Configure AWS Resources (If Necessary)
While Kubernetes automates the creation of the LoadBalancer, ensure the following AWS configurations are in place:
-
IAM Permissions: The AWS IAM role associated with your EKS worker nodes must have permissions to create and manage Elastic Load Balancers (ELBs). The necessary permissions include:
elasticloadbalancing:*
ec2:*
iam:ListServerCertificates
-
VPC and Subnets:
-
The EKS cluster should be deployed in a VPC with public subnets to allow internet access.
-
Public subnets should be tagged appropriately:
kubernetes.io/role/elb: 1
-
-
Security Groups:
- Ensure the security group associated with the LoadBalancer allows inbound traffic on port 3306 from your client IP address or the desired IP range.
4. Wait for DNS Propagation
The DNS name provided in the EXTERNAL-IP
may require some time to propagate. You can verify when it's ready by checking DNS resolution:
nslookup a1b2c3d4e5f6.us-west-1.elb.amazonaws.com
Once the DNS name resolves to an IP address, you can proceed to connect.
5. Connect to the WeSQL-Server Cluster
Use the MySQL client to connect to your database using the LoadBalancer's DNS name:
mysql -h a1b2c3d4e5f6.us-west-1.elb.amazonaws.com -P 3306 -uroot -p${YOUR_MYSQL_ROOT_PASSWORD}
Important: Replace
a1b2c3d4e5f6.us-west-1.elb.amazonaws.com
with the actualEXTERNAL-IP
DNS name from your service.
Troubleshooting Tips
-
If you receive an error like
Host 'X.X.X.X' is not allowed to connect to this MySQL server
, ensure your MySQL user is configured to allow connections from your client IP address. -
Firewall and Security Groups:
- Double-check that your AWS security groups allow inbound traffic on port 3306 from your IP address.
-
DNS Resolution Issues:
- If the DNS name isn't resolving, try flushing your DNS cache or wait a few more minutes for propagation.
-
LoadBalancer Status:
- Verify the LoadBalancer is in the
Active
state in the AWS console under EC2 > Load Balancers.
- Verify the LoadBalancer is in the
Security Considerations
-
Restrict Access:
- Limit inbound traffic to specific IP addresses using security group rules.
-
Use Secure Passwords:
- Ensure your MySQL root password is strong and not easily guessable.
-
Enable SSL/TLS:
- Configure MySQL to use SSL/TLS encryption for connections.
-
Monitor Access Logs:
- Regularly check logs for unauthorized access attempts.
-
Consider VPN or Bastion Hosts:
- For enhanced security, access the database through a VPN connection or via a bastion host instead of exposing it directly to the internet.
Delete the Cluster
Delete the WeSQL-Server cluster by running:
kubectl delete -f https://raw.githubusercontent.com/wesql/deploy/refs/heads/main/artifact/wesql-server.yaml
Delete the Load Balancer service (if created):
kubectl delete -f https://raw.githubusercontent.com/wesql/deploy/refs/heads/main/public-service/wesql-server-public-service.yaml
Delete the ConfigMap and Secret:
kubectl delete configmap wesql-server-config
kubectl delete secret wesql-server-secret
Additionally, you can wipe out the data by deleting PersistentVolumeClaims (PVCs) and S3 bucket objects:
kubectl get pvc
kubectl delete pvc data-mycluster-wesql-0-0 data-mycluster-wesql-1-0 data-mycluster-wesql-2-0
Next Steps
If you want to try out the WeScale feature, you can follow the tutorial: Deploying WeScale in Kubernetes.
By following these steps, you can deploy a WeSQL-Server cluster in Kubernetes and make it accessible over the internet. Always ensure you follow best practices for security and resource management when exposing services publicly.