3小時學會Kubernetes

本文主要是講解在Kubernates集羣上運行基於微服務的應用程序。html

原文內容來自Learn Kubernetes in Under 3 Hours: A Detailed Guide to Orchestrating Containers前端

零、準備工做

0.1 項目介紹

這個項目只有一個功能:在Web瀏覽器上輸入一個句子,而後會計算句子所表達的情緒。java

從技術的角度看,這個應用程序包含3個微服務,每一個都包含特定的功能:node

  • SA-Frontend:前端,Nginx網絡服務器,提供ReactJS靜態文件;
  • SA-WebApp:網絡應用,Java網絡應用程序,處理來自前端的請求;
  • SA-Logic:邏輯處理,Python應用程序,執行情感分析。

咱們能夠經過微服務之間的數據流來描述這種交互:python

  1. 客戶端應用程序請求初始頁面index.html(index.html頁面會加載ReactJS應用程序的腳本)
  2. 用戶與應用程序的交互請求到基於Spring的WebApp
  3. WebApp轉發情緒分析到Python應用。
  4. Python應用計算情緒值後返回。
  5. WebApp返回響應到ReactApp,而後ReactApp向用戶展現信息。

如今就克隆這個代碼庫:github.com/heqingbao/k…,接下來咱們要作更精彩的東西。nginx

1、在計算機上運行基於微服務的應用程序

咱們須要啓動所需的3個服務,這裏從前端應用程序開始。git

1.1 部署 sa-frontend 項目

1.1.1 設置React的本地部署

爲了運行React應用程序,須要先在計算機上安裝NodeJS和NPM,安裝好這些後,在終端中進入目錄sa-frontend,而後運行以下命令:github

npm install
複製代碼

該命令會將 React 應用程序的全部 Javascript 依賴都下載到文件夾 node_modules 中(package.json 文件中定義了全部依賴)。在全部依賴都解決後,運行以下命令:web

npm start
複製代碼

這樣就能夠了!咱們運行了 React 應用程序,如今能夠經過默認端口 localhost:3000 訪問該應用程序了。你能夠自由修改代碼,並從瀏覽器中觀察即時效果。spring

1.1.2 準備好 React 應用的產品環境

爲了搭建產品環境,咱們須要創建應用程序的靜態網頁,並經過網絡服務器提供服務。

首先在終端中進入目錄sa-frontend,而後運行以下命令:

npm run build
複製代碼

該命令會在項目的文件目錄中生成一個名叫「build」的文件夾。該文件夾內包含了 ReactJS 應用程序所需的全部靜態文件。

1.1.3 利用Nginx提供靜態文件

首先安裝並啓動 Nginx 網絡服務器。而後將 sa-frontend/build 目錄內的文件移動到 [nginx安裝目錄]/html。

如此一來,咱們就能夠經過 [nginx安裝目錄]/html/index.html 來訪問 index.html 文件了,而它是 Nginx 服務的默認文件。

默認狀況下,Nginx 網絡服務器會監聽端口 80。你能夠經過修改 [nginx安裝目錄]/conf/nginx.conf 文件中的 server.listen 字段來指定不一樣的端口。

打開瀏覽器,並訪問端口 80,能夠看到 ReactJS 應用程序加載成功。

在輸入框Type your sentence中輸入句子,而後點擊SEND,發現沒什麼反應。由於它會向http://localhost:8080/sentiment發送請求,接下來咱們就部署這個服務。

1.2 部署 sa-webapp 項目

1.2.1 建議Spring網絡應用程序

爲了編譯sa-webapp項目,必須安裝JDK8和Maven,並設置它們的環境變量。設置好後繼續操做。

1.2.2 將應用程序打包成jar文件

在終端中進入sa-webapp目錄,並運行以下命令:

mvn install
複製代碼

該命令會在目錄 sa-webapp 中生成一個名叫 target 的文件夾。target 文件夾內有打包好的 Java 應用程序包:’sentiment-analysis-web-0.0.1-SNAPSHOT.jar’。

1.2.3 啓動應用程序

進入target目錄,並經過以下命令啓動應用程序:

java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar
複製代碼

啓動失敗,能夠看到以下異常信息:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sentimentController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'sa.logic.api.url' in value "${sa.logic.api.url}"
複製代碼

這裏顯示的重要信息是sentimentController中的${sa.logic.api.url}沒法注入。下面是源碼:

@CrossOrigin(origins = "*")
@RestController
public class SentimentController {
@Value("${sa.logic.api.url}")
private String saLogicApiUrl;
@PostMapping("/sentiment")

public SentimentDto sentimentAnalysis(@RequestBody SentenceDto sentenceDto) {
    RestTemplate restTemplate = new RestTemplate();
    return restTemplate.postForEntity(
        saLogicApiUrl + "/analyse/sentiment", sentenceDto, SentimentDto.class).getBody();
    }
}
複製代碼

在 Spring 中默認的屬性資源是 application.properties(具體位置在 sa-webapp/src/main/resources 中)。可是這不是定義屬性的惟一方式,咱們能夠經過以前的命令完成屬性定義:

java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=WHAT.IS.THE.SA.LOGIC.API.URL
複製代碼

這裏應該由Python應用程序運行時定義的值初始化該屬性,如此一來String網絡應用程序就能夠知道在運行時把信息傳遞到哪裏了。

爲了簡單起見,咱們假設在localhost:5000上運行Python應用程序。

運行以下命令,而後咱們再部署最後一個服務:Python應用程序。

java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=http://localhost:5000
複製代碼

1.3 部署 sa-logic 項目

爲了啓動 Python 應用程序,首先咱們須要安裝 Python3 和 pip,以及設置它們的環境變量。(若是本機只有python2,建議使用virtualenv配置python多環境)

1.3.1 安裝依賴

在終端中進入 sa-logic/sa目錄,而後運行以下命令:

python -m pip install -r requirements.txt
python -m textblob.download_corpora
複製代碼

注意:若是是新安裝的python3,而且經過virtualenv建立的pytho> n3環境,在執行python -m textblob.download_corpora的時候可能會報如下錯誤:

