kubernetes高階之建立只讀檔案系統以及只讀asp.net core容器

周國通發表於2019-06-24

系列目錄

使用docker建立只讀檔案系統

容器化部署對應用的運維帶來了極大的方便,同時也帶來一些新的安全問題需要考慮.比如黑客入侵到容器內,對容器內的系統級別或者應用級別檔案進行修改,會造成難以估量的損失.(比如修改hosts檔案導致dns解析異常,修改web資源導致網站被嵌入廣告,後端邏輯被更改導致許可權驗證失效等,由於是分散式部署,哪些容器內的資源被修改也很難以發現).解決這個問題的辦法就是建立建立一個具有隻讀檔案系統的容器.下面介紹使用docker run命令和docker compose來建立具有隻讀檔案系統的容器.

使用docker run命令建立只讀檔案系統

比如說要建立一個只讀檔案系統的redis容器,可以執行以下命令

docker run --read-only redis

docker compose/swarm建立只讀檔案系統

yaml編排檔案示例如下

version: '3.3'
 
services:
  redis:
    image: redis:4.0.1-alpine
    networks:
      - myoverlay
    read_only: true

networks:
  myoverlay:

問題:建立只讀檔案系統看起來很不錯,但是實際上往往會有各種各樣的問題,比如很多應用要寫temp檔案或者寫日誌檔案,如果對這樣的應用建立只讀容器則很可能導致應用無法正常啟動.對於需要往固定位置寫入日誌或者臨時檔案的應用,可以掛載宿主機的儲存卷,雖然容器是隻讀的,但是掛載的盤仍然是可讀寫的.

建立只讀的asp.net core容器

上面一節我們講到了建立容器只讀檔案系統以增加安全性,以及如何解決需要寫入日誌檔案或者臨時檔案這樣常見的問題.我們嘗試建立一個只讀的asp.net應用時,即便不使用任何log元件(即不寫入日誌),仍然無法正常啟動映象.解決這個問題其實也非常簡單,只需要把環境變數COMPlus_EnableDiagnostics的值設定為0即可.

FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 52193

FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY . .
WORKDIR "/src"
RUN dotnet build "ReadOnlyTest.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "ReadOnlyTest.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
ENV DOTNET_RUNNING_IN_CONTAINER=true
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1

ENV COMPlus_EnableDiagnostics=0

COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ReadOnlyTest.dll"]

我們對這些環境變數進行簡單介紹

  • DOTNET_RUNNING_IN_CONTAINER值設定為true時則表示應用執行在容器內,方便我們獲取程式的執行環境,然後根據環境做出不同決策(比如單元測試的時候,可能要根據專案是執行在windows,linux或者linux容器做出不同的測試策略).當然,你也可以設定其它的環境變數來方便自己使用,比如你鍵名稱設定為IsRunningInDocker,但是DOTNET_RUNNING_IN_CONTAINER

  • DOTNET_CLI_TELEMETRY_OPTOUT是否輸出遙測資訊,如果設定為1則是關閉,這樣dotnet.exe就不會向除錯視窗輸出遙測資訊.

  • COMPlus_EnableDiagnostics目前沒有找到太多關於這個引數的詳細資訊,只是查閱資源發現這開啟這項配置可以建立只讀許可權 aspnet 應用程式.

微軟官方基礎映象裡還包含一項名稱叫作ASPNETCORE_VERSION的環境變數,我們可以直接讀取它,這樣使用公共的環境變數一來避免息手動設定和更新的麻煩,二來便於和社群交流(自己定義約束的只能用於內部團隊交流)

我們如何使用這些環境變數呢,其它可以在程式裡面暴露一個helper方法,比如

private bool InDocker { get { return Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true";} }

這樣我們就可以根據實際的需求來使用它.

上面我們介紹瞭如何使用docker run命令以及docker-compose建立只讀檔案系統.然而在kubernetes叢集裡,我們需要使用k8s的編排方法來建立只讀檔案系統.那麼在k8s裡如何建立只讀檔案系統.其實這裡涉及到了另一個高階主題:那就是k8s的安全策略(Pod Security Policies)我們將在下一節介紹它.

相關文章