install tidb
硬件配置
# 停止并禁用 firewalld 防火墙服务
systemctl stop firewalld
systemctl disable firewalld
# 设置 SELinux 为宽容模式
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# 禁用交换分区
swapoff -a
sed -i 's/^\(.*swap.*\)$/#\1/' /etc/fstab
# 加载网络桥接模块 br_netfilter
modprobe br_netfilter
# 创建并配置 Kubernetes 系统优化参数文件
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-arptables = 1
net.core.somaxconn = 32768
vm.swappiness = 0
net.ipv4.tcp_syncookies = 0
net.ipv4.ip_forward = 1
fs.file-max = 1000000
fs.inotify.max_user_watches = 1048576
fs.inotify.max_user_instances = 1024
net.ipv4.conf.all.rp_filter = 1
net.ipv4.neigh.default.gc_thresh1 = 80000
net.ipv4.neigh.default.gc_thresh2 = 90000
net.ipv4.neigh.default.gc_thresh3 = 100000
EOF
# 应用最新的系统配置
sysctl --system
# 启用并启动 irqbalance 服务,用于改善系统中断处理
systemctl enable irqbalance
systemctl start irqbalance
# 设置 CPU 性能模式为 "performance"
cpupower frequency-set --governor performance
# 设置系统文件打开数限制
cat <<EOF >> /etc/security/limits.conf
root soft nofile 1048576
root hard nofile 1048576
root soft stack 10240
EOF
# 再次应用最新的系统配置
sysctl --system
# 配置 Kubelet 的工作目录
echo "KUBELET_EXTRA_ARGS=--root-dir=/data1/kubelet" > /etc/sysconfig/kubelet
# 重启 Kubelet 服务以应用更改
systemctl restart kubelet
配置 Storage Class
这里使用本地 PV,官网推荐方法是使用挂载点方式来配置目录,相当于 TiDB OP 部署下,mount 目录。
服务器上没有多盘或者使用分区来挂盘,我们这里模拟挂载点:
# 创建必要的目录结构
mkdir -p /mnt/k8s-backup/subdir /k8s-backup/mount
mkdir -p /mnt/k8s-monitor/subdir /k8s-monitor/mount
mkdir -p /mnt/k8s-ssd/subdir /k8s-ssd/mount
mkdir -p /mnt/k8s-sharessd/subdir /k8s-sharessd/mount
mkdir -p /mnt/k8s-data/subdir /k8s-data/mount
mkdir -p /mnt/k8s-log/subdir /k8s-log/mount
# 等待文件系统更新
sleep 1
# 将挂载信息加入到 fstab 文件,确保重启后自动挂载
echo "/mnt/k8s-backup/subdir /k8s-backup/mount none bind 0 0" | sudo tee -a /etc/fstab
echo "/mnt/k8s-monitor/subdir /k8s-monitor/mount none bind 0 0" | sudo tee -a /etc/fstab
echo "/mnt/k8s-ssd/subdir /k8s-ssd/mount none bind 0 0" | sudo tee -a /etc/fstab
echo "/mnt/k8s-sharessd/subdir /k8s-sharessd/mount none bind 0 0" | sudo tee -a /etc/fstab
echo "/mnt/k8s-data/subdir /k8s-data/mount none bind 0 0" | sudo tee -a /etc/fstab
echo "/mnt/k8s-log/subdir /k8s-log/mount none bind 0 0" | sudo tee -a /etc/fstab
# 立即挂载所有配置
sudo mount -a
上面准备好之后,我们部署 local-volume-provisioner
local-volume-provisioner 的主要作用包括:
- 自动发现本地存储设备: 自动识别节点上的本地存储资源,如某个特定目录或分区。
- 创建 Persistent Volumes (PVs): 对于发现的每个本地存储设备,自动创建对应的 PV 对象。这样,用户就不需要手动为每个本地存储设备创建 PV。
- 监控和管理存储: 监控本地存储的状态,确保存储资源的健康和可用性。
部署 local-volume-provisioner
rm -rf local-volume-provisioner.yaml
wget https://raw.githubusercontent.com/pingcap/tidb-operator/v1.5.2/examples/local-pv/local-volume-provisioner.yaml
# 修改配置中的 configmap 里面的 storage 信息。
sed -i 's|/mnt/ssd|/k8s-ssd|g' local-volume-provisioner.yaml
sed -i 's|/mnt/sharedssd|/k8s-sharessd|g' local-volume-provisioner.yaml
sed -i 's|/mnt/monitoring|/k8s-monitor|g' local-volume-provisioner.yaml
sed -i 's|/mnt/backup|/k8s-backup|g' local-volume-provisioner.yaml
# 以上会给 tikv/pd/监控/备份使用
# 默认 pv 使用的 delete 模式管理,生产可以修改配置为 Retain
# 这里给 tidb 添加一个日志盘来做 data & 日志存储,添加以下内容:
# 所有 StorageClass 添加下:allowVolumeExpansion: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: "log-storage"
provisioner: "kubernetes.io/no-provisioner"
volumeBindingMode: "WaitForFirstConsumer"
allowVolumeExpansion: true
---
apiVersion: v1
kind: ConfigMap
... # 注意这里内容是省略的
log-storage:
hostDir: /k8s-log
mountDir: /k8s-log
---
apiVersion: apps/v1
kind: DaemonSet
... # 注意这里内容是省略的
volumeMounts:
... # 注意这里内容是省略的
- mountPath: /k8s-log
name: local-log
mountPropagation: "HostToContainer"
volumes:
... # 注意这里内容是省略的
- name: local-log
hostPath:
path: /k8s-log
locall-volume-provisioner 配置说明:
这个配置文件包含了多个 Kubernetes 资源定义,用于配置本地存储卷的供应,特别是对于没有自动卷供应能力的存储类(StorageClass)。配置内容涉及存储类定义、配置映射、守护进程集(DaemonSet)以及相关的服务账户和角色绑定。以下是关于这些资源及其功能的简洁说明:
存储类(StorageClass)
文件定义了四个存储类:
monitoring-storage
ssd-storage
shared-ssd-storage
backup-storage
这些存储类都使用 "kubernetes.io/no-provisioner"
作为供应器,这意味着它们不会自动供应存储。volumeBindingMode
设置为 "WaitForFirstConsumer"
,表示卷的绑定和动态供应将延迟到 Pod 引用它们为止。
配置映射(ConfigMap)
local-provisioner-config
是一个配置映射,为守护进程集提供配置。它包含了节点标签和存储类映射信息,指定了每个存储类对应的宿主目录 (hostDir
) 和挂载目录 (mountDir
)。
守护进程集(DaemonSet)
local-volume-provisioner
守护进程集用于部署一个运行在每个节点上的容器,这个容器负责将宿主机的目录供应为本地卷。它包括一些容器级的安全配置,并通过环境变量和挂载点配置来控制存储供应的行为。
服务账户和角色绑定
配置包括一个服务账户 local-storage-admin
和两个角色绑定,允许这个服务账户执行必要的 Kubernetes API 操作,如获取节点信息和管理持久卷。
核心修改配置项
- 存储路径修改:核心的修改项包括在 ConfigMap
的 storageClassMap
部分,将每个存储类的 hostDir
和 mountDir
修改为具体的路径,如 /k8s-ssd
等。
- 守护进程集的挂载点:在 DaemonSet
的容器配置中,volumeMounts
和 volumes
部分需要确保每个挂载点和宿主路径与 ConfigMap
中定义的路径相匹配。
这个配置整体上用于在不同的 Kubernetes 集群节点上提供特定的存储解决方案,支持没有动态供应能力的存储使用场景,适用于需要手动管理存储资源的环境。
应用
kubectl apply -f local-volume-provisioner.yaml
# 查看 volume 的管理 pod
kubectl get pod -n kube-system -l='app=local-volume-provisioner'
NAME READY STATUS RESTARTS AGE
local-volume-provisioner-49mzb 1/1 Running 0 4m38s
local-volume-provisioner-ffrjn 1/1 Running 0 4m38s
local-volume-provisioner-kvgtq 1/1 Running 0 4m38s
# 如果发现目录下无任何挂载点,则不会创建任何 PV,那么输出将为空。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
local-pv-20fa5bc3 196Gi RWO Delete Available monitoring-storage <unset> 97m
local-pv-2a2ee5a6 196Gi RWO Delete Available ssd-storage <unset> 97m
local-pv-73774db1 196Gi RWO Delete Available ssd-storage <unset> 97m
local-pv-74b8243d 196Gi RWO Delete Available shared-ssd-storage <unset> 99m
local-pv-771c997e 196Gi RWO Delete Available backup-storage <unset> 97m
local-pv-9d4c16f 196Gi RWO Delete Available ssd-storage <unset> 99m
local-pv-d3e9ec82 196Gi RWO Delete Available monitoring-storage <unset> 97m
local-pv-e8d37976 196Gi RWO Delete Available shared-ssd-storage <unset> 97m
local-pv-eda9391b 196Gi RWO Delete Available shared-ssd-storage <unset> 97m
local-pv-f0c19cfb 196Gi RWO Delete Available backup-storage <unset> 97m
local-pv-f1a2bef9 196Gi RWO Delete Available backup-storage <unset> 99m
local-pv-f72512e5 196Gi RWO Delete Available monitoring-storage <unset> 99m
注意 STORAGECLASS
,后续会使用。
以上,部署环境和盘已经都准备好了。
TiDB 安装
安装 helm
官网:https://helm.sh/docs/intro/install/
wget https://get.helm.sh/helm-v3.14.4-linux-amd64.tar.gz
tar -xzvf helm-v3.14.4-linux-amd64.tar.gz
install -m 755 linux-amd64/helm /usr/local/sbin/helm
CRD 安装
# 配置 helm repo
helm repo add pingcap https://charts.pingcap.org/
helm search repo pingcap
# 其他操作看官网 https://docs.pingcap.com/zh/tidb-in-kubernetes/stable/tidb-toolkit
# 创建 CRD
# Custom Resource Definition。CRD 允许你在 Kubernetes 集群中定义自定义资源
wget https://raw.githubusercontent.com/pingcap/tidb-operator/v1.5.2/manifests/crd.yaml
# 使用 apply 会有超长问题,yaml 太大了
kubectl create -f ./crd.yaml
kubectl get crd
operator 安装
# 查到 chart_version,例如:v1.5.2
helm search repo -l tidb-operator
export chart_version=v1.5.2
mkdir -p ${HOME}/tidb-operator && \
helm inspect values pingcap/tidb-operator --version=${chart_version} > ${HOME}/tidb-operator/values-tidb-operator.yaml
# 基本无需修改 values-tidb-operator.yaml,tidb-operator 相当于在线的 tiup,管理/检测 tidb-cluster 集群
# 推荐安装到 tidb-admin namespaces 下,可以看到对应 manager 的 pod,查看 pod 日志可以排查定位 tidb 集群管理上的问题
# !! TiDB Operator 默认会管理 Kubernetes 集群中的所有 TiDB 集群,如仅需其管理特定 namespace 下的集群,则可在 values.yaml 中设置 clusterScoped: false
# !! 新版本下,scheduler.create 推荐关闭,使用 default schedule 即可
sed -i -e '/scheduler:/,/create:/ s/create: true/create: false/' ${HOME}/tidb-operator/values-tidb-operator.yaml
# !! 修改 Timezone
sed -i 's/timezone: UTC/timezone: "Asia\/Shanghai"/g' values-tidb-operator.yaml
sed -i '/env: \[\]/c\
env:\n - name: TZ\n value: Asia/Shanghai\
' values-tidb-operator.yaml
kubectl create ns tidb-admin
helm install tidb-operator pingcap/tidb-operator --namespace=tidb-admin --version=${chart_version} -f ${HOME}/tidb-operator/values-tidb-operator.yaml && \
kubectl get po -n tidb-admin -l app.kubernetes.io/name=tidb-operator
# 查看是否 OK
kubectl get pod -n tidb-admin -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tidb-controller-manager-86bb89ddd-m5svk 1/1 Running 0 15s 10.244.1.10 vm172-16-201-193 <none> <none>
k8s 节点打标签
和 tikv 的 label 类似,服务器打标签,让各个组件优先调度到对应服务器
$ kubectl get nodes -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
vm172-16-201-18 Ready control-plane 19h v1.29.3 172.16.201.18 <none> CentOS Linux 7 (Core) 3.10.0-1160.102.1.el7.x86_64 containerd://1.6.31
vm172-16-201-193 Ready <none> 19h v1.29.3 172.16.201.193 <none> CentOS Linux 7 (Core) 3.10.0-1160.102.1.el7.x86_64 containerd://1.6.31
vm172-16-201-226 Ready <none> 19h v1.29.3 172.16.201.226 <none> CentOS Linux 7 (Core) 3.10.0-1160.102.1.el7.x86_64 containerd://1.6.31
kubectl label node vm172-16-201-18 node-role.kubernetes.io/pd=true
kubectl label node vm172-16-201-193 node-role.kubernetes.io/pd=true
kubectl label node vm172-16-201-226 node-role.kubernetes.io/pd=true
kubectl label node vm172-16-201-18 node-role.kubernetes.io/tikv=true
kubectl label node vm172-16-201-193 node-role.kubernetes.io/tikv=true
kubectl label node vm172-16-201-226 node-role.kubernetes.io/tikv=true
kubectl label node vm172-16-201-18 node-role.kubernetes.io/tidb=true
kubectl label node vm172-16-201-193 node-role.kubernetes.io/tidb=true
kubectl label node vm172-16-201-226 node-role.kubernetes.io/tidb=true
# 我们这里 3 个节点都运行各个组件进行调度
[root@vm172-16-201-18 tidb-operator]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
vm172-16-201-18 Ready control-plane,pd,tidb,tikv 19h v1.29.3
vm172-16-201-193 Ready pd,tidb,tikv 19h v1.29.3
vm172-16-201-226 Ready pd,tidb,tikv 19h v1.29.3
安装 tidb 集群
# get deploy yaml:https://github.com/pingcap/tidb-operator/blob/v1.5.2/examples/advanced/tidb-cluster.yaml,可以按照 operator 的版本你来选择模板
wget https://raw.githubusercontent.com/pingcap/tidb-operator/v1.5.2/examples/advanced/tidb-cluster.yaml
配置文件修改:
- name 集群名
- namespace 放在哪个 namespace
- version tidb 版本
- pvReclaimPolicy pv 策略,生产推荐 Retain,我们这里改为 delete
- requests 和 limit 下的 CPU 和 mem:cpu 里面 1000m = 1 vcore
- service 配置下,这里是对外服务 ip
- nodeSelector 打亲和,我们会对我们 k8s 打 label,然后这个配置相当于组件会往有这些 label 的节点去调度
- storageClassName 之前 pv 的 classname,我们这里有
monitoring-storage
ssd-storage
shared-ssd-storage
backup-storage
- dataSubDir pd/tikv/tiflash 的数据存储目录。默认是在 /var/lib/[pd tikv tiflash]. 配置这个之后,相当于在原来目录下,在创建一级目录,主要配合配置日志落盘使用的。这里配置为 "data"
- config 里面配置每个组件的各种配置
- spec.startScriptVersion: v2 ,新特性:诊断模式,使用 dig 命令替换 nslookup 命令来解析 DNS。
- tidb 特殊一些,我们配置 path = "/tidb/data" 和 storageVolums
完整配置,去掉注释:
grep -Ev "#|$^" tidb-cluster.yaml
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: tidb-wj
namespace: tidb
spec:
version: "v7.5.1"
timezone: UTC
startScriptVersion: v2
configUpdateStrategy: RollingUpdate
helper:
image: alpine:3.16.0
pvReclaimPolicy: Delete
enableDynamicConfiguration: true
pd:
baseImage: pingcap/pd
env:
- name: GRPC_DNS_RESOLVER
value: native
config: |
[dashboard]
internal-proxy = true
[log]
[log.file]
filename = "/var/lib/pd/log/pd.log"
max-days = 15
[replication]
location-labels = ["host"]
replicas: 3
maxFailoverCount: 0
requests:
cpu: 1000m
memory: 500Mi
storage: 196Gi
limits:
cpu: 1000m
memory: 1Gi
service:
type: NodePort
nodeSelector:
node-role.kubernetes.io/pd: "true"
mountClusterClientSecret: true
storageClassName: "shared-ssd-storage"
dataSubDir: "data"
tidb:
baseImage: pingcap/tidb
config: |
path = "/data/tidb"
[performance]
tcp-keep-alive = true
[log]
slow-query-file = "/data/tidb/log/tidb-slow.log"
[log.file]
filename = "/data/tidb/log/tidb.log"
max-backups = 15
replicas: 2
maxFailoverCount: 0
requests:
cpu: 1000m
memory: 1Gi
limits:
cpu: 1000m
memory: 1Gi
service:
type: NodePort
externalTrafficPolicy: Local
nodeSelector:
node-role.kubernetes.io/tidb: "true"
separateSlowLog: false
storageClassName: "tidb-storage"
storageVolumes:
- name: data
storageClassName: log-storage
storageSize: 196Gi
mountPath: "/data/tidb"
tikv:
baseImage: pingcap/tikv
env:
- name: GRPC_DNS_RESOLVER
value: native
config: |
log-level = "info"
[log.file]
filename = "/var/lib/tikv/log/tikv.log"
log-level = "info"
max-backups = 15
[resolved-ts]
enable = false
[storage]
reserve-space = "0MB"
[storage.block-cache]
capacity = "512MiB"
replicas: 3
maxFailoverCount: 0
requests:
cpu: 1000m
memory: 1Gi
storage: 196Gi
limits:
cpu: 2000m
memory: 2Gi
storage: 196Gi
nodeSelector:
node-role.kubernetes.io/tikv: "true"
mountClusterClientSecret: true
storageClassName: "ssd-storage"
dataSubDir: "data"
部署 tidb
# create ns
kubectl create ns tidb
kubectl apply -f tidb-cluster.yaml
kubectl get all,pvc -n tidb
部署完成后,可以去任何一个节点上(包含了 tidb/pd/tikv 的 POD 的) 查看目录使用情况:
tree /k8s-log/
/k8s-log/
└── mount
└── log
├── oom_record
└── tidb.log
3 directories, 1 file
[root@vm172-16-201-193 ~]# tree /k8s-log/ /k8s-sharessd/ /k8s-ssd/
/k8s-log/
└── mount
└── log
├── oom_record
└── tidb.log
/k8s-sharessd/
├── mount
│ ├── data
│ │ ├── hot-region
│ │ │ ├── 000001.log
│ │ │ ├── CURRENT
│ │ │ ├── LOCK
│ │ │ ├── LOG
│ │ │ └── MANIFEST-000000
│ │ ├── join
│ │ ├── member
│ │ │ ├── snap
│ │ │ │ └── db
│ │ │ └── wal
│ │ │ ├── 0000000000000000-0000000000000000.wal
│ │ │ └── 0.tmp
│ │ └── region-meta
│ │ ├── 000001.log
│ │ ├── CURRENT
│ │ ├── LOCK
│ │ ├── LOG
│ │ └── MANIFEST-000000
│ └── log
│ └── pd.log
└── subdir
/k8s-ssd/
├── mount
│ ├── data
│ │ ├── db
│ │ │ ├── 000005.log
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000004
│ │ │ ├── OPTIONS-000011
│ │ │ └── OPTIONS-000013
│ │ ├── import
│ │ ├── last_tikv.toml
│ │ ├── LOCK
│ │ ├── raftdb.info
│ │ ├── raft-engine
│ │ │ ├── 0000000000000001.raftlog
│ │ │ ├── 0000000000000001.rewrite
│ │ │ └── LOCK
│ │ ├── rocksdb.info
│ │ └── snap
│ └── log
│ └── tikv.log
└── subdir
20 directories, 31 files
这里部署 pd 和 tikv log 和 data 目录放置在同一级。
tidb-server 的日志放置对应 log-storage 挂载目录下
登录 TiDB
kubectl get all -n tidb
NAME READY STATUS RESTARTS AGE
pod/tidb-wj-discovery-5687bd8fc4-t45fk 1/1 Running 0 14m
pod/tidb-wj-pd-0 1/1 Running 0 14m
pod/tidb-wj-pd-1 1/1 Running 0 14m
pod/tidb-wj-pd-2 1/1 Running 0 14m
pod/tidb-wj-tidb-0 1/1 Running 0 14m
pod/tidb-wj-tidb-1 1/1 Running 0 14m
pod/tidb-wj-tikv-0 1/1 Running 0 14m
pod/tidb-wj-tikv-1 1/1 Running 0 14m
pod/tidb-wj-tikv-2 1/1 Running 0 14m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/tidb-wj-discovery ClusterIP 10.105.149.83 <none> 10261/TCP,10262/TCP 14m
service/tidb-wj-pd NodePort 10.102.173.121 <none> 2379:31166/TCP 14m
service/tidb-wj-pd-peer ClusterIP None <none> 2380/TCP,2379/TCP 14m
service/tidb-wj-tidb NodePort 10.102.58.180 <none> 4000:30321/TCP,10080:31912/TCP 14m
service/tidb-wj-tidb-peer ClusterIP None <none> 10080/TCP 14m
service/tidb-wj-tikv-peer ClusterIP None <none> 20160/TCP 14m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/tidb-wj-discovery 1/1 1 1 14m
NAME DESIRED CURRENT READY AGE
replicaset.apps/tidb-wj-discovery-5687bd8fc4 1 1 1 14m
NAME READY AGE
statefulset.apps/tidb-wj-pd 3/3 14m
statefulset.apps/tidb-wj-tidb 2/2 14m
statefulset.apps/tidb-wj-tikv 3/3 14m
可以看到 service 中 TiDB 的 cluster ip 为 10.102.58.180
所以登录方式为:
mysql -uroot -h10.102.58.180 -P4000 -p