(venv) ➜  sa git:(master) ✗ python -m textblob.download_corpora
[nltk_data] Error loading brown: <urlopen error [SSL:
[nltk_data]     CERTIFICATE_VERIFY_FAILED] certificate verify failed:
[nltk_data]     unable to get local issuer certificate (_ssl.c:1051)>
[nltk_data] Error loading punkt: <urlopen error [SSL:
[nltk_data]     CERTIFICATE_VERIFY_FAILED] certificate verify failed:
[nltk_data]     unable to get local issuer certificate (_ssl.c:1051)>
[nltk_data] Error loading wordnet: <urlopen error [SSL:
[nltk_data]     CERTIFICATE_VERIFY_FAILED] certificate verify failed:
[nltk_data]     unable to get local issuer certificate (_ssl.c:1051)>
[nltk_data] Error loading averaged_perceptron_tagger: <urlopen error
[nltk_data]     [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify
[nltk_data]     failed: unable to get local issuer certificate
[nltk_data]     (_ssl.c:1051)>
[nltk_data] Error loading conll2000: <urlopen error [SSL:
[nltk_data]     CERTIFICATE_VERIFY_FAILED] certificate verify failed:
[nltk_data]     unable to get local issuer certificate (_ssl.c:1051)>
[nltk_data] Error loading movie_reviews: <urlopen error [SSL:
[nltk_data]     CERTIFICATE_VERIFY_FAILED] certificate verify failed:
[nltk_data]     unable to get local issuer certificate (_ssl.c:1051)>
Finished.
複製代碼

解決方式是執行一下這個文件:/Applications/Python\ 3.7/Install\ Certificates.command,此文件經過Finder->應用程序裏面可以找到,雙擊就行。

1.3.2 啓動應用

在利用 Pip 安裝好依賴後,咱們就能夠經過運行以下命令啓動應用程序了:

python sentiment_analysis.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
複製代碼

這意味着應用程序已經啓動,並在 localhost 的端口 5000 上監聽 HTTP 請求了。

到此,若是一切順利,那麼在瀏覽器上訪問:http://localhost:3000/,而後在輸入框中輸入句子,應該就可以顯示情緒值了。

後面將介紹如何在Docker容器內啓動這些服務,由於這是在Kubernetes集羣內運行這些服務的前提條件。

2、爲每一個服務建立容器鏡像

Kubernetes 是容器管理平臺。可想而知咱們須要容器去管理它們。可是容器是什麼?Docker 官方文檔的最佳答案以下:

容器映像是輕量級的、獨立的、可執行軟件包,包含全部可運行的東西:代碼、運行時、系統工具、系統庫、設置。對於基於 Linux 和 Windows 的應用,不論環境如何,容器化的軟件均可以照常運行。

這意味着容器能夠在任何計算機上運行,甚至是在產品服務器上,都沒有任何差異。

爲了更形象地描述,讓咱們來對比一下 React 應用程序在虛擬機上和容器內運行的狀況。

經過虛擬機提供 React 靜態文件

使用虛擬機的缺點包括:

  • 資源效率低下,每一個虛擬機都須要一個徹底成熟的操做系統;
  • 對平臺有依賴性。本地機器上運行得很好的功能未必能在產品服務器上正常工做;
  • 與容器相比,更重並且規模伸縮較慢。

經過容器提供 React 靜態文件

使用容器的優勢包括:

  • 資源效率很高,在 Docker 的幫助下使用主機操做系統;
  • 對平臺沒有依賴性。能夠在本地機器上運行的容器能夠在任何機器上正常工做;
  • 經過映像層提供輕量級服務。

2.1 爲React應用創建容器鏡像

2.1.1 Docker簡介

Docker 容器最基本的組件是.dockerfile。該 Dockerfile 文件最基本的組成是容器鏡像,咱們將經過下列一系列說明,介紹如何建立一個符合應用程序需求的容器鏡像。

在開始定義 Dockerfile 以前,讓咱們先回想一下使用 Nginx 服務 React 靜態文件的步驟:

  1. 建立靜態文件(npm run build);
  2. 啓動 Nginx 服務器;
  3. 將前端項目的 build 文件夾的內容複製到 nginx/html 目錄中。

在下一節中,你會注意到建立容器與創建本地 React 的過程很是類似。

2.1.2 爲前端定義Dockerfile

前端 Dockerfile 的創建只有兩個步驟。這是由於 Nginx 團隊爲咱們提供了基本的 Nginx 映像,咱們能夠直接利用。這兩個步驟以下:

  1. 啓動基本的 Nginx 映像;
  2. 將 sa-frontend/build 目錄複製到容器的 nginx/html 中。

轉換成的Dockerfile以下所示:

FROM nginx
COPY build /usr/share/nginx/html
複製代碼

這個文件是可讀的,咱們能夠歸納爲:

從 Nginx 映像開始(無論裏面是什麼)。將 build 目錄複製到映像的 nginx/html 目錄中。而後就行了!

你可能在想,我應該將 build 文件複製到哪兒呢?例如:/usr/share/nginx/html。很是簡單:在 Docker Hub 的 Nginx 映像文檔中有記載。

2.1.3 創建並推送容器

在推送映像以前,咱們須要一個容器註冊來託管映像。Docker Hub 是一個免費的雲容器服務,咱們將使用它來作演示。接下來有 3 個任務須要完成:

  1. 安裝 Docker CE;

  2. 註冊 Docker Hub;

  3. 在終端中運行以下命令登陸:

    docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
    複製代碼

    或者執行:

    docker login
    複製代碼

    而後使用交互模式填寫用戶名和密碼。

在完成上述任何後,請進入目錄 sa-frontend。而後運行以下命令(請用你的 docker hub 用戶名替換 $DOCKER 用戶名,例如:heqingbao/sentiment-analysis-frontend)。

[root@VM_0_3_centos sa]# docker build -f Dockerfile -t heqingbao/sentiment-analysis-frontend .
Sending build context to Docker daemon 1.768 MB
Step 1/2 : FROM nginx
Trying to pull repository docker.io/library/nginx ... 
sha256:d59a1aa7866258751a261bae525a1842c7ff0662d4f34a355d5f36826abc0341: Pulling from docker.io/library/nginx
f17d81b4b692: Pull complete 
82dca86e04c3: Pull complete 
046ccb106982: Pull complete 
Digest: sha256:d59a1aa7866258751a261bae525a1842c7ff0662d4f34a355d5f36826abc0341
Status: Downloaded newer image for docker.io/nginx:latest
 ---> 62f816a209e6
Step 2/2 : COPY build /usr/share/nginx/html
 ---> 8284804168aa
Removing intermediate container f74eb32d3c46
Successfully built 8284804168aa
複製代碼

注意:若是是部署在遠端服務器上,必定要把App.js裏面的http://localhost:8080/sentimentlocalhost換成遠端主機的IP或容器的IP。

如今咱們能夠刪掉 -f Dockerfile 了,由於咱們已經在包含 Dockerfile 的目錄中了。

咱們可使用 docker push 命令來推送映像:

[root@VM_0_3_centos sa]# docker push heqingbao/sentiment-analysis-frontend
The push refers to a repository [docker.io/heqingbao/sentiment-analysis-frontend]
a5a0d2defc6a: Pushed 
ad9ac0e6043b: Mounted from library/nginx 
6ccbee34dd10: Mounted from library/nginx 
237472299760: Mounted from library/nginx 
latest: digest: sha256:eb5adb74d0685e267771d5bcdc536015a8cb58fe88c1860d10f13d2994d3c063 size: 1158
複製代碼

請確認映像已成功地被推送到 docker hub 代碼庫。

2.1.4 運行容器

如今任何人均可以獲取 heqingbao/sentiment-analysis-frontend 中的映像並運行:

docker pull heqingbao/sentiment-analysis-frontend
docker run -d -p 80:80 heqingbao/sentiment-analysis-frontend
複製代碼

Docker 容器已經處於運行狀態了!

訪問:http://yourid:80,試試看,你如今應該能夠訪問React應用程序了。

2.1.5 Dockerignore文件

剛纔咱們看到創建 SA-Frontend 的映像很是慢,很差意思,應該是超級慢。這是由於咱們必須將創建過程當中的環境文件發送給 Docker 服務。更具體地來講,創建過程當中的環境文件指的是在創建映像的時候,全部會用到的 Dockerfile 目錄中的數據。

以咱們的例子來講,SA-Frontend 文件包括以下文件夾:

sa-frontend:
|   .dockerignore
|   Dockerfile
|   package.json
|   README.md
+---build
+---node_modules
+---public
\---src
複製代碼

可是咱們只須要 build 文件夾。上傳其餘的文件會浪費時間。咱們能夠經過刪除其餘目錄來節約時間。這就須要用到 .dockerignore。你可能以爲這與 .gitignore 很類似,例如你能夠全部想要忽略的目錄都添加到 .dockerignore,以下所示:

node_modules
src
public
複製代碼

這個 .dockerignore 文件應該與 Dockerfile 在同一文件夾中。如今創建映像文件只須要幾秒鐘了。

這裏使用了自定義容器鏡像的方式,可是若是咱們的鏡像只使用一次(例如寫一些測試Demo),大可沒必要建立本身的鏡像而後再傳到倉庫,咱們能夠直接使用官方的Nginx鏡像便可。

2.1.6 直接使用官方Nginx鏡像部署React應用

下載nginx鏡像:

docker pull docker.io/nginx
複製代碼

啓動nginx容器:

docker run -d -p 80:80 --name mynginx \
--volume "$PWD/html":/usr/share/nginx/html \
docker.io/nginx
複製代碼

上面命令的各個參數含義以下:

  • -d: 在後臺運行
  • -p: 容器的80端口映射到宿主機的80端口
  • --name: 容器的名字爲mynginx
  • --volume: 把當前目錄下的html目錄映射到容器的/usr/share/nginx/html目錄

而後把前面sa-frontend項目編譯後的build目錄裏的全部文件拷貝到當前路徑下的html目錄裏。

訪問:http://yourid:80,試試看,你如今應該也能夠訪問React應用程序。

2.2 爲Java應用創建容器鏡像

在 sa-webapp 中打開 Dockerfile:

FROM openjdk:8-jdk-alpine
# Environment Variable that defines the endpoint of sentiment-analysis python api.
ENV SA_LOGIC_API_URL http://localhost:5000
ADD target/sentiment-analysis-web-0.0.1-SNAPSHOT.jar /
EXPOSE 8080
CMD ["java", "-jar", "sentiment-analysis-web-0.0.1-SNAPSHOT.jar", "--sa.logic.api.url=${SA_LOGIC_API_URL}"]
複製代碼

關鍵字 ENV 在 Docker 容器內聲明瞭環境變量。這可讓咱們在啓動容器的時候爲情感分析 API 提供 URL。

另外,關鍵字 EXPOSE 提供了一個端口,供咱們之後訪問。可是等等,咱們在 SA-Frontend 的時候沒有作這一步,說得很對!這個端口僅用於文檔,換句話說就是這個端口是用來向閱讀 Dockerfile 的人提供信息的。

你應該已經掌握了建立和推送容器映像。

建立鏡像:

[root@VM_0_3_centos sa-webapp]# docker build -f Dockerfile -t heqingbao/sentiment-analysis-web-app .
Sending build context to Docker daemon 20.49 MB
Step 1/5 : FROM openjdk:8-jdk-alpine
Trying to pull repository docker.io/library/openjdk ... 
sha256:b18e45570b6f59bf80c15c78d7f0daff1e18e9c19069c323613297057095fda6: Pulling from docker.io/library/openjdk
4fe2ade4980c: Pull complete 
6fc58a8d4ae4: Pull complete 
ef87ded15917: Pull complete 
Digest: sha256:b18e45570b6f59bf80c15c78d7f0daff1e18e9c19069c323613297057095fda6
Status: Downloaded newer image for docker.io/openjdk:8-jdk-alpine
 ---> 97bc1352afde
Step 2/5 : ENV SA_LOGIC_API_URL http://localhost:5000
 ---> Running in c3be1ec16ac4
 ---> ab213d1b2ce1
Removing intermediate container c3be1ec16ac4
Step 3/5 : ADD target/sentiment-analysis-web-0.0.1-SNAPSHOT.jar /
 ---> 5d1ebdbf659d
Removing intermediate container 7e5b7519d9e3
Step 4/5 : EXPOSE 8080
 ---> Running in e428a3388798
 ---> 0893bf90a104
Removing intermediate container e428a3388798
Step 5/5 : CMD java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=${SA_LOGIC_API_URL}
 ---> Running in 065ac2e61dbd
 ---> cba14182f49f
Removing intermediate container 065ac2e61dbd
複製代碼

啓動容器:

[root@VM_0_3_centos sa-webapp]# docker run -d -p 8080:8080 -e SA_LOGIC_API_URL='http://x.x.x.x:5050' heqingbao/sentiment-analysis-web-app
b3ab99abecd7a97f091e2362b4eee870037e562347f3996a9a1a2669ca60c651
複製代碼

上傳到倉庫:

[root@VM_0_3_centos sa-webapp]# docker push heqingbao/sentiment-analysis-web-app
The push refers to a repository [docker.io/heqingbao/sentiment-analysis-web-app]
4e1c5d0784bf: Pushed 
ed6f0bd39121: Mounted from library/openjdk 
0c3170905795: Mounted from library/openjdk 
df64d3292fd6: Mounted from library/openjdk 
latest: digest: sha256:be20fe12c184b6c4d2032141afe9b8cc092a9a083f1cf0a7dc8f73c4b1ebbaf8 size: 1159
複製代碼

2.3 爲Python應用創建容器鏡像

sa-logic 的 Dockerfile:

FROM python:3.6.6-alpine
COPY sa /app
WORKDIR /app
RUN pip3 install -r requirements.txt && \
    python3 -m textblob.download_corpora
EXPOSE 5000
ENTRYPOINT ["python3"]
CMD ["sentiment_analysis.py"]
複製代碼

如今你已是 Docker 達人了。

構建容器鏡像:

docker build -f Dockerfile -t heqingbao/sentiment-analysis-logic .
複製代碼

運行Docker容器:

docker run -d -p 5050:5000 heqingbao/sentiment-analysis-logic
複製代碼

2.4 測試容器化應用程序

1.運行sa-logic容器,並配置監聽端口5050:

docker run -d -p 5050:5000 heqingbao/sentiment-analysis-logic
複製代碼

2.運行 sa-webapp 容器,並配置監聽端口 8080(由於咱們改變了 Python 應用監聽的端口,因此咱們須要重寫環境變量 SA_LOGIC_API_URL):

$ docker run -d -p 8080:8080 -e SA_LOGIC_API_URL='http://x.x.x.x:5050' heqingbao/sentiment-analysis-web-app
複製代碼

3.運行 sa-frontend 容器:

docker run -d -p 80:80 heqingbao/sentiment-analysis-frontend
複製代碼

而後就能夠了。在瀏覽器中打開 x.x.x.x:80。

3、Kubernetes

3.1 爲何要使用Kubernetes?

本節中,咱們學習了 Dockerfile,如何使用它建立映像,以及推送映像到 Docker註冊目錄的命令。另外,咱們探討了如何經過忽略沒用的文件,減小須要發送的創建過程當中的環境文件。最後咱們從容器上運行了應用程序。

接下來,咱們介紹爲何要使用 Kubernetes?咱們將在下面深刻介紹 Kubernetes,這裏我想給你留個智力問答題。

  • 若是咱們的情感分析網絡應用完成得很好,忽然間訪問量暴漲到每分鐘數百萬的請求,那麼咱們的 sa-webapp 和 sa-logic 將面臨巨大的負荷壓力。請問,咱們如何才能擴大容器的規模?

3.2 Kubernetes簡介

我向你保證我沒有誇大其詞,讀完本文你會問「爲何咱們不稱它爲 Supernetes?」

3.2.1 Kubernetes 是什麼?

從容器啓動微服務後,咱們有一個問題,讓咱們經過以下問答的形式具體描述這個問題:

問:咱們怎麼擴大或縮小容器?

答:咱們啓動另一個容器。

問:咱們如何在容器間分攤負荷?若是當前服務器的負荷達到最大,那咱們是否須要另一個服務器?咱們如何最大化硬件使用率?

答:唔......呃......(讓我搜一下)

問:若是在打更新補丁的時候,不影響到全部的服務?若是服務出了問題,如何才能返回以前能正常工做的版本?

Kubernetes 能夠解決以上全部問題(以及更多問題!)。我能夠用一句話總結 Kubernetes:「Kubernetes 是容器控制平臺,能夠抽象全部的底層基礎設施(容器運行用到的基礎設施)。」

咱們對容器控制平臺有個模糊的概念。在本文後續部分,咱們將看看它的實際應用,可是這是第一次咱們提到「底層基礎設施的抽象」,因此咱們來詳細看看這個概念。

3.2.2 底層基礎設施的抽象

Kubernetes 經過一個簡單的 API 提供底層基礎設施的抽象,咱們能夠向該 API 發送請求。這些請求可讓 Kubernetes 盡最大能力應對。例如,能夠簡單地要求「Kubernetes 添加映像 x 的 4 個容器。」而後 Kubernetes 會找出使用中的節點,並在內添加新的容器。

這對開發人員來講意味着什麼?意味着開發人員不須要在乎節點的數目,也不須要在乎從哪裏運行容器以及如何與它們交流。開發人員不須要管理硬件優化,或擔憂節點關閉(它們將遵循墨菲法則),由於新的節點會添加到 Kubernetes 集羣。同時 Kubernetes 會在其餘運行的節點中添加容器。Kubernetes 會發揮最大的做用。

在上圖中咱們看到了一些新東西:

  • API服務器:與集羣交互的惟一方式。負責啓動或中止另一個容器,或檢查當前狀態,日誌等;
  • Kubelet:監視節點內的容器,並與主節點交流;
  • Pod:初始階段咱們能夠把 pod 當成容器。

就介紹這麼多,跟深刻的介紹會致使咱們分心,咱們能夠等到後面一點再介紹,有一些有用的資源,好比官方文檔,或者閱讀 Marko Lukša 的著做《Kubernetes in Action》

3.2.3 標準化的雲服務提供商

Kubernetes 另一個深刻人心的點是:它標準化了雲服務提供商。這是一個很大膽的宣言,咱們經過以下例子來具體看一看:

好比,有一個 Azure、Google 雲平臺或其餘雲服務提供商的專家,他擔任了一個搭建在全新的雲服務提供商的項目。這可能引發不少後果,好比說:他可能沒法在截止期限內完成;公司可能須要招聘更多相關的人員,等等。

相對的,Kubernetes 就沒有這個問題。由於不管是哪家雲服務提供商,你均可以在上面運行相同的命令。你能夠以既定的方式向 API 服務器發送請求。Kubernetes 會負責抽象,並實裝這家雲服務商。

停一秒鐘仔細想一下,這是極其強有力的功能。對公司來講,這意味着他們不須要綁定到一家雲服務商。他們能夠計算別家雲服務商的開銷,而後轉移到別家。他們依舊能夠保留原來的專家,保留原來的人員,他們還能夠花更少的錢。

說了這麼多,在下一節中讓咱們來實際使用 Kubernetes。

4、Kubernetes實踐 -- Pod

咱們創建了微服務在容器上運行,雖然頗爲坎坷,但仍是能夠工做的。咱們還提到這種解決方案不具備伸縮性和彈性,而 Kubernetes 能夠解決這些問題。在本文的後續章節,咱們會將各個服務轉移到由 Kubernetes 管理的容器中,如圖所示。

在本文中,咱們將使用 Minikube 進行本地調試,儘管全部東西都是運行在 Azure 和 Google 雲平臺中的。(我這裏是部署在騰訊雲上的)

4.1 安裝和啓動Minikube

請參閱安裝 Minikube 的官方文檔:

kubernetes.io/docs/tasks/…

k8smeetup.github.io/docs/tasks/

在Mac上安裝minikube:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.18.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
複製代碼

在Mac上安裝kubectl,Kubectl 是向 Kubernetes API 服務器發送請求的客戶端:

curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.12.2/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
複製代碼

或者:

curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
複製代碼

一般狀況下,上面命令下載都會很慢,甚至根本就沒法下載。有兩個辦法:

  • 若是有代理,能夠在終端配置
  • 直接經過其它方式下載(好比瀏覽器),而後再改權限,再放到path環境下。

啓動minikube:

minikube start
複製代碼

第一次啓動的時候會自動下載Minikube ISO,根據網絡狀況時間會比較久。

注意:有可能會安裝失敗,好比出現下面的錯誤:

➜  Desktop minikube start  
There is a newer version of minikube available (v0.30.0).  Download it here:
https://github.com/kubernetes/minikube/releases/tag/v0.30.0

To disable this notification, run the following:
minikube config set WantUpdateNotification false
Starting local Kubernetes cluster...
Starting VM...
Downloading Minikube ISO
 89.51 MB / 89.51 MB [==============================================] 100.00% 0s
E1111 20:06:02.564775    4725 start.go:116] Error starting host: Error creating host: Error with pre-create check: "VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path".

 Retrying.
