Kubernetes、OpenShift等等究竟是什麼,幹什麼,怎麼用?來一探究竟(一)

Kubernetes、OpenShift等等究竟是什麼,幹什麼,怎麼用?來一探究竟(一)

來自專欄 Kubernetes指南13 人贊了文章

本文的第五章——在OpenShift上部署響應式微服務中,提到了一些開發工具,按照出現的順序依次是OpenShift、Kubernetes、Docker、MiniShift、Fabric8 Maven插件等。對於一個沒有過微服務實踐經驗的小白來說,順著這篇文章繼續下去雖然並無不可,但難免溝溝坎坎,一頭霧水。所幸先把這些東西的概念、作用和使用方法摸摸底,擺脫小白的苦惱。讓我們開始吧。


Kubernetes(一)

Production-Grade Container Orchestration?

kubernetes.io圖標

進入Kubernetes官網,首先映入眼帘的就是幾個大字——Production-Grade Container Orchestration(生產級容器編排),然後是一行小字Automated container deployment, scaling, and management(自動化容器部署、擴展和管理)。那麼我們一下就大致明白了這東西的作用,就是用來搞容器化應用的嘛。看到這不妨先打個岔,因為提到了容器化應用,我們不得不先說說Docker這個東西。


Docker

Docker?

www.docker.com圖標

打開Docker的官網,點擊什麼是Docker,首先看到的又是一個看似吹逼的介紹——Docker is the worlds leading software containerization platform(Docker是一個世界領先的軟體容器平台)。接著點進Docker文檔頁面,我們又看到另一句話——Docker provides a way to run applications securely isolated in a container, packaged with all its dependencies and libraries(Docker提供了一種在容器中安全運行應用的方法,它會將應用所需的所有依賴和庫打包在一起)。OK,看起來和文章之前提到的fat jar有些類似。感覺這東西還不錯,怎麼用呢?在第五章中譯者也只是在自己的Mac中安裝了Docker軟體,並沒有什麼操作,就可以成功執行命令

mvn fabric8:deploy -Popenshift

將應用打包並部署到OpenShift中去。雖然這種工具能用就好,不過還是看看文檔稍微深入研究一下。Docker的官方教程一共分為6個部分,分別是:

  1. 設置Docker的運行環境
  2. 構建一個映像(image)並將其作為一個容器來運行
  3. 擴展你的應用來運行多個容器
  4. 在集群中分散式運行你的應用
  5. 添加後端資料庫來堆疊服務
  6. 將應用部署到生產環境

我想這部分我只簡單說一下前兩個,剩下的具體實踐請查看官方教程:

Get Started, Part 1: Orientation and setup?

docs.docker.com圖標

Docker是一個供開發者和系統管理員使用容器開發、部署與運行應用的平台。使用Linux容器來部署應用叫做容器化。容器本身並不新鮮,但是使用容器來簡化應用的部署是最近才有的事。容器化之所以變得越來越流行,是因為它具有靈活性、輕量級、可交換、可移動、可擴展和可堆疊等特性。

圖片來源:Docker官網

鏡像(images)和容器(containers)

容器通過運行一個鏡像來啟動。鏡像是一個可執行程序包,包含有運行應用程序所需的所有內容——包括代碼、運行時、庫、環境變數和配置文件。容器是一個鏡像的運行時實例——鏡像運行時在內存中的部分(具有狀態或者用戶進程的鏡像)。你可以像在Linux中一樣,通過執行命令

docker ps

來查看運行中的容器列表。

容器(containers)和虛擬機(virtual machines)

容器在Linux中本地運行,並與其它容器共享主機的內核。它運行一個獨立進程而佔用較少的內存,從而具有輕量化的特徵。相比之下,虛擬機(VM)運行一個完整的「客人」操作系統,通過虛擬機處理程序來虛擬訪問主機資源。一般來說,虛擬機會提供一個具有較多資源的環境,完全滿足大多數應用的需求。

容器和虛擬機


使用Docker容器編寫和運行APP

在安裝好Docker之後,我們首先以Python為例,嘗試使用Docker編寫並運行一個小程序。

在Docker之前,我們編寫程序時必須配置開發環境,同時還要保證生產環境的配置與開發環境配置完全相同,才能保證程序的正確運行,往往會造成一些不必要的麻煩。

通過使用Docker,我們可以將程序和它的運行環境整個提取出來成為一個鏡像文件(image),保證程序的正常運行。這些鏡像文件需要使用dockerfile文件來定義。

使用Dockerfile定義容器

dockerfile文件規定了容器中包含的環境。在此環境中對系統資源的訪問是虛擬的,與操作系統相分離。所以你需要將埠映射到容器的外部環境中,同時明確你需要將哪些文件包含到這個環境中來。看起來比較麻煩,但是在完成好這些之後,你就可以保證在這個環境中開發和編譯的程序可以在其他系統中正常運行了。

實踐一下

創建一個空文件夾,新建一個文件,命名為Dockerfile,寫入以下內容並保存。注意閱讀裡面的注釋部分。

# Use an official Python runtime as a parent imageFROM python:2.7-slim# Set the working directory to /appWORKDIR /app# Copy the current directory contents into the container at /appADD . /app# Install any needed packages specified in requirements.txtRUN pip install --trusted-host pypi.python.org -r requirements.txt# Make port 80 available to the world outside this containerEXPOSE 80# Define environment variableENV NAME World# Run app.py when the container launchesCMD ["python", "app.py"]

還需要兩個文件,一個是app.py,一個是requirments.txt

requirements.txt

FlaskRedis

app.py

