今天用這篇文章帶你們在本身的電腦上搭建一個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鏡像,也避免了在宿主機上單獨管理配置文件的麻煩。