E1111 20:06:02.567379    4725 start.go:122] Error starting host:  Error creating host: Error with pre-create check: "VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path"
================================================================================
An error has occurred. Would you like to opt in to sending anonymized crash
information to minikube to help prevent future errors?
To opt out of these messages, run the command:
	minikube config set WantReportErrorPrompt false
================================================================================
Please enter your response [Y/n]:
複製代碼

意思是說沒有找到VboxManager命令,須要先安裝VirtualBox。安裝完VirtualBox後,再執行minikube start時不會從新下載Minikube ISO

在啓動後,運行 kubectl get nodes 命令能夠獲得以下結果:

➜  Desktop kubectl get nodes
NAME       STATUS     ROLES     AGE       VERSION
minikube   NotReady   <none>    18m       v1.6.0
複製代碼

注意:我這裏在安裝1.12.2版本後,執行kubectl get nodes報錯:

➜  Desktop kubectl get nodes
Error from server (NotAcceptable): unknown (get nodes)
複製代碼

後面從新安裝了1.8.7版本就沒有這個問題。

Minikube 提供給咱們的 Kubernetes 集羣只有一個節點,可是記住咱們並不在意有多少個節點,Kubernetes 會負責抽象,對咱們來講深刻掌握 Kubernetes 並不重要。

