Openshift上的S2I和應用容器化方法:Openshift開發系列第一篇

在Openshift上部署應用php

oc new-app 命令可經過單個 URL 參數(最簡單的形式)指向 Git 存儲庫或容器鏡像。它會訪問這個 URL,以肯定如今是否要解釋該參數並執行構建或部署。oc new-app 命令作出的決定可能與您的指望不符。例如:若是 Git 存儲庫同時包含 Dockerfile 和 index.php 文件,那麼該存儲庫會被用做 Dockerfile 構建仍是 PHP S2I 構建的輸入?若是 Git 存儲庫包含以 PHP 爲目標的源代碼,並且您的 OpenShift 集羣包含適用於 PHP 5.6 和 7.0 的 S2I 構建器鏡像,則應使用哪一個版本?
爲了應對上述和其餘狀況,oc new-app 命令提供了不少選項:html

圖片

oc new-app 命令建立的資源oc new-app 命令可向當前項目添加如下資源,以支持構建和部署應用:node

  • 用於從源代碼或 Dockerfile 構建應用容器鏡像的構建配置。python

  • 指向內部註冊表中的已生成鏡像或指向外部註冊表中的現有鏡像的鏡像流。git

  • 會使用鏡像流做爲輸入來建立應用 Pod 的部署配置。github

  • 適用於應用容器鏡像已公開的全部端口的服務。若是應用容器鏡像沒有聲明任何公開端口,則不會建立任何服務。docker

試驗1:使用S2I部署應用

這個應用以 JavaScript 編寫,且使用 Node.js 運行時。它是一個基於 Express 框架的「hello, world」應用。express

您應根據如下要求構建應用並將其部署至 OpenShift 集羣:apache

  • 用於 OpenShift 的應用名爲 hello。該應用應該能從如下位置訪問:http://hello.apps.lab.example.com。npm

  • 包含應用源的 Git 存儲庫爲:http://services.lab.example.com/nodejs-helloworld。

  • 構建應用所需的 Npm 模塊可從如下位置獲取:http://services.lab.example.com:8081/nexus/content/groups/nodejs。

  • 使用 npm_config_registry 環境變量將這一信息傳輸至 Node.js 的 S2I 構建器鏡像。

  • python -m json.tool filename.json 命令可用於識別 JSON 文件中的語法錯誤。

[student@workstation ~]$ oc new-app --name hello \ --build-env npm_config_registry=\http://services.lab.example.com:8081/nexus/content/groups/nodejs \ http://services.lab.example.com/nodejs-helloworld

使用 npm_config_registry 環境變量將這一信息傳輸至 Node.js 的 S2I 構建器鏡像

包含應用源的 Git 存儲庫爲:http://services.lab.example.com/nodejs-helloworld。構建應用所需的 Npm 模塊可從如下位置獲取:http://services.lab.example.com:8081/nexus/content/groups/nodejs。使用 npm_config_registry 環境變量將這一信息傳輸至 Node.js 的 S2I 構建器鏡像。

Node.js 構建器鏡像不會指出 package.json 源文件中的具體錯誤位置。

將應用源克隆到 student 用戶的主文件夾:

使用文本編輯器打開 package.json 源文件,並查找語法錯誤。如下列出的部份內容顯示 "express" 密鑰後面缺乏冒號 (:):

圖片
圖片

公開應用供外部訪問:
圖片

使用 curl 命令嚮應用發送 HTTP 請求。它應該會返回「hello, world」消息:

圖片

應用容器化方法

