演示的最終效果如下圖,把閘道器部分和ingress去掉了,這裡只演示核心,寫了一個提供者和一個消費者,然後把他們註冊到外部到註冊中心nacos中,然後瀏覽器訪問消費者的時候,消費者用註冊中心獲取的服務名遠端去訪問提供者的資料。
同時還會演示nacos配置中心動態修改配置檔案的效果。從而達到了,k8s只部署應用服務的目的,而公共元件,資料庫,配置中心,中介軟體等放到k8s外面部署。
準備工作minikube:我這裡的演示環境用的minikube。相當於你們的k8s的部署環境
為了方便大家開發和體驗Kubernetes,提供了可以在本地部署的Minikube,minikube安裝部署方便,功能和真實環境的Kubernetes功能是一樣的。
docker:編譯和上傳應用程式映象需要用它,相關於你自己的開發環境。
映象倉庫:映象倉庫用來上傳打包好的映象,然後在其他伺服器上可以pull下來,我的映象倉庫中心直接用的docker hub官方的。你可以用阿里的或者私有docker中心。
我的演示電腦是mac
springcloud微服務k8s部署程式碼說明
這裡先看下provider以及consumer核心程式碼,如下:
provider的controller程式碼:
@RestController@Slf4j//實時更新配置中心的配置項@RefreshScopepublic class MainController { //注入配置檔案中的配置項,從nacos配置中心實時拉取 @Value("${test}") private String test; @GetMapping("helloK8s") public String helloK8s() { String ip = getIp(); System.out.println(test); return "provider--helloK8s test:"+test+" ip: "+ip; } //獲取本機ip地址 private String getIp(){ InetAddress ia=null; try { ia=InetAddress.getLocalHost(); String localname=ia.getHostName(); String localip=ia.getHostAddress(); System.out.println("本機名稱是:"+ localname); System.out.println("本機的ip是 :"+localip); return localip; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return ""; }}
consumer的controller程式碼:
@RestController@Slf4j//實時更新配置中心的配置項@RefreshScopepublic class ConsumerController { @Autowired private RestTemplate restTemplate; //注入配置檔案中的配置項,從nacos配置中心實時拉取 @Value("${test}") private String test; @GetMapping("/echo/appName") public String echoProviderName(){ //透過nacos註冊中心中的服務名first-provider去訪問提供者api String url = "http://first-provider/helloK8s"; String res = restTemplate.getForObject(url,String.class); log.info("res is {}",res); return "consumer---config: " +test+" content:" + res; }}
然後就是pom docker打包上傳的核心配置部分:
裡面的配置我不做過多講解了,可以自行百度。我這裡主要說明一點,裡面的配置項
<docker.host>http://192.168.1.105:3375</docker.host>
這裡面的地址配置的是訪問本地docker deamon的地址,docker的原理其實就是當你執行docker命令的時候,它會把命令傳送給docker deamon程式來執行具體的動作。
Daemon是Docker的守護程序,Docker Client透過命令列與Docker Damon通訊,完成Docker相關操作
Docker代理服務(shipyard/docker-proxy)
docker run -p 3375:2375 -v /var/run/docker.sock:/var/run/docker.sock -d -e PORT=2375 shipyard/docker-proxy
然後你的代理地址就是本機ip+3375,配置到pom檔案中即可。
開始操作第一步:編譯應用程式打包成jar,並編譯成docker映象,然後push到docker倉庫中心。
這裡的wanglining1987/test-k8s:provider build出來的映象
然後同理對consumer工程也執行這個步驟,最終jar包映象都上傳到了docker映象中心,如下圖:
這兩個映象就是上面編譯出來的。分別是消費者和生產者映象。
第二步,啟動minikube,並且啟動dashboard
啟動minikube,並指定阿里映象中心
minikube start --registry-mirror=https://j3wvoj70.mirror.aliyuncs.com
啟動dashboard,執行命令:minikube dashboard
執行結果如下:
執行成功後,會自動跳轉到dashboard介面,如下圖:
透過dashboard可以方便地管理k8s,比如操作Service,Deployment, pod等,每一步操作都會提示對應那個命令,很好用,提供了很大的方便。
第三步,編寫k8s的Deplyment對應的yaml檔案,來部署應用到Pod中
yaml檔案如下:
apiVersion: apps/v1kind: Deploymentmetadata: name: first-deployment-2 labels: app: first-app-labelspec: # 啟動三個例項 replicas: 3 selector: matchLabels: app: first-app template: metadata: labels: app: first-app spec: containers: - name: first-app # 指定要執行的映象,啟動後,會從映象中心下載該映象並執行 image: wanglining1987/test-k8s:provider ports: - containerPort: 8080---apiVersion: apps/v1kind: Deploymentmetadata: name: consumer labels: app: consumer-labelspec: replicas: 1 selector: matchLabels: app: consumer-app template: metadata: labels: app: consumer-app spec: containers: - name: consumer-app image: wanglining1987/test-k8s:consumer-2 ports: - containerPort: 8082
建立完成檔名:first-deployment.yaml
啟動nacos
執行應用映象之前,記住先把nacos註冊中心啟動一下,不然就啟動失敗了,按照最開始的架構,註冊中心是放到k8s外面執行,直接在本機電腦上執行啟動nacos即可,不放到k8s中。
執行起來後,可以透過 http://localhost:8848/nacos/去訪問nacos管理頁面
執行映象
然後執行如下命令,來把provider和consumer對應的映象執行起來。
kubectl create -f first-deployment.yaml
執行起來後,在dashboard中看下效果,如下:
上面兩個是啟動起來的Deployment。點進去可以檢視Deployment的詳情,具體什麼是Deployment就不展開說了,k8s裡的概念,有興趣去百度即可。這裡也可以用命令去檢視執行的Deployment,沒有dashboard來的方便直接。
然後可以去檢視Deployment部署的Pod,並且去檢視Pod內應用執行的日誌:
這裡consumer運行了一個例項,provider運行了三個,這個例項數量,也是在上面的first-deployment.yaml檔案中指定了。檢視pod日誌:
還是很方便的。可以看到應用起來了。
檢查下nacos註冊中心中是否已經註冊上應用了,開啟註冊中心管理介面地址如下圖:
可以看到有兩個服務註冊進去了first-provider和first-consumer,其中first-provider是三個例項,first-consumer是一個,跟前面配置的一致,在進去看下服務詳情如下:
觀察其IP地址,是k8s分配的內部地址,成功註冊到外部的nacos上了,這裡需要注意,k8s內的服務是可以訪問k8s外部的ip地址的,只是外部的機器沒有辦法訪問k8s內部的服務ip。
剩下最後一步了就是透過瀏覽器訪問下消費者,看看能不能成功呼叫提供者介面,並返回結果到頁面。
部署service暴露出來接下來要透過瀏覽器訪問消費者,怎麼訪問呢?直接透過ip肯定不行,都是k8s內部的ip地址。
k8s解決了這個問題,都很多方法,可以是ingress,或者直接透過Service直接暴露出來。
這裡簡單把k8s官網的對service和pod定義拉下來,供參考:
Kubernetes Pods是有生命週期的。他們可以被建立,而且銷燬不會再啟動。 如果您使用Deployment來執行您的應用程式,則它可以動態建立和銷燬 Pod。
一個Kubernetes的Service是一種抽象,它定義了一組Pods的邏輯集合和一個用於訪問它們的策略 - 有的時候被稱之為微服務。一個Service的目標Pod集合通常是由Label Selector 來決定的(下面有講一個沒有選擇器的Service 有什麼用處)。
舉個例子,想象一個處理圖片的後端運行了三個副本。這些副本都是可以替代的 - 前端不關心它們使用的是哪一個後端。儘管實際組成後端集合的Pod可能會變化,前端的客戶端卻不需要知道這個變化,也不需要自己有一個列表來記錄這些後端服務。Service抽象能讓你達到這種解耦。
對於熟悉springcloud微服務的,你就可以把k8s裡的這個service和springcloud中的微服務概念去對應,道理是差不多的。k8s可以把service通過幾種方式暴露出來,供外部訪問,有四種方式如下:
ClusterIP:透過叢集的內部 IP 暴露服務,選擇該值時服務只能夠在叢集內部訪問。 這也是預設的 ServiceType。
NodePort:透過每個節點上的 IP +靜態埠(NodePort)暴露服務。 NodePort 服務會路由到自動建立的 ClusterIP 服務。 透過請求 <節點 IP>:<節點埠>,你可以從叢集的外部訪問一個 NodePort 服務。
LoadBalancer:使用雲提供商的負載均衡器向外部暴露服務。 外部負載均衡器可以將流量路由到自動建立的 NodePort 服務和 ClusterIP 服務上。
ExternalName:透過返回 CNAME 和對應值,可以將服務對映到 externalName 欄位的內容(例如,foo.bar.example.com)。 無需建立任何型別的代理。
這裡選擇最方便的NodePort方式,對應的Service yaml檔案如下:
apiVersion: v1kind: Servicemetadata: name: consumer-service labels: app: consumer-app role: masterspec: type: NodePort#type: LoadBalancer ports: - port: 8083 targetPort: 8082 selector: # 這裡的consumer-app會去匹配first-deployment.yaml的template部分定義的lable名 # 從而和具體的Pod關聯起來了 app: consumer-app
命名:first-service.yaml,然後透過如下命令啟動Service
kubectl create -f first-service.yaml
啟動成功後,檢視dashboard,如下:
可以看到consumer-service啟動成功,跟yaml中定義的一致。
然後執行命令:
$minikube service consumer-service --urlhttp://192.168.64.2:32376
會把訪問服務的ip地址和埠打印出來,透過http://192.168.64.2:32376就可以訪問到consumer-service後面實際對應的應用程式了。
在最開始consumer專案對應的controller中定義了api /echo/appName,把路徑拼起來,去瀏覽器訪問:http://192.168.64.2:32376/echo/appName
對照前面provider和consumer程式碼看下,k8s內部的consumer透過外部的nacos註冊中的服務名成功的呼叫到了provider的介面,並列印輸出介面。
程式碼中還把配置檔案中的test變數列印了出來,這個主要是為了測試nacos配置中心的變化能不能更新到k8s內部的服務中的。如下部分
@Value("${test}")private String test;
nacos配置中心中的配置:
檔案內容
consumer配置檔案
provider配置檔案
列印結果中,標紅部分是配置中心的配置,也是成功了。
consumer---config: ffff content:provider--helloK8s test:eeeaafff ip: 172.17.0.7
總結我們的方案使用springcloud全部元件和特性,對開發者開發除錯更容易,開發方式也更熟悉。部署的時候只需要部署應用部分,發揮k8s部署擴容方便的優勢。結合了兩者共同的優勢