下面咱們將介紹 Kubernetes 的第一個資源:Pod。

4.2 Pod

我大愛容器,相信如今你也很喜歡容器。那爲何 Kubernetes 給咱們最小的可部署計算單元 Pod 呢?Pod是幹什麼的?由一個或一組容器組成的 Pod 能夠共享相同的運行環境。

可是咱們真的須要在一個 Pod 內運行兩個容器嗎?呃……通常來講,只會運行一個容器,咱們的例子中也是這樣的。可是有些狀況下,好比兩個容器須要共享卷,或它們之間是經過跨進程的交流方式交流的,又或者它們被綁到一塊兒,那麼就可使用 Pod。Pod 的另外一個特徵是:若是咱們但願使用其餘 Rke 等技術的話,咱們能夠作到不依賴 Docker 容器。

總的來講,Pod 的主要屬性包括(如上圖所示):

  1. 每一個 Pod 能夠在 Kubernetes 集羣內擁有惟一的 IP 地址;
  2. Pod 能夠擁有多個容器。這些容器共享同一個端口空間,因此他們能夠經過 localhost 交流(可想而知它們沒法使用相同的端口),與其餘 Pod 內容器的交流能夠經過結合 Pod 的 IP 完成;
  3. 一個 Pod 內的容器共享同一個卷、同一個 IP、端口空間、IPC 命名空間。