OpenShift 中的基本部署單元是 container image 或僅 image。容器鏡像由應用以及運行應用所需的全部依賴關係(共享庫、運行時環境、解釋器等)組成。根據您計劃在 OpenShift 集羣上部署和運行的應用類型來建立容器鏡像的多種方法:

  1. 容器鏡像:在 OpenShift 外部構建的容器鏡像能夠直接部署在 OpenShift 集羣上。在您已將應用打包爲容器鏡像的狀況下,此方法頗有用。若是第三方供應商已向您提供了通過認證且受支持的容器鏡像,則也可以使用此方法。您能夠將第三方供應商構建的鏡像部署至 OpenShift 集羣。

  2. Dockerfile:在某些狀況下,您會得到用於構建應用容器鏡像的 Dockerfile。在這種狀況下,您還可考慮使用其餘選項:

  • 您能夠對該 Dockerfile 進行自定義,構建新的鏡像以知足您的應用需求。若是更改幅度不大,並且您不想在鏡像中添加過多的層,則建議使用此選項。

  • 您可使用提供的容器鏡像做爲父級建立新的 Dockerfile,並自定義基本鏡像以知足您的應用需求。若是要建立具備更多自定義項的新子鏡像,而且從父鏡像繼承圖層,則建議使用此選項。

  1. Source-to-Image (S2I) 構建器鏡像:S2I 構建器鏡像包含基礎操做系統庫、編譯器和解釋器、運行時、框架和 Source-to-Image 工具。使用此方法構建應用時,OpenShift 將應用源代碼和構建器鏡像結合,以建立可在 OpenShift 集羣上部署的可當即運行的容器鏡像。對於開發人員而言,此方法具備多個優勢,這也是在 OpenShift 集羣上構建新應用以供部署的首選方式。

根據您的應用需求,您能夠經過多種方式來使用 S2I 構建器鏡像:紅帽提供了多種受支持的 S2I 構建器鏡像,以用於構建各種應用。紅帽建議您儘可能使用標準 S2I 構建器鏡像。S2I 構建器鏡像與普通容器鏡像相似,但前者包含額外的元數據、腳本和工具。您可使用 Dockerfiles 基於紅帽提供的父構建器鏡像來建立子鏡像。若是紅帽提供的 S2I 構建器鏡像都不符合您的應用需求,則您能夠構建本身的自定義 S2I 構建器鏡像。

S2I 構建器鏡像S2I 構建器鏡像是一種特殊形式的容器鏡像,它會生成並輸出應用容器鏡像。構建器鏡像包含應用所基於的基礎操做系統庫、語言運行時、框架和庫,以及各類 Source-to-Image 工具和實用程序。例如,若是想要部署到 OpenShift 的應用是用 PHP 編寫的,則可以使用 PHP 構建器鏡像來生成應用容器鏡像。您要提供存儲應用源代碼的 Git 存儲庫的位置,而後 OpenShift 會將該源代碼與基礎構建器鏡像進行整合,以生成要部署到 OpenShift 的容器鏡像。所生成的應用容器鏡像包含某一版本的紅帽企業 Linux、一個 PHP 運行時和相應的應用。構建器鏡像是一種很是便捷的機制。採用該機制時,無需建立 Dockerfile,便可輕鬆快速地從代碼生成可運行的容器。

使用容器鏡像雖然 Source-to-Image 構建是構建應用並將其部署至 OpenShift 的首選方式,但在某些狀況下您須要部署外部構建的應用。例如,某些供應商會提供已通過全面認證且可直接運行的受支持容器鏡像。在這種狀況下,OpenShift 支持部署預構建的容器鏡像。oc new-app 命令能夠提供多種靈活方式,以向 OpenShift 集羣部署容器鏡像。最簡單的方法就是,經過公共註冊表(如 docker.io)或私有註冊表(您所在企業內部託管的註冊表)獲取預構建的 docker 鏡像,而後向 oc new-app 命令提供該鏡像的位置。接着,OpenShift 會提取該鏡像並將其部署至 OpenShift 集羣,就像部署在 OpenShift 中構建的任何其餘鏡像同樣。

建立 S2I 構建器鏡像

S2I 構建器鏡像可經過多種選項來建立:

從頭開始建立您本身的 S2I 構建器鏡像。若是您的應用沒法使用 S2I 構建器鏡像按原樣提供的 RHCC,則可構建自定義 S2I 構建器鏡像,以經過自定義構建流程來知足您的應用需求。

OpenShift 提供了 s2i 命令行工具,幫助您啓動用於建立自定義 S2I 構建器鏡像的構建環境。它包含在 RHSCL YUM 存儲庫 (rhel-server-rhscl-7-eus-rpms) 的 source-to-image 軟件包中。

