今天用这篇文章带你们在本身的电脑上搭建一个Kubernetes Etcd集群,Kubernetes自己的功能就依赖Etcd实现,不过并不会开放给咱们的程序使用,因此须要本身单独搭建。html
Etcd如今是分布式服务架构中的重要组件,它由 CNCF 孵化托管, 在微服务和 Kubernates 集群中不只能够做为服务注册与发现,仍是一个用于配置共享的分布式键值存储,采用 raft 算法,实现分布式系统数据的可用性和一致性。node
通常用Go语言开发的gRPC服务会使用Etcd实现服务发现和注册。此外一些重要的配置也会存储在Etcd里经过让程序监听Key的变动来实现无需重启应用的配置更新。git
关于为何要使用Etcd咱们不作过多介绍,如今切入正题。安装Etcd的方式比较多,若是想直接把Etcd集群安装在机器上而不是Kubernetes里能够经过 goreman
工具。不过由于我电脑上安装了Minikube,因此想尽可能把全部东西都运行在Kubernetes里这样将来换电脑也就不用发愁须要安装那么多工具集了。除了演示在Kubernetes里安装运行Etcd集群外,还会安装一个Etcd的Web UI服务,让咱们可以经过浏览器查询和设置Etcd的Key-Value,这个Etcd Web UI服务一样是运行在Kubernetes里,相信经过今天文章的学习你也必定感觉到Kubernetes的便捷和学到很多知识。github
在开始跟着文章里的步骤安装Etcd前,须要先确保本身的电脑里安装了Minikube 这个单节点Kubernetes集群。我之前的文章里有详细介绍过安装步骤,我把他放在这里供你们参考。算法
Minikube-运行在笔记本上的Kubernetes集群docker
在Kubernetes里安装Etcd的方法有两种,一种是原始的经过StatefulSet控制器,也就是有状态应用来编排Etcd的节点,这种须要配置Pod使用的镜像,配置文件和启动命令。经过无头服务,在集群内部为Pod提供名称到IP的映射,以及NodePort类型的服务向集群外暴露客户端端口。还有一种是使用coreos提供Etcd Operator直接安装,不少细节都为咱们直接处理好了。shell
在这里咱们使用第一种用StatefulSet建立Etcd节点和Service对外暴露客户端端口的安装方式。api
首先咱们来建立为Etcd集群的Pod提供Pod名称到IP映射的无头服务。浏览器
---
apiVersion: v1
kind: Service
metadata:
name: etcd
namespace: etcd
annotations:
# Create endpoints also if the related pod isn't ready
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
ports:
- port: 2379
name: client
- port: 2380
name: peer
clusterIP: None
selector:
component: etcd
复制代码
这里要建立的无头服务的名称是 etcd 。由于StatefulSet编排的Pod名称永远是PodName-序号,到时候集群内部各个Etcd节点配置的通讯方式就能够用 "PodName-序号.etcd:2380" 这种形式来代替使用"节点IP:2380"。bash
2380是Etcd服务端的端口,而对外提供服务的客户端端口是2379,所以还须要有一个NodePort类型的Service向集群外部暴露客户端对2379端口的访问。
---
apiVersion: v1
kind: Service
metadata:
name: etcd-client
namespace: etcd
spec:
ports:
- name: http
nodePort: 30453
port: 2379
targetPort: 2379
protocol: TCP
type: NodePort
selector:
component: etcd
复制代码
建立这两个Service: kubectl apply -f resources/services.yml -n etcd
关于Kubernetes Service 和 StatefulSet 的做用原理、各类配置的详细解释能够参考我公众号里之前的文章:
深刻理解StatefulSet,用Kubernetes编排有状态应用
咱们经过StatefulSet编排建立3个Etcd节点的Pod,建立出来后上面的那两个Service会根据Pod的标签component=etcd
找到它们,把节点加入到本身的服务端点列表中。
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: etcd
labels:
component: etcd
spec:
serviceName: etcd
replicas: 3
selector:
matchLabels:
component: etcd
template:
metadata:
name: etcd
labels:
component: etcd
spec:
volumes:
- name: etcd-storage
emptyDir: {}
containers:
- name: etcd
image: quay.io/coreos/etcd:latest
ports:
- containerPort: 2379
name: client
- containerPort: 2380
name: peer
volumeMounts:
- name: etcd-storage
mountPath: /var/run/etcd/default.etcd
复制代码
Pod的启动命令里要配置上每一个节点点的IP和端口,上面说了无头服务的配置能够经过PodName-序号.etcd 的方式解析出IP,这里对应的就是:
etcd-0.etcd
etcd-1.etcd
etcd-2.etcd
复制代码
不过为了灵活性,我参考了国外一位网友分享的方式经过启动时执行shell脚本的方式,动态根据Etcd集群节点数量来设置启动命令里的 PeersUrl等配置
env:
- name: CLUSTER_SIZE
value: "3"
- name: SET_NAME
value: "etcd"
- name: MINIKUBE_IP
value: "$MINIKUBE_IP"
- name: MINIKUBE_PORT
value: "$MINIKUBE_PORT"
command:
- /bin/sh
- -ecx
- | IP=$(hostname -i) PEERS="" for i in $(seq 0 $((${CLUSTER_SIZE} - 1))); do PEERS="${PEERS}${PEERS:+,}${SET_NAME}-${i}=http://${SET_NAME}-${i}.${SET_NAME}:2380" done exec etcd --name ${HOSTNAME} \ --listen-peer-urls http://${IP}:2380 \ --listen-client-urls http://${IP}:2379,http://127.0.0.1:2379 \ --advertise-client-urls http://${HOSTNAME}.${SET_NAME}:2379,http://${MINIKUBE_IP}:${MINIKUBE_PORT} \ --initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \ --initial-cluster-token etcd-cluster-1 \ --initial-cluster ${PEERS} \ --initial-cluster-state new \ --data-dir /var/run/etcd/default.etcd 复制代码
StatefulSet的建立命令为:
cat resources/etcd.yml.tmpl | resources/config.bash | kubectl apply -n etcd -f - 复制代码
提供了一个shell脚原本设置 MINIKUBE_PORT 这两个在容器里没法得到的环境变量。
建立Etcd集群所使用的 yaml 资源声明文件和具体的操做步骤都已经放到了Github上,你们能够按照里面的命令进行操做。连接地址:github.com/kevinyan815…
测试安装是否成功也简单,观测Pod在Kubernetes里都正常启动起来后咱们往Etcd里 set 一个键值,看能不能再查询出来就好了。
接下来咱们在说说怎么给Etcd作个Web UI,毕竟一些为应用程序预准备的配置若是要用命令行一条条 set 进去的话也太麻烦了。
作这个Web UI,说来话长,花的时间比上面搭建Etcd集群多多了,大概花了两三天反复尝试才搞定。
Web UI我使用了 e3w 这个项目
本来这个项目是有提供docker镜像和docker-compose容器编排运行的,不过我实在不想再在我电脑上安装这么多工具集了就一直想把它改形成能在 Kubernetes 里运行的方式。
看了下这个项目的源码,启动的时候会去读取 /app/conf
目录下的config.default.ini
配置文件,WebUI服务的端口号默认配置的是8080,有了这两个信息后咱们就能够经过Deployment建立Pod来放置Web UI服务,经过Service暴露Web UI服务供集群外部访问的端口了。
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: e3w-deployment
namespace: etcd
labels:
app: e3w
spec:
replicas: 1
selector:
matchLabels:
app: etcd-client-e3w
template:
metadata:
labels:
app: etcd-client-e3w
spec:
containers:
- name: e3w-app-container
image: soyking/e3w:latest
ports:
- name: e3w-server-port
containerPort: 8080
---
kind: Service
apiVersion: v1
metadata:
name: e3w-service
namespace: etcd
spec:
type: NodePort
selector:
app: etcd-client-e3w
ports:
- protocol: TCP
targetPort: e3w-server-port
nodePort: 30081
port: 80
复制代码
至于配置文件,个人设想是把配置放到ConfigMap里,再把ConfigMap里的配置项做为文件挂载在原来配置文件的路径上。这样作的好处有两个:
下面 ConfigMap 里的 e3w-config.default.ini 就是咱们要做为文件挂载到容器里的配置项。
apiVersion: v1
kind: ConfigMap
metadata:
name: e3w-configmap
namespace: etcd
labels:
config: e3w.ini
data:
e3w-config.default.ini: | [app] port=8080 auth=false [etcd] root_key=root dir_value= addr=etcd-0.etcd.etcd.svc.cluster.local:2379,etcd-1.etcd.etcd.svc.cluster.local:2379,etcd-2.etcd.etcd.svc.cluster.local:2379 username= password= cert_file= key_file= ca_file= 复制代码
不过,在这一步上实属费了很多时间,主要是把 ConfigMap 的一个配置项做为文件挂载到容器里除了须要在 volumeMounts.MountPath 上配置完整的目录和文件名外还须要用上 subPath 这个配置。
spec:
containers:
volumeMounts:
- name: e3w-configmap-volume
mountPath: /app/conf/config.default.ini
subPath: config.default.ini
volumes:
- name: e3w-configmap-volume
configMap:
name: e3w-configmap
items:
- key: e3w-config.default.ini
path: config.default.ini
复制代码
这又是一个小知识点,关于Volume挂载时 subPath 的应用场景等后面再说(你们想听的话下篇就安排,记得点赞啊)。
配置文件搞定后,再看一下Pod运行的状态,就再也不是Error了。
上面建立的Etcd集群里的三个基点和e3w的WebUI服务都能正常运行。
经过WebUI咱们能够查看Etcd集群的运行状态
以及更方便地经过UI界面管理Key-Value:
总体上感受这个Web UI服务体验上还不错,不少功能都有。
Etcd Web UI服务的 yaml 定义文件我也放到了GitHub上,连接地址:github.com/kevinyan815…
今天的文章,感受前面安装Etcd集群的内容没有什么新鲜的知识,都是之前讲过的知识点的实际应用。在介绍安装Etcd Web UI服务时却是用到了两个新的知识点,咱们经过将 configMap 的某一个配置项做为配置文件挂载到容器里的方式既避免了修改 e3w 项目源代代码从新打Docker镜像,也避免了在宿主机上单独管理配置文件的麻烦。