注:容器有個本身獨立的文件系統,儘管他們能夠經過 Kubernetes 的資源卷共享數據。

更多詳細內容,請參閱相關的官方文檔:

kubernetes.io/docs/concep…

4.2.1 Pod的定義

以下是咱們的第一個 pod sa-frontend 的清單文件,咱們會對文件內容進行逐一解釋。

apiVersion: v1
kind: Pod                                            # 1
metadata:
  name: sa-frontend                                  # 2
spec:                                                # 3
  containers:
    - image: rinormaloku/sentiment-analysis-frontend # 4
      name: sa-frontend                              # 5
      ports:
        - containerPort: 80                          # 6
複製代碼

#1 kind:指定咱們想建立的 Kubernetes 資源的類型。這裏是 Pod。

#2 name:定義該資源的名字。咱們在這裏命名爲 sa-frontend。

#3 spec:該對象定義了資源應有的狀態。Pod Spec 中最重要的屬性是容器的數組。

#4 image:是指咱們但願在本 Pod 中啓動的容器的映像。

#5 name:Pod 中容器中惟一的名字。

#6 containerPort:是指容器監聽的端口號。這只是爲了提供文檔信息(即使沒有這個端口也不會影響訪問)。

建立 SA Frontend 的 Pod

你能夠在 resource-manifests/sa-frontend-pod.yaml 中找到上述 Pod 的定義。你能夠在終端中進入該文件夾,或在命令行輸入完整的路徑。而後執行以下命令:

kubectl create -f sa-frontend-pod.yaml
pod "sa-frontend" created
複製代碼

能夠經過以下命令確認 Pod:

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
sa-frontend                   1/1       Running   0          7s
複製代碼

若是該 Pod 還處於容器生成中的狀態的話,你能夠在運行命令的時候加入參數 --watch,當 Pod 進入運行狀態的時候,終端會顯示信息。

從外部訪問應用程序

爲了從外部訪問應用程序,咱們須要建立服務類型的Kubernetes資源,具體內容咱們將在後續章節講解,雖然經過服務類型的資源支持外部訪問是更合適的作法,可是此處爲了快速調試,咱們還有另一個辦法,即轉發端口:

kubectl port-forward sa-frontend-pod 88:80
Forwarding from 127.0.0.1:88 -> 80
複製代碼

在瀏覽器中訪問 127.0.0.1:88,便可打開 React 應用程序。

擴大規模的錯誤方法

咱們說過 Kubernetes 的主要特點之一就是伸縮性,爲了證實這一點,讓咱們運行另一個 Pod。咱們經過以下定義建立另一個 Pod 資源:

apiVersion: v1
kind: Pod                                            
metadata:
  name: sa-frontend2      # The only change
spec:                                                
  containers:
    - image: rinormaloku/sentiment-analysis-frontend 
      name: sa-frontend                              
      ports:
        - containerPort: 80
複製代碼

而後,經過以下命令建立新的 Pod:

kubectl create -f sa-frontend-pod2.yaml
pod "sa-frontend2" created
複製代碼

能夠經過以下命令確認第二個 Pod:

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
sa-frontend                   1/1       Running   0          7s
sa-frontend2                  1/1       Running   0          7s
複製代碼

如今咱們有兩個運行中的 Pod。

請注意:這不是最終的解決方案,還有不少缺陷。咱們將在另外一個 Kubernetes 資源的部署一節中改善這個方案。

總結 Pod

