一個網站的微服務架構實戰(2)k8s遷移
前言
我們一起回顧上一篇文章《Bees平臺的微服務架構(1)docker和docker-compose》,一共通過Dockerfile構建了三個docker映象:mysql資料庫,部署angular前端頁面的nginx,和springboot介面。然後使用docker-compose來做容器服務的編排,以保障不同容器之間可以互訪。為了提高開發的效率,我們還寫了一個自動部署的指令碼,實際是隻是通過docker-compose.yml啟動和關閉容器,在本地映象庫中生成或刪除映象。
不可否認,docker-compose服務編排的小巧靈活性讓人愛不釋手,那我們今天為什麼要遷移到k8s(kubernetes)上呢?因為k8s的編排能力更強,因為k8s可以做跨主機的分散式叢集,因為k8s搭載rancher將更有利於微服務架構的統一管理,等等。
k8s準備
本文將不講解k8s和rancher的安裝和配置,相關的安裝文件和配置文件網上有很多。最近阿里雲產品春節大促銷,我一時沒忍住又買了一臺伺服器,打完折扣還是很貴。心疼歸心疼,不過這樣我就有兩臺伺服器了,就順便搭建了k8s的叢集環境。
映象倉庫
分散式叢集帶來的複雜度就增加了。你沒辦法直接使用本地的映象庫地址了,我不想搭建映象倉庫,好在阿里的docker映象倉庫是免費的,就將最終版的docker映象推送到阿里的容器倉庫裡面。當需要啟動容器時,容器的地址就寫阿里容器倉庫裡的地址,後文中會出現。
宿主機掛載卷
分散式的另一個問題就是宿主機的掛載卷,如果對上一篇文章印象深刻的話,應該記得mysql資料庫的資料檔案和nginx代理的圖片檔案等,都是掛載在宿主機上的。因為docker容器的特性,如果不使用掛載卷,在重啟容器之後容器內的資料都會丟失。分散式環境中,不同主機之間是沒辦法互訪目錄的。我是通過在一臺機器上搭建了nfs伺服器,將單臺機器上的目錄開放為共享目錄,具體內容下文有介紹。
服務互訪
不同服務之間免不了要相互訪問,例如:springboot要訪問資料庫和redis,angualr要呼叫springboot介面。而且考慮到k8s上經常要對某個服務做多節點的叢集,所以要在註冊中心開放給外界訪問的地址應該是叢集的地址。
我們在docker-compose上是怎麼做的呢?在docker-compose.yml 上定義多個服務service,每個service對應於一個映象。容器啟動後,對應容器的服務名稱即可以作為 hostname來使用。
k8s上也有類似的用法,它使用yaml檔案,kind型別有很多,例如:Pod表示啟動的服務是一個pod;ReplicationController則會根據Pod模板生成一批pod作為叢集;Service則相當於服務的註冊,可給與之對應的pod副本叢集提供訪問地址,等等還有很多。那這個問題Service就能解決,我們給不同的服務都建立一個Service,這樣就也能同docker-compose一樣通過服務的名稱就能訪問與之對應服務的pod副本叢集。
其他
因為業務需要,在之前的三個映象的基礎上又加了一個redis映象。那麼分散式redis、分散式mysql環境搭建就太麻煩了,如果以後有機會再單獨寫文章來介紹,這次我乾脆就只啟動單節點的mysql和redis。
nfs共享目錄
NFS是Network File System的簡寫,即網路檔案系統,NFS是FreeBSD支援的檔案系統中的一種。NFS基於RPC(Remote Procedure Call)遠端過程呼叫實現,其允許一個系統在網路上與它人共享目錄和檔案。通過使用NFS,使用者和程式就可以像訪問本地檔案一樣訪問遠端系統上的檔案。NFS是一個非常穩定的,可移植的網路檔案系統。
選用nfs的另一個原因是,nfs服務在k8s上可以直接作為儲存卷使用,十分方便。
安裝
nfs是基於rpc的,安裝nfs就需要確保已安裝rpcbind,不過一般CentOS都預設已安裝了rpcbind
##查詢是否已安裝nfs 和 rpcbind [mpaas@kerry1 k8s]$ rpm -qa | grep nfs [mpaas@kerry1 k8s]$ rpm -qa | grep rpcbind ##如果沒安裝,則通過有yum安裝 [mpaas@kerry1 k8s]$ yum -y install nfs-utils [mpaas@kerry1 k8s]$ yum -y install rpcbind
安裝完成後,必須要先啟動rpcbind服務,再啟動nfs服務
[mpaas@kerry1 k8s]$ systemctl start rpcbind [mpaas@kerry1 k8s]$ systemctl start nfs-server
設定開機啟動
[mpaas@kerry1 k8s]$ systemctl enable rpcbind [mpaas@kerry1 k8s]$ systemctl enable nfs-server
配置
通過修改/etc/exports 檔案,設定nfs的共享目錄
/home/nfs/bees/mysql/data *(rw,no_root_squash,no_all_squash,sync)
如上,將 /home/nfs/bees/mysql/data作為共享目錄
星號* 代表可在任意伺服器上訪問該共享目錄,也可以指定特點的ip和埠訪問
括號內是引數設定,常見的引數則有:
rw ro該目錄分享的許可權是可擦寫 (read-write) 或只讀 (read-only),但最終能不能讀寫,還是與檔案系統的 rwx 及身份有關。 sync asyncsync 代表資料會同步寫入到記憶體與硬碟中,async 則代表資料會先暫存於記憶體當中,而非直接寫入硬碟! no_root_squash root_squash客戶端使用 NFS 檔案系統的賬號若為 root 時,系統該如何判斷這個賬號的身份?預設的情況下,客戶端 root 的身份會由 root_squash 的設定壓縮成 nfsnobody, 如此對伺服器的系統會較有保障。但如果你想要開放客戶端使用 root 身份來操作伺服器的檔案系統,那麼這裡就得要開 no_root_squash 才行! all_squash不論登入 NFS 的使用者身份為何, 他的身份都會被壓縮成為匿名使用者,通常也就是 nobody(nfsnobody) 啦! anonuid anongidanon 意指 anonymous (匿名者) 前面關於 *_squash 提到的匿名使用者的 UID 設定值,通常為 nobody(nfsnobody),但是你可以自行設定這個 UID 的值!當然,這個 UID 必需要存在於你的 /etc/passwd 當中! anonuid 指的是 UID 而 anongid 則是群組的 GID 囉。
編輯完 /etc/exports 檔案後,執行下列命令生效
[mpaas@kerry1 k8s]$exportfs -r
在伺服器端,可執行下列命令檢視目錄是否共享成功
[mpaas@kerry1 k8s]$ showmount -e localhost Export list for localhost: /home/nfs/bees/mysql/data *
也可以在另外一臺機器上安裝nfs後執行上述命令,只需要將localhost換成目標伺服器的ip地址即可。
nginx服務
先啟動nginx來部署angualr,我們需要建立一個RC,根據模板建立pods,暫時只建立一個pod,後續如果需要擴充套件再在rancher上管理。
建立bees_angular_rc.yaml,開放pod的80埠
apiVersion: v1 kind: ReplicationController metadata: name: bees-angular spec: replicas: 1 selector: app: bees-angular template: metadata: labels: app: bees-angular spec: containers: - name: bees-angular image: registry.cn-hangzhou.aliyuncs.com/kerry2019/bees-nginx:v1.0 ports: - containerPort: 80
建立bees_angualr_svc.yaml,設定nodePort,將pod的80埠對映給宿主機的30000埠
apiVersion: v1 kind: Service metadata: name: bees-angular spec: type: NodePort ports: - port: 80 nodePort: 30000 selector: app: bees-angular
那麼執行下列命令即可建立rc和service,與之對應的pod也會執行起來
##啟動rc [mpaas@kerry1 k8s]$ kubectl create -f bees-angular-rc.yaml ##啟動service [mpaas@kerry1 k8s]$ kubectl create -f bees-angular-svc.yaml ##檢視pod是否啟動成功 [mpaas@kerry1 k8s]$ kubectl get pods
mysql服務
建立bees_mysql_rc.yaml,開放pod的3306埠,並將nfs伺服器上的共享目錄 /home/nfs/bees/mysql/data 掛載到容器中
apiVersion: v1 kind: ReplicationController metadata: name: bees-mysql spec: replicas: 1 selector: app: bees-mysql template: metadata: labels: app: bees-mysql spec: containers: - name: bees-mysql image: registry.cn-hangzhou.aliyuncs.com/kerry2019/bees-mysql:v1.0 ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: 資料庫密碼 volumeMounts: - name: mysql-data-persistent-storage mountPath: /var/lib/mysql volumes: - name: mysql-data-persistent-storage nfs: path: /home/nfs/bees/mysql/data server: nfs伺服器的ip
建立bees_mysql_svc.yaml
apiVersion: v1 kind: Service metadata: name: bees-mysql spec: type: NodePort ports: - port: 3306 nodePort: 30003 selector: app: bees-mysql
springboot服務
bees_springboot_rc.yaml
kind: ReplicationController metadata: name: bees-springboot spec: replicas: 1 selector: app: bees-springboot template: metadata: labels: app: bees-springboot spec: containers: - name: bees-springboot image: registry.cn-hangzhou.aliyuncs.com/kerry2019/bees-springboot:v1.0 ports: - containerPort: 8010
bees_springboot_svc.yaml
apiVersion: v1 kind: Service metadata: name: bees-springboot spec: type: NodePort ports: - port: 8010 nodePort: 30004 selector: app: bees-springboot
都是一些基礎的程式碼使用,這裡就不過多寫了。由於我本身對於k8s的掌握還不夠,遷移k8s之後的自動部署指令碼該如何修改?待後續我研究完之後再補上文件。