from flask import Flaskfrom redis import Redis, RedisErrorimport osimport socket# Connect to Redisredis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)app = Flask(__name__)@app.route("/")def hello(): try: visits = redis.incr("counter") except RedisError: visits = "<i>cannot connect to Redis, counter disabled</i>" html = "<h3>Hello {name}!</h3>" "<b>Hostname:</b> {hostname}<br/>" "<b>Visits:</b> {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)if __name__ == "__main__": app.run(host=0.0.0.0, port=80)

放在同一個路徑下,進入該路徑,命令行執行:

sudo docker build -t friendlyhello .

你會看到

> example sudo docker build -t friendlyhello .Password:Sending build context to Docker daemon 4.608kBStep 1/7 : FROM python:2.7-slim ---> 46ba956c5967Step 2/7 : WORKDIR /app ---> Using cache ---> 2cbb6e08c67bStep 3/7 : ADD . /app ---> Using cache ---> 76f6dde62a64Step 4/7 : RUN pip install --trusted-host pypi.python.org -r requirements.txt ---> Running in a9a37271c155Collecting Flask (from -r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB)Collecting Redis (from -r requirements.txt (line 2)) Downloading https://files.pythonhosted.org/packages/3b/f6/7a76333cf0b9251ecf49efff635015171843d9b977e4ffcf59f9c4428052/redis-2.10.6-py2.py3-none-any.whl (64kB)Collecting Werkzeug>=0.14 (from Flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)Collecting click>=5.1 (from Flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl (71kB)Collecting Jinja2>=2.10 (from Flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)Collecting itsdangerous>=0.24 (from Flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB)Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->Flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gzBuilding wheels for collected packages: itsdangerous, MarkupSafe Running setup.py bdist_wheel for itsdangerous: started Running setup.py bdist_wheel for itsdangerous: finished with status done Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5 Running setup.py bdist_wheel for MarkupSafe: started Running setup.py bdist_wheel for MarkupSafe: finished with status done Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46Successfully built itsdangerous MarkupSafeInstalling collected packages: Werkzeug, click, MarkupSafe, Jinja2, itsdangerous, Flask, RedisSuccessfully installed Flask-1.0.2 Jinja2-2.10 MarkupSafe-1.0 Redis-2.10.6 Werkzeug-0.14.1 click-6.7 itsdangerous-0.24Removing intermediate container a9a37271c155 ---> 497b82c67188Step 5/7 : EXPOSE 80 ---> Running in d1c71a9a13b9Removing intermediate container d1c71a9a13b9 ---> 5f57f818576aStep 6/7 : ENV NAME World ---> Running in 937116ea617dRemoving intermediate container 937116ea617d ---> 1c85580934f4Step 7/7 : CMD ["python", "app.py"] ---> Running in e940ced2e729Removing intermediate container e940ced2e729 ---> 921b0bfc5176Successfully built 921b0bfc5176Successfully tagged friendlyhello:latest> example

這時我們的image已經創建好了,位於本機的docker鏡像註冊表中。

? example docker image lsREPOSITORY TAG IMAGE ID CREATED SIZEfriendlyhello latest 921b0bfc5176 2 minutes ago 151MBpython 2.7-slim 46ba956c5967 3 weeks ago 140MBhello-world latest e38bc07ac18e 6 weeks ago 1.85kB

運行app

運行程序,使用參數-p將你的計算機的4000埠映射到容器中的80埠:

docker run -p 4000:80 friendlyhello

瀏覽器訪問localhost:4000/

按Ctrl + c退出。

然後以隔離狀態後台運行:

docker run -d -p 4000:80 friendlyhello

此時這個容器就在後台開始運行了。你可以查看它們:

$ docker container lsCONTAINER ID IMAGE COMMAND CREATED1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago

也可以停止運行對應ID的容器:

$ docker container stop 1fa4ab2cf395

你也可以分享你的image,首先需要註冊一個Docker ID,然後在你的本機上登錄:

$ docker login

在docker hub中將你的鏡像文件打上標記:

$ docker tag image username/repository:tag

username是你的用戶名,repository和tag自取,代表鏡像的位置和標籤。例如:

$ docker tag friendlyhello john/get-started:part2

獲取鏡像文件列表:

$ docker image lsREPOSITORY TAG IMAGE ID CREATED SIZEfriendlyhello latest d9e555c53008 3 minutes ago 195MBjohn/get-started part2 d9e555c53008 3 minutes ago 195MBpython 2.7-slim 1c7128a655f6 5 days ago 183MB...

公開鏡像文件:

$ docker push username/repository:tag

執行完成之後,你可以登錄docker hub,就會看到一個新的鏡像文件躺在那裡了。

遠程運行鏡像文件:

$ docker run -p 4000:80 username/repository:tag

如果本地機器上沒有該鏡像,就會從遠程下載:

$ docker run -p 4000:80 john/get-started:part2Unable to find image john/get-started:part2 locallypart2: Pulling from john/get-started10a267c67f42: Already existsf68a39a6a5e4: Already exists9beaffc0cf19: Already exists3c1fe835fb6b: Already exists4c9f1fa8fcb8: Already existsee7d8f576a14: Already existsfbccdcced46e: Already existsDigest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068Status: Downloaded newer image for john/get-started:part2 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

從此以後,無論你在哪裡執行 docker run 命令,你的代碼都會和配置好的環境一起愉快地運行下去了。


介紹這些東西所需要的內容比我想的要多得多,而Docker官方文檔的接下來的部分與容器的編排有關,這點與Kubernetes的功能有所重合。所以關於Docker的內容我會另開一個專題來進一步學習。下一篇文章我們繼續Kubernetes和OpenShift的脈絡前進吧。


推薦閱讀:

Docker - 通往新世界的大門
Dockerfile實踐
Serverless Kubernetes 快速入門指南

TAG:Kubernetes | Docker | OpenShift |