提供靜態文件的 Nginx 網絡服務器在另個不一樣的 Pod 內運行。如今咱們有兩個問題:

  • 怎樣對外開放這些服務,讓用戶經過 URL 來訪問它們?
  • 怎樣平衡 Pod 之間的負荷?

Kubernetes 提供了服務類型的資源。在下一節中咱們將詳細介紹。

5、Kubernetes 實踐——服務

Kubernetes 服務資源能夠做爲一組提供相同服務的 Pod 的入口。這個資源肩負發現服務和平衡 Pod 之間負荷的重任,如圖 16 所示。

在 Kubernetes 集羣內,咱們擁有提供不一樣服務的 Pod(前端、Spring 網絡應用和 Flask Python 應用程序)。因此這裏的問題是:服務如何知道該處理哪一個 Pod?例如:它如何生成這些 Pod 的終端列表?

這個問題能夠用標籤來解決,具體分兩個步驟:

  1. 給全部服務處理的對象 Pod 貼上標籤;
  2. 在服務中使用一個選擇器,該選擇器定義了全部貼有標籤的對象 Pod。

下列視圖看起來更清晰:

咱們能夠看到 Pod 都貼着標籤「app: sa-frontend」,服務用這個標籤找到目標 Pod。

標籤

標籤提供了一種簡單的方法用於管理Kubernetes資源。它們有一對鍵值表示,且能夠用於全部資源。按照圖17中的例子,修改清單文件。

在修改完畢後保存文件,並經過以下命令應用這些變動:

kubectl apply -f sa-frontend-pod.yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
pod "sa-frontend" configured
kubectl apply -f sa-frontend-pod2.yaml 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
pod "sa-frontend2" configured
複製代碼

咱們看到了一個警告(在應用的時候,而非建立,明白了)。在第二行咱們看到部署了 pod 「sa-frontend」和 「sa-frontend2」。咱們能夠過濾想要查看的 Pod:

kubectl get pod -l app=sa-frontend
NAME           READY     STATUS    RESTARTS   AGE
sa-frontend    1/1       Running   0          2h
sa-frontend2   1/1       Running   0          2h
複製代碼

驗證帶有標籤的 Pod 的另外一種方法是在上述命令中加入標誌符 --show-labels,那麼結果中會顯示每一個 Pod 的全部標籤。

很好!Pod 已經貼上了標籤,咱們準備好經過服務找到它們了。讓咱們定義 LoadBalancer 類型的服務,如圖 18 所示。

服務的定義

LoadBalancer 服務的 YAML 定義以下所示:

apiVersion: v1
kind: Service              # 1
metadata:
  name: sa-frontend-lb
spec:
  type: LoadBalancer       # 2
  ports:
  - port: 80               # 3
    protocol: TCP          # 4
    targetPort: 80         # 5
  selector:                # 6
    app: sa-frontend       # 7
複製代碼

#1 kind:服務;

#2 type:指定類型,咱們選擇 LoadBalancer,由於咱們想平衡 Pod 之間的負荷;

#3 ports:指定服務獲取請求的端口;

#4 protocol:定義交流;

#5 targetPort:能夠未來訪的請求轉發到這個端口;

#6 selector:包含選擇pod屬性的對象;

#7 app:sa-frontend定義了哪一個是目標 Pod,只有擁有標籤「app: sa-frontend」的纔是目標 Pod。

經過運行以下命令建立服務:

kubectl create -f service-sa-frontend-lb.yaml
service "sa-frontend-lb" created
複製代碼

能夠經過運行以下命令檢查的服務的狀態:

kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
sa-frontend-lb   LoadBalancer   10.101.244.40   <pending>     80:30708/TCP   7m
複製代碼

External-IP 處於 pending 狀態(不用再等了,這個狀態不會變的)。這是由於咱們使用的是 Minikube。若是咱們在 Azure 或 Google 雲服務上運行,那麼咱們能夠獲得一個公開的 IP,那麼全世界均可以訪問咱們的服務了。

儘管如此,Minikube 也不會置咱們於不顧,它提供一個很是有用的本地調試命令,以下所示:

minikube service sa-frontend-lb
Opening kubernetes service default/sa-frontend-lb in default browser...
複製代碼

這能夠在瀏覽器中打開指向該服務的 IP。服務受到請求後,會將請求轉發給其中一個 Pod(不用理會是哪一個)。經過利用服務做爲訪問入口,這種抽象可讓咱們看到並將多個 Pod 當成一個來交互。

服務的總結

在本節中,咱們介紹了給資源貼標籤,在服務中使用標籤做爲選擇器,咱們還定義並建立了一個 LoadBalancer 的服務。這知足了咱們但願伸縮應用程序規模的需求(只需加入新的貼了標籤的 Pod),並經過將服務做爲訪問入口在 Pod 之間作負載均衡。

6、Kubernetes 實踐——部署

Kubernetes 部署能夠幫助每個應用程序的生命都保持相同的一點:那就是變化。此外,只有掛掉的應用程序纔會一塵不變,不然,新的需求會源源不斷地涌現,更多代碼會被開發出來、打包以及部署。這個過程當中的每一步都有可能出錯。

部署資源能夠自動化應用程序從一版本升遷到另外一版本的過程,並保證服務不間斷,若是有意外發生,它可讓咱們迅速回滾到前一個版本。

部署實踐

如今咱們有兩個 Pod 和一個服務開放,並且它們之間有負載均衡(如圖 19 所示)。咱們提到過現有的 Pod 還遠遠不夠完美。須要分開管理每個 Pod(建立、更新、刪除和監視他們的狀況)。快速更新和迅速回滾根本不可能!這樣是不行的,部署 Kubernetes 資源能夠解決這裏的每一個問題。

在繼續下面的內容以前,讓咱們複述下咱們的目標,經過概述可讓咱們更好的理解部署資源的清單文件的定義。咱們想要的是:

  1. 映像 rinormaloku/sentiment-analysis-frontend 的兩個 Pod;
  2. 部署期間服務不間斷;
  3. Pod 貼有標籤 app: sa-frontend,因此咱們能夠經過 sa-frontend-lb 服務找到各個服務。

在下一節中,咱們能夠將這些需求反映到部署的定義中。

部署的定義

以下資源定義的YAML文件能夠達成以上全部提到的點:

apiVersion: extensions/v1beta1
kind: Deployment                                          # 1
metadata:
  name: sa-frontend
spec:
  replicas: 2                                             # 2
  minReadySeconds: 15
  strategy:
    type: RollingUpdate                                   # 3
    rollingUpdate: 
      maxUnavailable: 1                                   # 4
      maxSurge: 1                                         # 5
  template:                                               # 6
    metadata:
      labels:
        app: sa-frontend                                  # 7
    spec:
      containers:
        - image: rinormaloku/sentiment-analysis-frontend
          imagePullPolicy: Always                         # 8
          name: sa-frontend
          ports:
            - containerPort: 80
