头图

为什么选择 Kubernetes

容器是打包和运行应用程序的好方式。在生产环境中,我们需要管理运行应用程序的容器,并确保不会停机。如果一个容器发生故障,则需要启动另一个容器。如果系统处理此行为,会不会更便捷?这就是 Kubernetes(后文简称K8s) 的价值所在,它为你提供了一个可弹性运行分布式系统的框架。K8s 用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 同时,k8s 为你提供了自动部署和回滚、服务发现和负载均衡、存储编排、自我修复、密钥与配置管理等很多功能。即使有一些关于 k8s 复杂性的抱怨,我们仍然坚信它带来的益处远大于复杂性成本。

Kubernetes 如何维护应用状态

Kubernetes 在其早期阶段主要针对无状态应用程序(不管理自己的持久性数据的应用程序),这一特性直到 k8s 引入了 persistent volumes(持久卷)和 StatefulSet 后得到了提升。通常,当 Kubernetes 容器死亡时,它将被具有新标识(包括新IP地址和主机名)的新容器替换。但是,StatefulSet功能可确保每个 Pod 具有自己的稳定身份(可通过DNS解析),无论它被重启了多少次。这对 KaiwuDB 很有用,因为这意味着每次更换或重启 Pod 时,我们不必将其视为集群中的新节点,也避免了大量数据复制。这对于支持 KaiwuDB 的共识协议和分布式事务非常重要。作为云原生数据库, KaiwuDB 可以容忍丢失单个数据节点的数据丢失,它能检测到集群中缺失的副本,并自动添加新副本。出于降低延迟的考虑,我们推荐您使用本地磁盘作为存储,虽然远程存储允许副本在不丢失数据的情况下移动。

为什么在 Kubernetes 上使用 KaiwuDB

多数情况下,在 K8s 上部署、运维 KaiwuDB 比在物理机或虚拟机上更方便。这主要因为 KaiwuDB 是单个可执行文件,可通过每个节点提供到数据库的通用网关。每个节点都是全对等的,唯一的区别是该节点管理的是哪部分数据。当遇到间歇性故障或进行滚动升级时, K8s 助力于数据库集群的快速恢复。尽管 K8s 带来许多诸多的便利,我们仍然要权衡 k8s 带给我们的弹性与通过物理机或虚拟机获得更高性能的利弊。即使在物理机或虚拟机上维护数据库需要更多的人工操作,但获得的最佳性能比 k8s 上要好。

KaiwuDB 如何运行在 Kubernetes 上

一、创建数据库集群
1.如果您没有使用网络存储而是本地存储卷时,需要创建3个 persistent volumes(持久卷)来提供给 pod 使用:

$ kubectl apply -f pv0.yaml -f pv1.yaml -f pv2.yaml

可参考以下的持久卷(pv)yaml文件:

apiVersion: v1
kind: PersistentVolume
metadata:
 name: pv-bini-0
 labels:
   app: bini
spec:
 capacity:
   storage: 10Gi
 volumeMode: Filesystem
 accessModes:
 - ReadWriteOnce
 storageClassName: local
 persistentVolumeReclaimPolicy: Retain
 local:
   path: /home/inspur/pv/pv0
 nodeAffinity:
   required:
     nodeSelectorTerms:
     - matchExpressions:
       - key: kubernetes.io/hostname
         operator: In
         values: ['slave1']

2.在准备好 Kubernetes 的环境后,您可以使用 yaml 文件去创建 StatefulSet 来创建数据库集群:

$ kubectl create -f bini-statefulset.yaml
service/bini-public created
service/bini created
poddisruptionbudget.policy/bini-budget created
statefulset.apps/bini created

3.由于我们还未初始化集群,三个 Pods 处于 running 状态:

$ kubectl get pods
NAME     READY     STATUS    RESTARTS   AGE
bini-0   0/1       Running   0          1m
bini-1   0/1       Running   0          1m
bini-2   0/1       Running   0          1m

4.查看本地持久卷声明与本地持久卷已经成功绑定:

$ kubectl get persistentvolumeclaims
NAME             STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
datadir-bini-0   Bound    pv-bini-1   1Gi        RWO            local          2m
datadir-bini-1   Bound    pv-bini-0   1Gi        RWO            local          2m
datadir-bini-2   Bound    pv-bini-2   1Gi        RWO            local          2m

5.创建集群初始化的 yaml 文件:

$ kubectl create -f cluster-init.yaml
job.batch/cluster-init created

6.用于初始化的 job 将很快处于 completed 状态:

$ kubectl get job cluster-init
NAME           COMPLETIONS   DURATION   AGE
cluster-init   1/1           10s        30s

数据库节点的三个 pods 也将处于 running 状态:

$ kubectl get pods
NAME                 READY   STATUS      RESTARTS   AGE
cluster-init-bw928   0/1     Completed   0          50s
bini-0               1/1     Running     0          3m23s
bini-1               1/1     Running     0          3m23s
bini-2               1/1     Running     0          3m23s

二、使用内置的 SQL 客户端:1.启动一个临时的交互式 pod 并启动其中的内置 SQL 客户端:

$ kubectl run bini -it \
--image=bini:release2.0 \
--rm \
--restart=Never \
-- sql \
--insecure \
--host=bini-public

2.运行一些 SQL 语句:

root@bini-public:26257/defaultdb> create database bank;
root@bini-public:26257/defaultdb> create database bank;
root@bini-public:26257/defaultdb> create table bank.accounts (
name varchar(255),
balance decimal
);
root@bini-public:26257/defaultdb> insert into bank.accounts values ('Andy',100),('Bob',200),('Chris',300);
root@bini-public:26257/defaultdb> select * from bank.accounts;
 name  | balance  
+-------+---------+
 Andy  |     100  
 Bob   |     200  
 Chris |     300  
(3 rows)

3.退出 SQL shell 后这个 pod 也随之删除

root@bini-public:26257/defaultdb> \q

三、通过 Admin UI 查看集群状态

方法一:为 Service 设置NodePort
使用 Service 中的 NodePort,将 Admin UI 的端口映射到本地机器的一个端口上,采用 localhost + NodePort 的方式访问。

方法二:使用端口转发的方式手动将 K8s 中的 Service 转发到本地机器的一个端口上

$ kubectl port-forward service/bini-public --address 0.0.0.0 8080:8080
Forwarding from 0.0.0.0:8080 -> 8080

管理集群

一、增加节点

$ kubectl scale statefulset bini --replicas=4
statefulset.apps/bini scaled

在配置好新的本地持久存储卷后,将看到第4个 pod 成功加入集群:

NAME                 READY   STATUS      RESTARTS   AGE
cluster-init-bw928   0/1     Completed   0          1m39s
bini-0               1/1     Running     0          4m12s
bini-1               1/1     Running     0          4m12s
bini-2               1/1     Running     0          4m12s
bini-3               1/1     Running     0          30s

二、移除节点

1.启动一个临时的交互式pod,并使用bini node status命令获取数据库节点的内部ID:

$ kubectl run bini -it \
--image=bini/release2.0 \
--rm \
--restart=Never \
-- node status \
--insecure \
--host=bini-public
 id |                   address                   |  build  |         started_at         |         updated_at         | is_available | is_live  
+----+---------------------------------------------+---------+----------------------------+----------------------------+--------------+---------+
  1 | bini-0.bini.default.svc.cluster.local:26257 | ff04cdd | 2021-02-04 09:34:47.053657 | 2021-02-05 02:45:31.756302 | true         | true    
  2 | bini-2.bini.default.svc.cluster.local:26257 | ff04cdd | 2021-02-04 09:34:47.814316 | 2021-02-05 02:45:32.464036 | true         | true    
  3 | bini-1.bini.default.svc.cluster.local:26257 | ff04cdd | 2021-02-04 09:34:47.077002 | 2021-02-05 02:45:31.756099 | true         | true    
  4 | bini-3.bini.default.svc.cluster.local:26257 | ff04cdd | 2021-02-05 02:01:14.868258 | 2021-02-05 02:45:29.947311 | true         | true    
(4 rows)

2.注意地址中编号最高的节点的ID(也就是上一步中包含bini-3的地址),并使用bini node decommission命令对其进行停用:

kubectl run bini -it \
--image=bini:release2.0 \
--rm \
--restart=Never \
-- node decommission <node ID> \
--insecure \
--host=bini-public

接下来,您将看到退役节点的状态:

id | is_live | replicas | is_decommissioning | is_draining  
+---+---------+----------+--------------------+-------------+
 4 |  true   |       28 |        true        |    false
节点完全停止运行后,您将看到以下信息:

id | is_live | replicas | is_decommissioning | is_draining  
+---+---------+----------+--------------------+-------------+
 4 |  true   |        0 |        true        |    false    
(1 row)
No more data reported on target nodes. Please verify cluster health before removing the nodes.

3.从 StatefulSet 中移除一个节点:

$ kubectl scale statefulset bini --replicas=3
statefulset "bini" scaled

三、滚动升级

$ kubectl patch statefulset bini -p '{"spec":{"template":{"spec":{"containers":[{"name":"bini","image":"bini:release2.0"}]}}}}'

四、删除集群

删除创建的所有资源

$ kubectl delete pods,statefulsets,services,persistentvolumeclaims,persistentvolumes,poddisruptionbudget,jobs -l app=bini
pod "bini-0" deleted
pod "bini-1" deleted
pod "bini-2" deleted
pod "bini-3" deleted
service "bini" deleted
service "bini-public" deleted
persistentvolumeclaim "datadir-bini-0" deleted
persistentvolumeclaim "datadir-bini-1" deleted
persistentvolumeclaim "datadir-bini-2" deleted
persistentvolumeclaim "datadir-bini-3" deleted
poddisruptionbudget "bini-budget" deleted
job "cluster-init" deleted

KaiwuDB
15 声望1 粉丝

KaiwuDB 是浪潮控股的数据库企业,公司汇聚了全球顶尖的数据库人才,以 AIoT 数据库为核心产品,面向工业物联网、数字能源、交通车联网、智慧产业等各大行业领域,提供领先创新的数据服务软件。