This document describes how to deploy a TiDB cluster to Kubernetes on your laptop (Linux or macOS) for development or testing.
Docker in Docker (DinD) runs Docker containers as virtual machines and runs another layer of Docker containers inside the first layer of Docker containers. kubeadm-dind-cluster uses this technology to run the Kubernetes cluster in Docker containers. TiDB Operator uses a modified DinD script to manage the DinD Kubernetes cluster.
Before deploying a TiDB cluster to Kubernetes, make sure the following requirements are satisfied:
-
Resources requirement: CPU 2+, Memory 4G+
Note: For macOS, you need to allocate 2+ CPU and 4G+ Memory to Docker. For details, see Docker for Mac configuration.
-
Docker: 17.03 or later
Note: Legacy Docker Toolbox users must migrate to Docker for Mac by uninstalling Legacy Docker Toolbox and installing Docker for Mac, because DinD cannot run on Docker Toolbox and Docker Machine.
Note:
kubeadm
validates installed Docker version during the installation process. If you are using Docker later than 18.06, there would be warning messages. The cluster might still be working, but it is recommended to use a Docker version between 17.03 and 18.06 for better compatibility. You can find older versions of docker here. -
Helm Client: version >= 2.9.0 and < 3.0.0
-
Kubectl: 1.10 at least, 1.13 or later recommended
Note: The outputs of different versions of
kubectl
might be slightly different. -
For Linux users,
kubeadm
might produce warning messages during the installation process if you are using kernel 5.x or later versions. The cluster might still be working, but it is recommended to use kernel version 3.10+ or 4.x for better compatibility. -
root
access or permissions to operate with the Docker daemon. -
Supported filesystem
For Linux users, if the host machine uses an XFS filesystem (default in CentOS 7), it must be formatted with
ftype=1
to enabled_type
support, see Docker's documentation for details.You can check if your filesystem supports
d_type
using commandxfs_info / | grep ftype
, where/
is the data directory of you installed Docker daemon.If your root directory
/
uses XFS withoutd_type
support, but there is another partition does, or is using another filesystem, it is also possible to change the data directory of Docker to use that partition.Assume a supported filesystem is mounted at path
/data
, use the following instructions to let Docker use it:# Create a new directory for docker data storage mkdir -p /data/docker # Stop docker daemon systemctl stop docker.service # Make sure the systemd directory exist mkdir -p /etc/systemd/system/docker.service.d/ # Overrite config cat << EOF > /etc/systemd/system/docker.service.d/docker-storage.conf [Service] ExecStart= ExecStart=/usr/bin/dockerd --data-root /data/docker -H fd:// --containerd=/run/containerd/containerd.sock EOF # Restart docker daemon systemctl daemon-reload systemctl start docker.service
First, make sure that the docker daemon is running, and you can install and set up a Kubernetes cluster (version 1.12) using DinD for TiDB Operator with the script in our repository:
# Get the code
$ git clone --depth=1 https://github.com/pingcap/tidb-operator
# Set up the cluster
$ cd tidb-operator
$ manifests/local-dind/dind-cluster-v1.12.sh up
If the cluster fails to pull Docker images during the startup due to the firewall, you can set the environment variable KUBE_REPO_PREFIX
to uhub.ucloud.cn/pingcap
before running the script dind-cluster-v1.12.sh
as follows (the Docker images used are pulled from UCloud Docker Registry):
$ KUBE_REPO_PREFIX=uhub.ucloud.cn/pingcap manifests/local-dind/dind-cluster-v1.12.sh up
An alternative solution is to configure HTTP proxies in DinD:
$ export DIND_HTTP_PROXY=http://<ip>:<port>
$ export DIND_HTTPS_PROXY=http://<ip>:<port>
$ export DIND_NO_PROXY=.svc,.local,127.0.0.1,0,1,2,3,4,5,6,7,8,9 # whitelist internal domains and IP addresses
$ manifests/local-dind/dind-cluster-v1.12.sh up
There might be some warnings during the process due to various settings and environment of your system, but the command should exit without any error. You can verify the k8s cluster is up and running by:
# Get the cluster information
$ kubectl cluster-info
Kubernetes master is running at http://127.0.0.1:8080
KubeDNS is running at http://127.0.0.1:8080/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
kubernetes-dashboard is running at http://127.0.0.1:8080/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy
# List host nodes (in the DinD installation, they are docker containers) in the cluster
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kube-master Ready master 11m v1.12.5 10.192.0.2 <none> Debian GNU/Linux 9 (stretch) 3.10.0-957.12.1.el7.x86_64 docker://18.9.0
kube-node-1 Ready <none> 9m32s v1.12.5 10.192.0.3 <none> Debian GNU/Linux 9 (stretch) 3.10.0-957.12.1.el7.x86_64 docker://18.9.0
kube-node-2 Ready <none> 9m32s v1.12.5 10.192.0.4 <none> Debian GNU/Linux 9 (stretch) 3.10.0-957.12.1.el7.x86_64 docker://18.9.0
kube-node-3 Ready <none> 9m32s v1.12.5 10.192.0.5 <none> Debian GNU/Linux 9 (stretch) 3.10.0-957.12.1.el7.x86_64 docker://18.9.0
Once the k8s cluster is up and running, we can install TiDB Operator into it using helm
:
$ helm install charts/tidb-operator --name=tidb-operator --namespace=tidb-admin --set scheduler.kubeSchedulerImageName=mirantis/hypokube --set scheduler.kubeSchedulerImageTag=final
Then wait a few minutes until TiDB Operator is running:
$ kubectl get pods --namespace tidb-admin -l app.kubernetes.io/instance=tidb-operator
NAME READY STATUS RESTARTS AGE
tidb-controller-manager-5cd94748c7-jlvfs 1/1 Running 0 1m
tidb-scheduler-56757c896c-clzdg 2/2 Running 0 1m
By using helm
along with TiDB Operator, we can easily set up a TiDB cluster:
$ helm install charts/tidb-cluster --name=demo --namespace=tidb
And wait a few minutes for all TiDB components to get created and ready:
# Use `Ctrl + C` to exit watch mode
$ kubectl get pods --namespace tidb -l app.kubernetes.io/instance=demo -o wide --watch
# Get basic information of the TiDB cluster
$ kubectl get tidbcluster -n tidb
NAME PD STORAGE READY DESIRE TIKV STORAGE READY DESIRE TIDB READY DESIRE
demo pingcap/pd:v3.0.1 1Gi 3 3 pingcap/tikv:v3.0.1 10Gi 3 3 pingcap/tidb:v3.0.1 2 2
$ kubectl get statefulset -n tidb
NAME DESIRED CURRENT AGE
demo-pd 3 3 1m
demo-tidb 2 2 1m
demo-tikv 3 3 1m
$ kubectl get service -n tidb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-discovery ClusterIP 10.96.146.139 <none> 10261/TCP 1m
demo-grafana NodePort 10.111.80.73 <none> 3000:32503/TCP 1m
demo-pd ClusterIP 10.110.192.154 <none> 2379/TCP 1m
demo-pd-peer ClusterIP None <none> 2380/TCP 1m
demo-prometheus NodePort 10.104.97.84 <none> 9090:32448/TCP 1m
demo-tidb NodePort 10.102.165.13 <none> 4000:32714/TCP,10080:32680/TCP 1m
demo-tidb-peer ClusterIP None <none> 10080/TCP 1m
demo-tikv-peer ClusterIP None <none> 20160/TCP 1m
$ kubectl get configmap -n tidb
NAME DATA AGE
demo-monitor 5 1m
demo-monitor-dashboard-extra-v3 2 1m
demo-monitor-dashboard-v2 5 1m
demo-monitor-dashboard-v3 5 1m
demo-pd 2 1m
demo-tidb 2 1m
demo-tikv 2 1m
$ kubectl get pod -n tidb
NAME READY STATUS RESTARTS AGE
demo-discovery-649c7bcbdc-t5r2k 1/1 Running 0 1m
demo-monitor-58745cf54f-gb8kd 2/2 Running 0 1m
demo-pd-0 1/1 Running 0 1m
demo-pd-1 1/1 Running 0 1m
demo-pd-2 1/1 Running 0 1m
demo-tidb-0 1/1 Running 0 1m
demo-tidb-1 1/1 Running 0 1m
demo-tikv-0 1/1 Running 0 1m
demo-tikv-1 1/1 Running 0 1m
demo-tikv-2 1/1 Running 0 1m
To access the TiDB cluster, use kubectl port-forward
to expose services to the host. The port numbers in command are in <host machine port>:<k8s service port>
format.
Note: If you are deploying DinD on a remote machine rather than a local PC, there might be problems accessing "localhost" of that remote system. When you use
kubectl
1.13 or later, it is possible to expose the port on0.0.0.0
instead of the default127.0.0.1
by adding--address 0.0.0.0
to thekubectl port-forward
command.
-
Access TiDB using the MySQL client
Before you start testing your TiDB cluster, make sure you have installed a MySQL client.
-
Use
kubectl
to forward the host machine port to the TiDB service port:$ kubectl port-forward svc/demo-tidb 4000:4000 --namespace=tidb
Note: If the proxy is set up sucessfully, it will print something like
Forwarding from 0.0.0.0:4000 -> 4000
. After testing, pressCtrl + C
to stop the proxy and exit. -
Then, to connect to TiDB using the MySQL client, open a new terminal tab or window and run the following command:
$ mysql -h 127.0.0.1 -P 4000 -u root
-
-
View the monitor dashboards
-
Use
kubectl
to forward the host machine port to the Grafana service port:$ kubectl port-forward svc/demo-grafana 3000:3000 --namespace=tidb
Note: If the proxy is set up sucessfully, it will print something like
Forwarding from 0.0.0.0:3000 -> 3000
. After testing, pressCtrl + C
to stop the proxy and exit. -
Then, open your web browser at http://localhost:3000 to access the Grafana monitoring interface.
- Default username: admin
- Default password: admin
-
-
Permanent remote access
Although this is a very simple demo cluster and does not apply to any serious usage, it is useful if it can be accessed remotely without
kubectl port-forward
, which might require an open terminal.TiDB, Prometheus, and Grafana are exposed as
NodePort
Services by default, so it is possible to set up a reverse proxy for them.-
Find their listing port numbers using the following command:
$ kubectl get service -n tidb | grep NodePort demo-grafana NodePort 10.111.80.73 <none> 3000:32503/TCP 1m demo-prometheus NodePort 10.104.97.84 <none> 9090:32448/TCP 1m demo-tidb NodePort 10.102.165.13 <none> 4000:32714/TCP,10080:32680/TCP 1m
In this sample output, the ports are: 32503 for Grafana, 32448 for Prometheus, and 32714 for TiDB.
-
Find the host IP addresses of the cluster.
DinD is a K8s cluster running inside Docker containers, so Services expose ports to the containers' address, instead of the real host machine. We can find IP addresses of Docker containers by the following command:
$ kubectl get nodes -o yaml | grep address addresses: - address: 10.192.0.2 - address: kube-master addresses: - address: 10.192.0.3 - address: kube-node-1 addresses: - address: 10.192.0.4 - address: kube-node-2 addresses: - address: 10.192.0.5 - address: kube-node-3
Use the IP addresses for reverse proxy.
-
Set up a reverse proxy.
Either (or all) of the container IPs can be used as upstream for a reverse proxy. You can use any reverse proxy server that supports TCP (for TiDB) or HTTP (for Grafana and Prometheus) to provide remote access. HAProxy and NGINX are two common choices.
-
You can scale out or scale in the TiDB cluster simply by modifying the number of replicas
.
-
Edit the
charts/tidb-cluster/values.yaml
file with your preferred text editor.For example, to scale out the cluster, you can modify the number of TiKV
replicas
from 3 to 5, or the number of TiDBreplicas
from 2 to 3. -
Run the following command to apply the changes:
helm upgrade demo charts/tidb-cluster --namespace=tidb
Note: If you need to scale in TiKV, the consumed time depends on the volume of your existing data, because the data needs to be migrated safely.
Use kubectl get pod -n tidb
to verify the number of each compoments equal to values in the charts/tidb-cluster/values.yaml
file, and all pods are in Running
state.
-
Edit the
charts/tidb-cluster/values.yaml
file with your preferred text editor.For example, change the version of PD/TiKV/TiDB
image
tov3.0.1
. -
Run the following command to apply the changes:
helm upgrade demo charts/tidb-cluster --namespace=tidb
Use kubectl get pod -n tidb
to verify that all pods are in Running
state. Then you can connect to the database and use tidb_version()
function to verify the version:
MySQL [(none)]> select tidb_version();
*************************** 1. row ***************************
tidb_version(): Release Version: v3.0.1
Git Commit Hash: 06f3f63d5a87e7f0436c0618cf524fea7172eb93
Git Branch: HEAD
UTC Build Time: 2019-05-28 12:48:52
GoVersion: go version go1.12 linux/amd64
Race Enabled: false
TiKV Min Version: 2.1.0-alpha.1-ff3dd160846b7d1aed9079c389fc188f7f5ea13e
Check Table Before Drop: false
1 row in set (0.001 sec)
When you are done with your test, use the following command to destroy the TiDB cluster:
$ helm delete demo --purge
Note: This only deletes the running pods and other resources, the data is persisted.
If you do not need the data anymore, run the following commands to clean up the data. (Be careful, this permanently deletes the data).
$ kubectl get pv -l app.kubernetes.io/namespace=tidb -o name | xargs -I {} kubectl patch {} -p '{"spec":{"persistentVolumeReclaimPolicy":"Delete"}}'
$ kubectl delete pvc --namespace tidb --all
-
If you want to stop the DinD Kubernetes cluster, run the following command:
$ manifests/local-dind/dind-cluster-v1.12.sh stop
You can use
docker ps
to verify that there is no docker container running. -
If you want to restart the DinD Kubernetes after you stop it, run the following command:
$ manifests/local-dind/dind-cluster-v1.12.sh start
If you want to clean up the DinD Kubernetes cluster, run the following commands:
$ manifests/local-dind/dind-cluster-v1.12.sh clean
$ sudo rm -rf data/kube-node-*
Warning: You must clean the data after you destroy the DinD Kubernetes cluster, otherwise the TiDB cluster would fail to start when you try to bring a new cluster up again.