複製代碼

#1 kind:部署;

#2 replicas:是部署 Spec 對象的一個屬性,定義了咱們想運行多少的 Pod。因此是 2;

#3 type:指定從當前版本升遷到下個版本的時候,部署使用的策略。此處的策略 RollingUpdate 能夠保證部署期間服務不間斷;

#4 maxUnavailable:是 RollingUpdate 對象的一個屬性,定義了在升級的時候,最大容許中止的 Pod 數量(與但願的狀態相比)。對咱們的部署來講,咱們有 2 個副本,這意味着在一個 Pod 中止後,咱們還會有另一個 Pod 運行,因此能夠保證應用程序可訪問;

#5 maxSurge:是 RollingUpdate 對象的另外一個屬性,定義了添加到部署的最大 Pod 數量(與但願的狀態相比)。對咱們的部署來講,這意味着在向新版本遷移的時候,咱們能夠加一個 Pod,那麼咱們能夠同時擁有個 3 個 Pod;

#6 template:指定 Pod 的模板,部署在建立新 Pod 的時候,會用到該模板。極可能這個很是類似的 Pod 會當即吸引你;

#7 app: sa-frontend:根據模板建立的 Pod 將被貼上該標籤;

#8 imagePullPolicy:當設置成 Always 的時候,每一次新部署都會從新獲取容器映像。

坦白來講,這一堆的文本讓我更糊塗了,因此仍是讓咱們來看個例子:

kubectl apply -f sa-frontend-deployment.yaml
deployment "sa-frontend" created
複製代碼

照例讓咱們確認是否一切如約履行了:

kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
sa-frontend                    1/1       Running   0          2d
sa-frontend-5d5987746c-ml6m4   1/1       Running   0          1m
sa-frontend-5d5987746c-mzsgg   1/1       Running   0          1m
sa-frontend2                   1/1       Running   0          2d
複製代碼

如今咱們有 4 個運行中的 Pod,兩個是由部署建立的,而另外兩個是咱們手動建立的。經過 kubectl delete pod 命令刪除其中一個手動建立的 Pod。

練習:刪除其中一個部署建立的 Pod,看看結果怎樣。在閱讀以下的解釋前,請先想一想緣由。

解釋:刪除一個 Pod 後,部署注意到當前的狀態(只有 1 個 Pod 在運行)與但願的狀態(2 個 Pod 處於運行狀態),因此它會再啓動一個 Pod。

那麼,除了保持但願的狀態外,使用部署還有什麼好處?讓咱們先來看看好處。

好處 1:採用零停機時間部署(Zero-downtime)

產品經理帶着新的需求來找咱們,說客戶想要在前端加一個綠色的按鈕。開發者寫好了代碼後,只需提供給咱們同樣必須的東西,容器映像 rinormaloku/sentiment-analysis-frontend:green。而後就該咱們了,咱們須要採用零停機時間部署,這項工做很難嗎?讓咱們試試看!

編輯 deploy-frontend-pods.yaml 文件,將容器映像改成新的映像:rinormaloku/sentiment-analysis-frontend:green。保存變動,並運行以下命令:

kubectl apply -f deploy-frontend-green-pods.yaml --record
deployment "sa-frontend" configured
複製代碼

讓咱們經過以下命令檢查下上線的狀態:

kubectl rollout status deployment sa-frontend
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 of 2 updated replicas are available...
deployment "sa-frontend" successfully rolled out
複製代碼

從部署上看來,上線已經成功。在這個過程當中副本被逐個替換。意味着應用程序始終在線。在繼續下面的內容前,先讓咱們來確認一下更新確實有效。

確認部署

讓咱們在瀏覽器中確認更新的結果。運行咱們以前用到過的命令 minikube service sa-frontend-lb,它會打開瀏覽器。咱們能夠看到按鈕 SEND 已更新了。

「RollingUpdate」背後的狀況

在咱們應用了新的部署後,Kubernetes 會將新狀態與舊的相比。在咱們的例子中,新狀態須要兩個 rinormaloku/sentiment-analysis-frontend:green 映像的 Pod。這與當前的運行狀態不一樣,因此 Kubernetes 會執行 RollingUpdate。

這裏的 RollingUpdate 會根據咱們指定的規格執行,也就是「maxUnavailable: 1″和「maxSurge: 1″。這意味着部署須要終止一個 Pod,而且僅能夠運行一個新的 Pod。這個過程會不斷重複,一直到全部的 Pod被替換(如圖 21 所示)。

咱們繼續介紹第二個好處。

聲明:出於娛樂的目的,下面的部分我按照小說的形式來書寫。

好處2:回滾到前一個狀態

產品經理跑進辦公室說,他遇到一個大麻煩!

產品經理大喊道:「產品環境中的應用程序有一個很關鍵的 bug!!須要立刻回滾到前一個版本」。

你冷靜地看着他,眼睛都沒有眨一下,就轉向了心愛的終端,而後開始敲:

kubectl rollout history deployment sa-frontend
deployments "sa-frontend"
REVISION  CHANGE-CAUSE
1         <none>         
2         kubectl.exe apply --filename=sa-frontend-deployment-green.yaml --record=true
複製代碼

你看了一眼前一個部署,而後問產品經理:「上個版本不少 bug,那前一個版本運行得很完美嗎?」

產品經理吼道:「是啊,你沒聽見我說嘛?!」

你沒理他,你知道該如何處理,因而你開始敲:

kubectl rollout undo deployment sa-frontend --to-revision=1
deployment "sa-frontend" rolled back
複製代碼

而後,你輕輕地刷新了頁面,以前的修改全都不見了!

產品經理瞠目結舌地看着你。

你拯救了你們!

我知道……這是個很無聊的故事。在 Kubernetes 出現以前,這個故事挺好的,更加戲劇化,讓人高度緊張,並且這種狀態持續了很長時間。那段舊時光仍是很美好的!

大多數的命令都自帶說明,只是有一些細節你須要本身搞清楚。爲何第一個版本中字段 CHANGE-CAUSE 的值爲 ,而同時第二次改版的時候,CHANGE-CAUSE 的值爲「kubectl.exe apply –filename=sa-frontend-deployment-green.yaml –record=true」。

你應該能夠發現這是由於在應用新的映像的時候,咱們用到了標誌符 --record。

在下一節中,咱們將使用以前全部的概念,完成整個架構。

7、Kubernetes 和其餘一切的實戰應用

如今咱們學習了完成架構的全部必須的資源,所以這一節會很是快。圖 22 中灰色的部分是須要作的事情。讓咱們從底部開始:部署 sa-logic 的部署。

