寫在前面
隨着微服務架構的流行,日志也需要由專門的分布式日志組件來完成這個工作,我們項目使用的是 ExceptionLess 這個組件,它是前后端分離的;這篇文章我們就來實踐容器化 ExceptionLess 的前端,並為其包含一個 nginx 的宿主,形成一個能夠獨立運行的、自包含的環境,這樣當我們使用k8s集群的時候,就可以使用這個開箱即用的鏡像,任意伸縮,滾動更新,按需擴容等等。
ExceptionLess UI 是使用Angular開發的一個純前端 Web UI,首先我們需要安裝環境(git、npm、bower、grunt etc.),請參考詳細步驟。安裝完成后,使用 grunt 發布項目,這樣一個純靜態的前端網站就生成了;然后將剛剛生成的所有靜態文件以tar.gz格式壓縮成歸檔文件,如 exceptionless.ui.gkb.tar.gz。
構造鏡像
原理
一個Linux版本的鏡像,本質上就是帶有某種環境的Linux系統。比如鏡像nginx:1.13.12,就是安裝了nginx 1.13.12 的linux系統,然后打包成的一個鏡像。理解了鏡像的本質,我們就可以從零構造一個帶有指定配置的、任意版本的nginx鏡像(其實,我們接下來就是要在做這件事情)。
同理,現在我們需要將包含靜態文件的純前端,宿主到一個web服務器,和傳統的方法是一樣的,先安裝一個web服務器,然后將其作為靜態資源的宿主。不同的是,當我們用容器化的思想來做這件事情時候,把所有的流程編排進Dockerfile即可,就是這么簡單。
綜上所述,構建鏡像就是構建一個帶有某種環境的Linux系統,只是我們將傳統安裝環境的步驟編排進Dockerfile而已。
示例說明
我已經使用k8s部署了一個nginx 1.13.12環境,現在以交互模式進入容器:
kubectl -n k8s-ecoysystem-apps exec -it nginx-deployment-6c45fc49cb-zdlfb /bin/bash

看到了嗎,這就一個安裝了nginx 1.13.12的linux環境。
如何編寫Dockerfile?
引導
其實,當我們安裝完成nginx時,它已經配置好了一個靜態資源的例子,如下:

所以我們可以通過瀏覽器,訪問到如下的界面:

這個界面就是靜態文件/usr/share/nginx/html/index.html被瀏覽器渲染的效果。
編排步驟
把部署靜態資源的步驟編排進Dockerfile(這個步驟也可以從零構建FROM SCRATCH,條條道路通羅馬,大家下去自己實戰)
FROM nginx:1.13.12
MAINTAINER justmine
WORKDIR /usr/share/nginx/html
ADD ["exceptionless.ui.tar.gz","."]
- FROM nginx:1.13.12 從一個帶有
nginx:1.13.12環境的linux開始構建 - MAINTAINER justmine 說明作者
- WORKDIR /usr/share/nginx/html 設置工作目錄
- ADD ["exceptionless.ui.tar.gz","."] 將靜態資源拷貝到
nginx宿主對外提供靜態資源的目錄下。這里也可以使用copy命令來完成,但是需要我們提前解壓好歸檔文件。
注意:WORKDIR工作目錄指的是當前命令執行的工作目錄,所以
ADD第二個參數直接用點(.)代替即可,這樣操作起來相對來說比較便利。但是ADD第一個參數的工作目錄和這個沒有關系,指的是docker build時傳遞的工作目錄,所以需要注意,如果在傳遞的目錄下,找不到這個歸檔文件,最后一步生成鏡像就會報錯Forbidden path outside of the build context。
Dockerfile生成鏡像並上傳到DockerHub
docker build -t justmine/nginx-hosted-exceptionless-ui:1.0 .
docker push justmine/nginx-hosted-exceptionless-ui:1.0
千萬注意
docker build最后的一個點(.),這是歸檔文件的上下文目錄。

k8s集群
deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hosted-exceptionless-ui
namespace: k8s-ecoysystem-apps
spec:
replicas: 1
selector:
matchLabels:
app: nginx-hosted-exceptionless-ui
template:
metadata:
labels:
app: nginx-hosted-exceptionless-ui
spec:
containers:
- image: justmine/nginx-hosted-exceptionless-ui:1.0
imagePullPolicy: Always
name: nginx-hosted-exceptionless-ui
ports:
- containerPort: 80
protocol: TCP
service.yml
apiVersion: v1
kind: Service
metadata:
name: nginx-hosted-exceptionless-ui
namespace: k8s-ecoysystem-apps
spec:
type: NodePort
selector:
app: nginx-hosted-exceptionless-ui
ports:
- nodePort: 32003
port: 80
targetPort: 80

瀏覽器(firefox)查看效果

日志

總結
本篇分析了鏡像的本質,鏡像的構建原理,並一步一步地引導大家容器化一個開箱即用的純前端UI,這也是微服務架構實行前后端分離后,容器化前端的一個典型例子。可以說容器化后,使用k8s就可以為所欲為,真正的讓k8s成為微服務應用平台的一大利器啊。這也是我在容器化微服務路上,落實的一個案例,希望分享給大家,更希望把整個思緒過程分享給大家。
項目參考:https://github.com/justmine66/k8s.ecoysystem.apps/tree/master/k8s/ExceptionLess
附言
上次詳解k8s零停機滾動發布微服務后,社區群里有人希望這周趕緊寫金絲雀部署,這里說聲抱歉,由於我們自己的微服務項目也需要與k8s結合,所以,需要先解決實際工作中急切遇到的一些問題。后面會抽時間完成金絲雀部署實踐,請繼續關注。
如果你覺得本篇文章對您有幫助的話,感謝您的【推薦】,這將成為我繼續寫作的動力。
如果你對 kubernets 和 dotnet 感興趣的話可以關注我,我會定期的在博客分享我的學習心得。
我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=2ijrp0ik104ko
