一、缘由
ES集群上K8s,主要解决横向扩展复杂的问题,次要可以节约一定的成本。
通过更改StatefulSet的副本数,可以有序横向扩展ES集群,并通过集群自动平衡数据的方法,将数据迁移到新加入的节点。
二、预备环境
阿里云ASK集群:版本1.22.15-aliyun.1
ES集群:版本 elasticsearch:6.3.2
存储:阿里云SSD云盘
三、架构
部署在阿里云ASK集群的statefulset,不存在资源竞争
方案1(正常方案):master节点3个,data节点N个。
方案2(简单粗暴):初始3个节点,所有节点都是master节点和node节点;后续扩容不用在意discovery,保持master是初期节点即可。(本例采用)
四、部署步骤
1、全部所需yaml文件预览
create-ns.yaml # 命名空间
mhw-es-headless-svc.yaml # 通过headless-svc配置es集群域名
mhw-storage-class.yaml # 动态存储卷
mhw-es-statefulset.yaml # 有状态应用ES
mhw-es-svc.yaml # LoadBalance类型的svc,作为集群入口
mhw-kibana.yaml # kibana
2、创建elasticsearch命名空间
新建create-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: elasticsearch
labels:
name: elasticsearch
说明:创建专属的namespace和业务应用网络隔离,资源隔离。
3、创建headless类型的svc
新建mhw-es-headless-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: mhw-es-svc
namespace: elasticsearch
spec:
selector:
app: mhw-es
clusterIP: None
ports:
- name: rest # 节点与外部通信端口
port: 9200
- name: inter-node # 节点内部通信端口
port: 9300
说明:有状态应用通过headless-svc所确定的域名来相互通信。
4、创建动态存储卷storageclass
新建mhw-storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: alicloud-disk-ssd-es
provisioner: diskplugin.csi.alibabacloud.com
parameters:
type: cloud_ssd
fstype: ext4
resourceGroupId: "rg-aek2q6kagvjz2zq"
volumeBindingMode: Immediate # 立即绑定,非延迟绑定
reclaimPolicy: Delete # 保留策略,不保留,删除pvc的时候删除云盘
allowVolumeExpansion: false # 是否动态扩展
说明:数据存储采用云盘,云盘可以选择类型和IOPS,就是按量付费可能略贵。具体参数见文档:[使用阿里云云盘动态存储卷](使用云盘动态存储卷 (aliyun.com))
5、创建有状态应用ES
新建mhw-es-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mhw-es-cluster # statefuleSet的名称
namespace: elasticsearch # 所属命名空间
spec:
serviceName: mhw-es-svc # headless-svc的名称
selector:
matchLabels:
app: mhw-es
replicas: 3 # 3个节点
template:
metadata:
labels:
app: mhw-es # es容器标签
annotations:
k8s.aliyun.com/eci-use-specs : "2-8Gi" # 实例配置
spec:
containers:
- name: mhw-es # es容器名称
image: registry-vpc.cn-beijing.aliyuncs.com/zuhaowan-tools/elasticsearch:6.3.2
resources: # 分配的资源
requests:
cpu: 2
memory: 8Gi
limits:
cpu: 2
memory: 8Gi
livenessProbe:
tcpSocket:
port: 9200
initialDelaySeconds: 40
timeoutSeconds: 5
periodSeconds: 5
ports:
- containerPort: 9200
name: rest
protocol: TCP
- name: inter-node
containerPort: 9300
protocol: TCP
volumeMounts: # 数据卷挂载
- name: data
mountPath: /usr/share/elasticsearch/data
env:
- name: TZ # 时区设置
value: Asia/Shanghai
- name: cluster.name # ES集群名称
value: mhw-cluster
- name: node.name # ES节点名称,来自有状态应用自身名字
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: discovery.zen.ping.unicast.hosts # 自动发现种子节点列表,用于后期选主节点
value: "mhw-es-cluster-0.mhw-es-svc,mhw-es-cluster-1.mhw-es-svc,mhw-es-cluster-2.mhw-es-svc"
- name: discovery.zen.minimum_master_nodes # 防止脑裂的配置
value: "2"
- name: ES_JAVA_OPTS # Java堆内存
value: "-Xms4g -Xmx4g"
- name: network.host
value: "0.0.0.0"
- name: http.cors.allow-origin
value: "*"
- name: http.cors.enabled
value: "true"
- name: http.max_initial_line_length
value: "8k"
- name: http.max_header_size
value: "16k"
- name: bootstrap.memory_lock # 内存锁定
value: "false"
initContainers: # init容器解决es数据目录权限问题
- name: fix-permissions
image: busybox
command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
volumeMounts: # es数据目录挂载路径
- name: data
mountPath: /usr/share/elasticsearch/data
volumeClaimTemplates: # PVC模版,使用storageclass动态创建pv
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ] # 单节点读写
storageClassName: alicloud-disk-ssd-es
resources:
requests:
storage: 50Gi # 创建云盘的大小
说明:
ES6集群不需要配置集群初始化时引导选择主节点的配置,所以这个配置cluster.initial_master_nodes 可以不写。
这个集群三个节点默认都是master和data节点。
discovery.zen.ping.unicast.hosts 只在最开始配置三个节点即可,后续节点不用再添加进来,永远使用这三个选一个当主节点的意思。
注意指定时区
6、创建ES集群入口SLB
创建mhw-es-svc.yaml
apiVersion: v1
kind: Service
metadata:
annotations: # 创建按量付费的SLB
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-connect-port: '9200'
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-flag: 'on'
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-interval: '3'
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-type: tcp
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-healthy-threshold: '4'
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-scheduler: wlc
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-instance-charge-type: "PayByCLCU"
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-unhealthy-threshold: '4'
service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-name: "mhw-es"
name: mhw-es-svc-slb
namespace: elasticsearch
spec:
ports:
- name: http
port: 9200
protocol: TCP
targetPort: 9200
selector:
app: mhw-es
type: LoadBalancer
说明:因为本实例中ES集群和业务应用分属于不同namespace,网络隔离了,通过headless-svc名称无法访问通。所以需要一个集群外的访问入口,这里使用私网SLB。
7、创建Kibana
创建mhw-kibana.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mhw-kibana-deployment
namespace: elasticsearch
labels:
app: mhw-kibana
spec:
minReadySeconds: 15
replicas: 1
selector:
matchLabels:
app: mhw-kibana
template:
metadata:
labels:
app: mhw-kibana
annotations:
k8s.aliyun.com/eci-use-specs : "1-2Gi"
spec:
terminationGracePeriodSeconds: 40
containers:
- name: mhw-kibana
image: registry-vpc.cn-beijing.aliyuncs.com/zuhaowan-tools/kibana:6.3.2
ports:
- containerPort: 5601
resources:
requests:
cpu: 1
memory: 2Gi
limits:
cpu: 1
memory: 2Gi
livenessProbe:
tcpSocket:
port: 5601
initialDelaySeconds: 40
timeoutSeconds: 5
periodSeconds: 5
env:
- name: TZ # 时区
value: "Asia/Shanghai"
- name: ELASTICSEARCH_URL # ES集群的地址
value: "http://mhw-es-svc:9200"
- name: XPACK.MONITORING.UI.CONTAINER.ELASTICSEARCH.ENABLED # 关闭x-pack
value: "false"
- name: I18N.DEFAULTLOCALE # 本地化
value: "zh-CN"
imagePullSecrets:
- name: zhw-user-secret
说明:
注意连接ES集群地址的变量配置即可,ES6和ES7可能不一样。
可以直接使用容器IP或者创建nodeport和loadblance类型的svc来访问kibana。
本例是部署在ASK集群,集群内网是打通的,故直接使用容器IP访问Kibana。
五、遇到的问题
1、交换分区memory_lock问题
在ES的配置文件中,官方建议不使用交换分区(使用交换分区会使ES性能急剧下降),将bootstrap.memory_lock设置为true,或者最本质方法彻底禁用交换内存。
在本例中,ASK集群的底层是ECI主机,默认交换分区是禁用的(阿里云ECS交换分区默认也是禁用的)。故可以在配置文件中将bootstrap.memory_lock设置为false。
2、缩容PVC释放问题
缩容的时候PVC默认是保留的,同样对应的PV和云盘都是保留的。
上面storageclass设置的PVC删除的时候PV和云盘是同时删除的。
基于以上,如果确认不再使用对应的PVC(存储),需要手动删除,云盘会立刻释放。
3、版本问题
以上是基于ES6部署的配置文件,如果是ES7或者ES8集群,可能会有所差别。
以上是基于阿里云ASK集群,如果是阿里云ACK集群(普通K8s集群),yaml文件可能有差别。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 lxwno.1@163.com