部署 SA-Logic

在終端中進入資源清單文件所在的目錄,而後運行以下命令:

kubectl apply -f sa-logic-deployment.yaml --record
deployment "sa-logic" created
複製代碼

SA-Logic 的部署會建立三個 Pod(Pod 上運行着咱們的 Python 應用)。該命令還會給Pod 貼上 app: sa-logic 的標籤。有了這個標籤,咱們就能從 SA-Logic 服務中利用選擇器來選擇這些 Pod。請花點時間打開 sa-logic-deployment.yaml,查看其內容。

這裏的概念都是同樣的,所以咱們能夠直接講解下一個資源:SA-Logic 服務。

SA Logic 服務

首先來解釋下爲何須要該服務。咱們的 Java 應用(在 SA-WebApp 部署的 Pod 中運行)依賴於 Python 應用提供的情感分析。但如今,與咱們在本地運行一切服務時的情況不一樣,咱們並無一個單一的 Python 應用監聽着某個端口,咱們只有兩個 Pod,若是須要,咱們能夠有更多的 Pod。

這就是爲何須要「服務」爲一組提供相同功能的 Pod 提供訪問入口。這就是說,咱們能夠利用 SA-Logic 服務做爲全部 SA-Logic Pod 的訪問入口。

運行以下命令:

kubectl apply -f service-sa-logic.yaml
service "sa-logic" created
複製代碼

更新後的應用程序狀態:如今咱們有兩個 Pod 在運行(包含 Python 應用程序),而且 SA-Logic 服務提供了訪問入口,該訪問入口將在 SA-WebApp 的 Pod 中使用。

如今須要部署 SA-WebApp Pod,咱們須要用到部署資源。

SA-WebApp 部署

咱們已經學過了部署,儘管這個部署會用到更多的特性。打開 sa-web-app-deployment.yaml 文件,會發現如下的新內容:

- image: rinormaloku/sentiment-analysis-web-app
  imagePullPolicy: Always
  name: sa-web-app
  env:
    - name: SA_LOGIC_API_URL
      value: "http://sa-logic"
  ports:
    - containerPort: 8080
複製代碼

咱們感興趣的第一件事就是 env 屬性。咱們猜想它定義了環境變量 SA_LOGIC_API_URl,值爲在 Pod 內的值爲 http://sa-logic。但爲何要初始化成 http://sa-logic,sa-logic 到底是什麼?

咱們先來介紹下 kube-dns。

KUBE-DNS

Kubernetes 有個特殊的 Pod 叫作 kube-dns。默認狀況下,全部 Pod 都用它做爲 DNS 服務器。kube-dns 的一個重要屬性就是它爲每一個創建的訪問都建立一條 DNS 記錄。

這就是說當咱們建立 sa-logic 服務時,它會得到一個 IP 地址。它的名字會加入到 kube-dns 中(和它的 IP 地址一塊兒)。這樣全部 Pod 都可以把 sa-logic 翻譯成 SA-Logic 服務的 IP 地址。

好,如今能夠繼續了:

SA WebApp 部署(續)

運行如下命令:

kubectl apply -f sa-web-app-deployment.yaml --record
deployment "sa-web-app" created
複製代碼

完了。剩下的工做就是經過 LoadBalancer 服務將 SA-WebApp Pod 暴露到外部。LoadBalancer 服務提供了 SA-WebApp Pod 的訪問入口,這樣 React 應用程序就能發送 HTTP 請求了。

SA-WebApp 服務

打開 service-sa-web-app-lb.yaml 文件,能夠看到內容仍是挺熟悉的。

因此咱們能夠運行以下命令:

kubectl apply -f service-sa-web-app-lb.yaml
service "sa-web-app-lb" created
複製代碼

這樣架構就完成了。但還有一點不完美的地方。在部署 SA-Frontend Pod 以後,容器映像指向了 http://localhost:8080/sentiment 處的 SA-WebApp。但如今咱們須要將其更新爲 SA-WebApp LoadBalancer 的 IP 地址(其做用是 SA-WebApp Pod 的訪問入口)。

修補該不完美是個快速複習一切的絕佳機會(若是能不參照如下的指南獨立完成更好)。下面咱們開始:

  1. 執行下列命令獲取 SA-WebApp LoadBalancer 的 IP:
minikube service list
|-------------|----------------------|-----------------------------|
|  NAMESPACE  |         NAME         |             URL             |
|-------------|----------------------|-----------------------------|
| default     | kubernetes           | No node port                |
| default     | sa-frontend-lb       | http://192.168.99.100:30708 |
| default     | sa-logic             | No node port                |
| default     | sa-web-app-lb        | http://192.168.99.100:31691 |
| kube-system | kube-dns             | No node port                |
| kube-system | kubernetes-dashboard | http://192.168.99.100:30000 |
|-------------|----------------------|-----------------------------|
複製代碼
  1. 在 sa-frontend/src/App.js 中使用 SA-WebApp LoadBalancer 的 IP,以下:
analyzeSentence() {
        fetch('http://192.168.99.100:31691/sentiment', { /* shortened for brevity */})
            .then(response => response.json())
            .then(data => this.setState(data));
    }
複製代碼
  1. 構建靜態文件 npm build (須要先切換到 sa-front-end 目錄);

  2. 構建容器映像:

    docker build -f Dockerfile -t $DOCKER_USER_ID/sentiment-analysis-frontend:minikube .

  3. 將映像推送到 Docker hub:

    docker push $DOCKER_USER_ID/sentiment-analysis-frontend:minikube

  4. 編輯 sa-frontend-deployment.yaml 並使用新的映像;

  5. 執行 kubectl apply -f sa-frontend-deployment.yaml 命令。

刷新瀏覽器(若是你關閉了瀏覽器,則執行 minikube service sa-frontend-lb)。敲個句子試試看!

8、全文總結

Kubernetes 對團隊、項目都頗有好處,它能簡化部署,提供伸縮性、靈活性,可讓咱們使用任何底層基礎設施。之後咱們叫它 Supernetes 吧!

本文中覆蓋的內容:

  • 構建/打包/運行 ReactJS、Java 和 Python 應用程序;
  • Docker容器,如何利用 Dockerfile 定義並構建容器;
  • 容器註冊目錄,咱們採用 Docker Hub 做爲容器的代碼庫;
  • 介紹了 Kubernetes 的最重要的內容;
  • Pod;
  • 服務;
  • 部署;
  • 新概念,如零停機時間部署;
  • 建立可伸縮的應用;
  • 流程上,咱們將整個微服務應用程序轉成了 Kubernetes 集羣。

歡迎關注公衆號:非著名開發者,獲取更多精彩內容。

ok_developer
相關文章
相關標籤/搜索