随着 kubernetes 的快速发展,很多应用都在往 kubernetes 上面迁移,现阶段对于无状态应用的迁移是非常容易做到的,但是对于有状态应用的迁移还是有一定门槛的,主要是有状态应用的运行方式各有不同,比如 MySQL、MongoDB、Redis 这些应用运行的方式方法都不太相同,特别是对于线上环境需要高可用的集群模式的时候,则差别就更大了,这就导致了有状态应用向 Kubernetes 的迁移必然进度会很慢。现在比较好的解决方案就是针对有状态应用开发对应的 Operator 应用,比如 prometheus-operator、etcd-operator 等等,关于 Operator 的开发,可以查看前面的一篇入门文章:Kubernetes Operator 快速入门教程 以了解更多信息。
同样的,对于 Elasticsearch 应用,现在官方也推出了基于 Kubernetes Operator 的应用:Elastic Cloud on Kubernetes (ECK),用户可使用该产品在 Kubernetes 上配置、管理和运行 Elasticsearch 集群。
ElasticCloudonKubernetes(ECK)
是一个 Elasticsearch Operator,但远不止于此。ECK 使用 Kubernetes Operator 模式构建而成,需要安装在您的 Kubernetes 集群内,其功能绝不仅限于简化 Kubernetes 上 Elasticsearch 和 Kibana 的部署工作这一项任务。ECK 专注于简化所有后期运行工作,例如:
ECK 不仅能自动完成所有运行和集群管理任务,还专注于简化在 Kubernetes 上使用 Elasticsearch 的完整体验。ECK 的愿景是为 Kubernetes 上的 Elastic 产品和解决方案提供 SaaS 般的体验。
在 ECK 上启动的所有 Elasticsearch 集群都默认受到保护,这意味着在最初创建的那一刻便已启用加密并受到默认强密码的保护。
从 6.8 和 7.1 版本开始,Elasticsearch 核心安全功能(TLS 加密、基于角色的访问控制,以及文件和原生身份验证)会免费提供。
通过 ECK 部署的所有集群都包括强大的基础(免费)级功能,例如可实现密集存储的冻结索引、Kibana Spaces、Canvas、Elastic Maps,等等。您甚至可以使用 Elastic Logs 和 Elastic Infrastructure 应用监测 Kubernetes 日志和基础设施。您可以获得在 Kubernetes 上使用 Elastic Stack 完整功能的体验。
ECK 内构建了 Elastic Local Volume,这是一个适用于 Kubernetes 的集成式存储驱动器。ECK 中还融入了很多最佳实践,例如在缩小规模之前对节点进行 drain 操作,在扩大规模的时候对分片进行再平衡,等等。从确保在配置变动过程中不会丢失数据,到确保在规模调整过程中实现零中断。
当然前提是你要有一个已经可运行的 kubernetes 集群(1.11版本以上),最好确保你的每个节点上至少有4GB内存可以使用,因为我们知道 Elasticsearch 是比较消耗资源的。
首先在集群中安装 ECK 对应的 Operator 资源对象:
$ kubectl apply -f https://download.elastic.co/downloads/eck/0.8.1/all-in-one.yaml
安装成功后,会自动创建一个 elastic-system 的 namespace 以及一个 operator 的 Pod:
$ kubectl get pods -n elastic-system
NAME READY STATUS RESTARTS AGE
elastic-operator-01/1Running115h
这个时候会安装上若干个 CRD 对象,当然这些 CRD 资源的控制器就在上面的 elastic-operator-0 这个 Pod 中:
$ kubectl get crd | grep elastic
apmservers.apm.k8s.elastic.co 2019-06-30T08:12:41Z
clusterlicenses.elasticsearch.k8s.elastic.co 2019-06-30T08:12:41Z
elasticsearches.elasticsearch.k8s.elastic.co 2019-06-30T08:12:41Z
enterpriselicenses.elasticsearch.k8s.elastic.co 2019-06-30T08:12:41Z
kibanas.kibana.k8s.elastic.co 2019-06-30T08:12:41Z
remoteclusters.elasticsearch.k8s.elastic.co 2019-06-30T08:12:41Z
trustrelationships.elasticsearch.k8s.elastic.co 2019-06-30T08:12:41Z
users.elasticsearch.k8s.elastic.co 2019-06-30T08:12:41Z
然后我们可以利用 CRD 对象来创建一个非常简单的单个 Elasticsearch 集群:(elastic.yaml)
apiVersion: elasticsearch.k8s.elastic.co/v1alpha1
kind: Elasticsearch
metadata:
name: elastic
namespace: elastic-system
spec:
version: 7.2.0
nodes:
- nodeCount: 1
config:
node.master: true
node.data: true
node.ingest: true
声明了要创建一个 7.2.0 版本的单节点的 Elasticsearch 资源对象:
$ kubectl create -f elastic.yaml
但是执行上面的命令会出现超时的情况:Errorfromserver(Timeout):errorwhencreating"STDIN":Timeout:request didnotcomplete within requested timeout30s
,创建不成功。这主要是因为 ECK 添加了一个 validation webhook 的 Admission,我们可以临时将这个对象删除:
# 先备份一下
$ kubectl getValidatingWebhookConfiguration-o yaml > ValidatingWebhookConfiguration.yaml
# 删除 ValdiationWebhook
$ kubectl deleteValidatingWebhookConfiguration validating-webhook-configuration
然后重新执行上面的创建命令即可成功。创建成功后需要等一小会儿待镜像拉取成功,然后就可以看到一个前缀为 elastic
的 Pod 运行成功:
$ get pods -n elastic-system
NAME READY STATUS RESTARTS AGE
elastic-es-h4xns977f5 1/1Running03h10m
elastic-operator-01/1Running115h
同样可以查看自定义的 Elasticsearch
这个 CRD 资源对象:
$ kubectl get elasticsearch -n elastic-system
NAME HEALTH NODES VERSION PHASE AGE
elastic green 17.2.0Operational3h10m
我们可以看到集群的相关信息。
同样,也可以用 CRD 对象 Kibana 来部署 kibana 应用:(kibana.yaml)
apiVersion: kibana.k8s.elastic.co/v1alpha1
kind: Kibana
metadata:
name: kibana
namespace: elastic-system
spec:
version: 7.2.0
nodeCount: 1
elasticsearchRef:
name: elastic
注意属性 spec.elasticsearchRef.name
的值为上面我们创建的 Elasticsearch 对象的 name:elastic
。直接添加这个资源对象即可:
$ kubectl create -f kibana.yaml
$ kubectl get pods -n elastic-system
NAME READY STATUS RESTARTS AGE
elastic-es-h4xns977f5 1/1Running03h15m
elastic-operator-01/1Running115h
kibana-kibana-79479c64bc-zpdr7 1/1Running0162m
$ kubectl get svc -n elastic-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elastic-es ClusterIP10.98.117.110<none>9200/TCP 3h17m
elastic-es-discovery ClusterIPNone<none>9300/TCP 3h17m
elastic-webhook-service ClusterIP10.106.65.101<none>443/TCP 15h
kibana-kibana ClusterIP10.107.3.36<none>5601/TCP 3h16m
最后我们可以去访问 kibana 来验证我们的集群,比如我们可以再添加一个 Ingress 对象:(ingress.yaml)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kibana
namespace: elastic-system
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: kibana.qikqiak.com
http:
paths:
- backend:
serviceName: kibana-kibana
servicePort: 5601
path: /
创建上面的 Ingress 对象:
$ kubectl create -f ingress.yaml
$ kubectl get ingress -n elastic-system
NAME HOSTS ADDRESS PORTS AGE
kibana kibana.qikqiak.com 8082m
将上面的域名做好 DNS 解析或者 hosts 映射。
然后我们需要获取访问 kibana 的用户名和密码,用户名默认是 elastic
,可以通过如下方式获取访问密码:
$ PASSWORD=$(kubectl get secret elastic-elastic-user -n elastic-system -o=jsonpath='{.data.elastic}'| base64 --decode)
$ echo $PASSWORD
...这是访问密码..
接下来在浏览器中打开上面的 kibana.qikqiak.com
地址,正常就会跳转到登录页面了:
使用上面的用户名和密码登录即可进入 kibana dashboard 页面:
上面我们部署的 Elasticsearch 集群是一个单节点的,我们可以直接修改 Elasticsearch 的资源清单文件来修改集群配置。ECK 会确保我们在现有集群上进行修改不会中断应用。
比如,我们将集群升级到2个节点,只需要设置 spec.nodes[0].nodeCount=2
即可:
apiVersion: elasticsearch.k8s.elastic.co/v1alpha1
kind: Elasticsearch
metadata:
name: elastic
namespace: elastic-system
spec:
version: 7.2.0
nodes:
- nodeCount: 2
config:
node.master: true
node.data: true
node.ingest: true
直接更新集群信息即可:
$ kubectl apply -f elastic.yaml
$ kubectl get pods -n elastic-system
NAME READY STATUS RESTARTS AGE
elastic-es-7pz8pv5ztj1/1Running07m56s
elastic-es-h4xns977f5 1/1Running03h36m
elastic-operator-01/1Running115h
kibana-kibana-79479c64bc-zpdr7 1/1Running03h3m
$ kubectl get elasticsearch -n elastic-system
NAME HEALTH NODES VERSION PHASE AGE
elastic green 27.2.0Operational3h37m
可以看到 elastic 这个 Elasticsearch 资源的状态是 green
,两个节点。
上面我们部署的集群默认是使用的 emptyDir volume
,我们知道 emptyDir
和 Pod 的生命周期是一致的,Pod 重建后数据肯定就没有了,在生产环境中肯定是不行的。
我们可以在集群中使用 PV/PVC 来进行持久化,同样,在上面的 Elasticsearch 资源对象中添加存储相关数据:
apiVersion: elasticsearch.k8s.elastic.co/v1alpha1
kind: Elasticsearch
metadata:
name: elastic
namespace: elastic-system
spec:
version: 7.2.0
nodes:
- nodeCount: 2
config:
node.master: true
node.data: true
node.ingest: true
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
#storageClassName: standard # 可以指定可用的storage class
为了能够获得磁盘的最佳性能,ECK 支持每个节点使用 local volume,关于在 ECK 中使用 local volume 的方法可以查看下面几篇资料:
关于定制 Elasticsearch 资源对象的一些方法,我们可以直接去查看 ECK 的 git 仓库中的介绍即可,当然我们也可以直接在集群中通过 describe
命令去获取 Elastisearch CRD 的资源声明:
$ kubectl describe crd elasticsearch
项目地址:https://github.com/elastic/cloud-on-k8s/
扫描下面的二维码关注我们的微信公众帐号,在微信公众帐号中回复 加群 即可加入到我们的 kubernetes 讨论群里面共同学习。
推荐阅读
kubernetes垃圾回收器GarbageCollector Controller源码分析(一)
kubernetes垃圾回收器Garbage Collector Controller源码分析(二)
Docker / Kubernetes 镜像源不可用,教你几招搞定它!
• end •
极客时间100门课程限时大减价,添加下面微信咨询+返现
上下滑动可查看更多哦
课程名称 | 拼团价 | 额外返现 | 到手价 |
---|---|---|---|
DDD实战课 | 55 | 15 | 40 |
Netty源码剖析与实战 | 99 | 19 | 80 |
DevOps实战笔记 | 68 | 19 | 49 |
说透中台 | 19 | 4 | 15 |
分布式技术原理与算法解析 | 68 | 19 | 49 |
Node.js开发实战 | 109 | 19 | 90 |
高并发系统设计40问 | 79 | 19 | 60 |
全栈工程师修炼指南 | 79 | 19 | 60 |
即时消息技术剖析与实战 | 55 | 13 | 42 |
研发效率破局之道 | 65 | 19 | 46 |
ZooKeeper实战与源码剖析 | 89 | 19 | 70 |
编译原理之美 | 65 | 19 | 46 |
Swift核心技术与实战 | 89 | 19 | 70 |
浏览器工作原理与实践 | 65 | 19 | 46 |
网络编程实战 | 65 | 19 | 46 |
消息队列高手课 | 65 | 19 | 46 |
TypeScript开发实战 | 89 | 19 | 70 |
从0打造音视频直播系统 | 65 | 19 | 46 |
Spring Boot与Kubernetes云原生微服务实践 | 89 | 31 | 58 |
Flutter核心技术与实战 | 65 | 19 | 46 |
黄勇的OKR实战笔记 | 65 | 19 | 46 |
Elasticsearch核心技术与实战 | 89 | 19 | 70 |
Linux实战技能100讲 | 89 | 19 | 70 |
SQL必知必会 | 65 | 19 | 46 |
Kafka核心技术与实战 | 65 | 19 | 46 |
透视HTTP协议 | 65 | 19 | 46 |
玩转webpack | 65 | 19 | 46 |
OpenResty从入门到实战 | 89 | 19 | 70 |
Java性能调优实战 | 65 | 19 | 46 |
零基础学Java | 89 | 19 | 70 |
深入拆解Tomcat & Jetty | 65 | 19 | 46 |
Python核心技术与实战 | 65 | 19 | 46 |
Web协议详解与抓包实战 | 89 | 19 | 70 |
深入浅出计算机组成原理 | 65 | 19 | 46 |
从0开发一款iOS App | 89 | 19 | 70 |
大规模数据处理实战 | 65 | 19 | 46 |
许式伟的架构课 | 89 | 19 | 70 |
从0开始做增长 | 65 | 19 | 46 |
趣谈Linux操作系统 | 65 | 19 | 46 |
Vue开发实战 | 89 | 19 | 70 |
iOS开发高手课 | 65 | 19 | 46 |
Go语言从入门到实战 | 89 | 19 | 70 |
Java并发编程实战 | 65 | 19 | 46 |
软件工程之美 | 65 | 19 | 46 |
玩转Spring全家桶 | 89 | 19 | 70 |
面试现场 | 55 | 13 | 42 |
重学前端 | 65 | 19 | 46 |
TensorFlow快速入门与实战 | 89 | 19 | 70 |
代码精进之路 | 65 | 19 | 46 |
10x程序员工作法 | 65 | 19 | 46 |
数据分析实战45讲 | 65 | 19 | 46 |
玩转Git三剑客 | 55 | 13 | 42 |
程序员的数学基础课 | 65 | 19 | 46 |
Android开发高手课 | 65 | 19 | 46 |
Linux性能优化实战 | 65 | 19 | 46 |
MySQL实战45讲 | 79 | 19 | 60 |
Nginx核心知识100讲 | 89 | 19 | 70 |
从0开始学大数据 | 65 | 19 | 46 |
白话法律42讲 | 65 | 19 | 46 |
算法面试通关40讲 | 89 | 19 | 70 |
数据结构与算法之美 | 65 | 19 | 46 |
深入剖析Kubernetes | 65 | 19 | 46 |
从0开始学微服务 | 55 | 13 | 42 |
技术管理实战36讲 | 65 | 19 | 46 |
Go语言核心36讲 | 65 | 19 | 46 |
程序员进阶攻略 | 65 | 19 | 46 |
邱岳的产品实战 | 65 | 19 | 46 |
深入拆解Java虚拟机 | 65 | 19 | 46 |
快速上手Kotlin开发 | 89 | 19 | 70 |
持续交付36讲 | 55 | 13 | 42 |
软件测试52讲 | 65 | 19 | 46 |
React实战进阶45讲 | 89 | 31 | 58 |
零基础学Python | 89 | 19 | 70 |
机器学习40讲 | 55 | 13 | 42 |
从0开始学游戏开发 | 55 | 13 | 42 |
趣谈网络协议 | 65 | 19 | 46 |
微服务架构实战160讲 | 189 | 46 | 143 |
Java核心技术36讲 | 65 | 19 | 46 |
从0开始学架构 | 65 | 19 | 46 |
硅谷产品实战36讲 | 55 | 13 | 42 |
技术领导力300讲 | 149 | 31 | 118 |
9小时搞定微信小程序开发 | 89 | 19 | 70 |
深入浅出区块链 | 55 | 13 | 42 |
推荐系统三十六式 | 55 | 13 | 42 |
赵成的运维体系管理课 | 55 | 13 | 42 |
人工智能基础课 | 55 | 13 | 42 |
邱岳的产品手记 | 65 | 19 | 46 |
朱赟的技术管理课 | 55 | 13 | 42 |
左耳听风 | 189 | 31 | 158 |
AI技术内参 | 79 | 19 | 60 |
技术与商业案例解读 | 79 | 19 | 60 |