對現有 S2I 構建器鏡像進行派生。無需從頭開始建立。您可使用適用於 RHCC 中的現有構建器鏡像的 Dockerfile(可從 https://github.com/sclorg/?q=s2i獲取),而後再對其進行自定義以知足您的需求。

對現有 S2I 構建器鏡像進行擴展。您還能夠建立子鏡像,而後向現有構建器鏡像添加內容或替換其中的內容,從而對現有的構建器鏡像進行擴展。

試驗2: 使用 OpenShift 來從 Dockerfile 中構建和部署 Apache HTTP 服務器容器。

查看 Apache HTTP 服務器父 Dockerfile。

FROM registry.lab.example.com:5000/rhel7:7.3 1

MAINTAINER Red Hat Training <training@redhat.com>

# Generic labels
LABEL Component="httpd" \ 2
     Name="do288/httpd-parent" \
     Version="1.0" \
     Release="1"

# Labels consumed by OpenShift
LABEL io.k8s.description="A basic Apache HTTP Server image with ONBUILD instructions" \ 3
     io.k8s.display-name="Apache HTTP Server parent image" \
      io.openshift.expose-services="80:http" \
     io.openshift.tags="apache, httpd"

# DocumentRoot for Apache
ENV DOCROOT=/var/www/html \4
\
   LOG_PATH=/var/log/httpd

# Need this for installing Apache from cla***oom yum repo
ADD training.repo /etc/yum.repos.d/training.repo

RUN   yum install -y --setopt=tsflags=nodocs --noplugins httpd && \ 5
     yum clean all --noplugins -y && \
      echo "Hello from the httpd-parent container!" > ${HOME}/index.html

# Allows child images to inject their own content into DocumentRoot
ONBUILD COPY src/ ${DOCROOT}/ 6

EXPOSE 80

# This stuff is needed to ensure a clean start
RUN rm -rf /run/httpd && mkdir /run/httpd

# Run as the root user
USER root 7

# Launch apache daemon
CMD /usr/sbin/apachectl -DFOREGROUND

構建並部署 Apache HTTP 服務器子鏡像:

oc new-app --name hello
http://services.lab.example.com/container-build
--insecure-registry

命令行將會完成以下操做:

  • OpenShift 從 oc new-app 命令提供的 URL 克隆 Git 存儲庫。

  • Git 存儲庫根上的 Dockerfile 會自動識別,並啓動 Docker 構建進程。

  • 父 Dockerfile 中的 ONBUILD 指令會觸發子 index.html 文件的複製,其會覆蓋父索引頁。

  • 最後,構建的鏡像會推送到 OpenShift 內部註冊表。

查看構建日誌

Cloning "http://services.lab.example.com/container-build" ... 1
        Commit: 32494325ace534486841c085da0cbc55c05ae33c (Initial commit)
        Author: root <root@foundation0.ilt.example.com>
        Date:   Sun Oct 15 12:07:05 2017 -0400
Pulling image registry.lab.example.com:5000/do288/httpd-parent@sha256:853d59eca... 2
...
Pulled 5/6 layers, 85% complete
Pulled 6/6 layers, 100% complete
Extracting
Step 1 : FROM registry.lab.example.com:5000/do288/httpd-parent@sha256:853d59eca...
# Executing 1 build trigger... 3
Step 1 : COPY src/ ${DOCROOT}/
...
Successfully built c8a37064e3e9
Pushing image docker-registry.default.svc:5000/container-build/hello:latest ... 4
...
Pushed 7/7 layers, 100% complete
Push successful

查看 Pod 沒法啓動的緣由:

因爲 OpenShift 使用隨機 userid 運行容器,低於 1024 的端口是特權端口,只能以 root 身份運行。
OpenShift 用於運行容器的隨機 userid 不具備在 /var/log/httpd(RHEL 7 上的 Apache HTTP 服務器的默認日誌文件位置)中讀寫日誌文件的權限。

配置 OpenShift 以容許容器做爲 Dockerfile 的 USER 指令中配置的用戶運行。此方法不須要對 Dockerfile 進行任何更改。爲應用建立新的服務賬戶

oc create serviceaccount apacheuser

將 anyuid SCC 添加到服務賬戶:

oc adm policy add-scc-to-user anyuid -z apacheuser

將 serviceAccountName 屬性添加到 spec.template.spec 部分(terminationGracePeriodSeconds 屬性下面),而後保存文件:

前一個 oc edit 命令觸發了新的部署。等待新 Pod 就緒並在運行。查看應用 Pod 的狀態:

圖片

使用路由公開應用供外部訪問:
圖片

相關文章
相關標籤/搜索