DCOS雲平臺之應用容器化改造規範

jaymarco發表於2020-09-24

對於傳統應用來說,使用和不使用Docker可能並不能直接給企業帶來好處,相反使用中遇到了問題肯定會給企業帶來麻煩。大家會問是什麼原因讓大家接受和使用Docker,並將他們的應用遷移至Docker容器使用呢?Docker最大的好處無非是高效的標準化應用交付,它不僅能提高了運維工作效率,並節約硬體成本。據國外的統計使用Docker平均可以提升60%的效率,同時節約40%的成本。

當我們需要遷移一個應用的時候,首先需要了解一個應用當前正在使用的資源有哪些。瞭解當前系統的網路拓撲,瞭解當前系統之間互相呼叫關係。現有的拓撲結構是遷移的最好參考,傳統的單體模式下,很多應用程式執行在一臺主機之上,但在微服務體系下,我們更傾向於透過容器來解耦合,實際上,並不是所有系統都適合於解耦合,任何一個企業在遷移過程中都不願意去重新對一個應用模組重新編碼,因為有的程式可能根本就找不到程式碼,有的程式根本就找不到對應開發商,有的系統甚至要全部梳理一遍才能瞭解系統整體架構。要想讓傳統應用遷移至容器後上雲成功,想必在改造的過程中需要遵循一些規範。

2.1.1 熱點資料快取規範

1 、問題描述

熱點資料指應用系統在執行過程中經常使用的資料,傳統方式是應用系統在啟動時透過資料庫載入到應用例項快取中,提高資料的訪問速度,但往往因為載入的資料過多而導致系統啟動過慢。

2 、改造建議

建議應用在設計時將熱點資料存放到快取伺服器(如Redis、Memcached)中   ,在啟動時避免執行載入快取動作,提高應用系統啟動速度,相關熱點資料可透過手動或自動方式更新到快取伺服器中,應用透過訪問快取伺服器獲取相關熱點資料。

規範

1 、問題描述

有狀態應用是指使用者在登陸後會有一定的會話資訊(也就是應用中的session物件)儲存在例項中,如果該例項異常停止,該使用者的會話資訊就會丟失。

2 、改造建議

建議應用開發設計時將使用者的會話資訊儲存到快取伺服器(如Redis、Memcached)中,根據使用者的唯一標識session_id來對快取伺服器進行存取使用者的會話資訊,這樣會話資訊與應用例項分離,實現應用無狀態話。

3 、中介軟體session儲存配置樣例

1) 、Tomcat樣例

應用伺服器本地會話儲存改為使用key-value資料庫(redis)儲存。Session的讀取依然由中介軟體Session Manager進行自定義管理。

例如:tomcat中載入 tomcat-redis-sessionmanage-1.2.jar   、commons-pool-1.6.jar 、jedis-2.1.jar

tomcat/conf/context.xml 中加入如下配置:

<Manager className= “com.orangefunction.tomcat.redissessions.RedisSessionManager”

 maxInactiveInterval= “60”    //當前會話的失效時間

 sentineMaster= “自定義”    //與redis配置保持一致

2 )、php-fpm+nginx樣例

nginx 安裝使用php70-php-pecl-redis擴充套件包,然後php連線redis配置

$config['sess_cookie_name']   = 'nlf_front_session';

$config['sess_expiration']   = 7200;

$config['sess_save_path']   = '127.0.0.1:6379?auth=Redis@2017';

$config['sess_match_ip'] =   FALSE;

$config['sess_time_to_update']   = 300;

$config['sess_regenerate_destroy']   = FALSE;

規範

1 )應用日誌檔案命名規則:[應用名]_[容器ID]_catalina.out_[date]

2 )應用日誌統一輸出到應用規劃目錄下

3 )每個容器中應用日誌檔案個數最大為5個,每個日誌檔案容量最大為200M

日誌在測試環境中開啟除錯開關,但在生產環境中必須關閉除錯開關

5 )容器內的應用日誌檔案統一收集到日誌伺服器

1 、問題描述

應用系統在開發過程中需要分別在開發環境、測試環境、預生產環境和生產環境,而對於不同環境,應用只是某些配置檔案的配置不同(如資料庫連線地址,訪問介面地址)不同,而程式程式碼相同,在不同環境中部署時就要進行重新打包。

2 、改造建議

建議應用針對不同環境準備相應的配置檔案,並全部打包到應用包中,我們以web.xml為例,命名規則如下:

開發環境—dev_web.xml

測試環境—test_web.xml

預生產環境—pre_web.xml

生產環境—pud_web.xml

並將檔案存放路徑寫入系統整合文件中。

2.2     應用映象打包改造規範

改造事項

問題描述

改造建議

應用中介軟體選型

傳統方式是可以將輕量級與重量級的中介軟體軟體部署到小機或是虛機是沒有問題,因為他會佔用著一臺主機資源,對啟動服務時間要求不是那麼高。如果重量級的應用部署到容器內就不適合容器秒級啟動的目標,也會出現資源浪費情況。

1 、Java開發語言程式動態應用使用tomcat輕量級中介軟體

2 、靜態應用使用nginx高效能WEB 伺服器

3 、Php開發語言程式動態應用使用php-fpm與nginx結合

4 、快取伺服器使用Redis高效能快取伺服器

容器應用程式非root使用者啟動

如果容器中使用的root使用者啟動應用,這樣在外面的宿主機就可以自由的使用直接docker exec命令獲取root許可權,安全風險比較大。

1 、docker容器預設以root執行。

2 、隨著docker的成熟,越來越多的安全預設選項變得可用。請求root是危險的,可能無法在所有環境中可用。所以映象應該使用USER命令來指令容器以一個非root使用者來執行。

應用固化服務監聽埠

對於標準的服務只需提供一個對外服務埠,而有些應用在執行過程中會自己產生一些服務埠對外服務,而且這些埠是隨機產生,給管理帶來不便。

在應用設計時儘量不要在應用執行時產生額外的服務埠,如果必須使用則需讓埠固定下來並體現在系統整合文件中

定時任務與應用分離

傳統方式定時任務都與應用打包在一起,透過修改配置檔案的特定配置項來控制定時任務是否啟動,這樣就會出現應用的差異化,在系統執行時就需要去手動配置。

將定時任務與應用分開,執行不同容器。

單應用單容器執行

傳統方式是可以將多個應用部署到一套中介軟體執行環境,但如果多個應用部署到一個容器環境會影響資源爭用問題,影響系統效能與系統之間隔離性。

每個容器中只能執行一個應用,不能部署多個應用到一個容器

應用容器中執行單程式

容器中執行多個程式應用會影響系統資源爭用,影響問題定位。

執行的容器只跑單個程式

應用容器之間介面呼叫

服務間介面呼叫使用非標準協議進行互動(如EJB呼叫使用t3協議),無法透過負載均衡器進行有效負載

服務間介面呼叫透過TCP和HTTP協議進行互動,這樣可使用負載均衡器進行有效負載

不要依賴IP地址

傳統方式部署應用是會有一個獨立IP地址,然後註冊到LB負載均衡和介面呼叫地址。但如果部署的容器採用固定IP實現負載就會存在單點故障,因為容器IP地址是隨時會變化的,所以註冊到LB的地址也要隨時變更。

1 )每個容器都有自己的內部IP地址,如果你啟動並停止它地址可能會變化。

2 )如果應用或微服務需要與其他容器通訊,由於容器IP是不固定的,應用依賴IP地址將無法與其他容器通訊,可以選擇更合適的方式與其他容器進行通訊。

持久化有狀態資料

傳統方式對介面、附件檔案直接存放在伺服器,或是FTP伺服器,使用都是正常的。但如果將有狀態的資料放在容器裡面,就會因容器銷燬而丟失,因此我們需要將容器裡面有狀態的資料單獨掛出來,以保障資料永久不丟失。

1 )由於容器是一次性的,當容器被停止、銷燬或替換時,應用在容器中儲存的資料同樣會被銷燬。

2 )如果應用需要儲存資料,需儲存在共享資料儲存中。

清除不必要的依賴包和檔案

容器化映象打包時間可以將軟體依賴包直接以儲存方式掛在容器外。不要因導致容器映象大小越來越大,影響容器快速啟動。

容器的一個顯著特點是秒級啟動,一旦製作了一個超大的映象將難以分發。就失去了容器的意義了。

不要在映象中儲存憑據、使用環境變數

關於應用容器呼叫介面服務時應該在打包映象的時候按規範不能寫死IP地址,以免後續資料庫地址變更後需要調整映象。

1 )不要在應用中寫死服務的IP和埠(如資料庫IP和埠、服務介面IP和埠),採用域名的方式。

2 )環境變數應該以傳參的形式傳入容器,而不是直接寫死在容器中,需要的環境變數可寫入系統整合文件中。

3    實際專案容器化經驗與總結

以下是我們在某金融專案針對兩套系統的應用進行容器化改造後的經驗總結:

改造內容

改造子項

DCOS 小組

開發小組

相關檔案路徑位置

日誌持久化

tomcat 日誌

在容器/app/bin/startserver.sh中新增行:
  export CATALINA_OPTS="${CATALINA_OPTS} -Dhostname=${HOSTNAME}   -Dmarathon.app.id=${MARATHON_APP_ID}"

1 、更新log4j.xml中value欄位,規範如下:
  value="/logs/tomcat/${marathon.app.id}:${hostname}:log4j.log"
 
  2、對應用日誌進行切割
  log4j.appendeer.root.layout.conversionPattern=%d(yyy-MM-dd HH:mm:ss) (%-5p)   %c (%F:%L) - %m%n

更改APP的'log4j.properties檔案的Value值,檔名改為value="/logs/tomcat/${marathon.app.id}:${hostname}:root.log
  value="/logs/tomcat/${marathon.app.id}:${hostname}:core.log
  value="/logs/tomcat/${marathon.app.id}:${hostname}:torque.log
 
  更改WEB的'log4j.properties檔案的Value值,檔名改為value="/logs/tomcat/${marathon.app.id}:${hostname}:spdbcccActivityDY.log
  所有'log4j.properties檔案中log4j.appendeer.root.layout.conversionPatter變更為:
  log4j.appendeer.root.layout.conversionPattern=%d(yyy-MM-dd HH:mm:ss) (%-5p)   %c (%F:%L) - %m%n

nginx 日誌

在容器內修改配置檔案/etc/nginx/nginx.conf中新增日誌輸出
  error_log  /logs/nginx/error.log error

nginx 代理轉發日誌檔名:/logs/nginx/error.log

php-fpm 日誌

在容器內修改配置檔案/etc/opt/remi/php70/php-fpm.conf中新增日誌輸出error_log = /logs/php-fpm/error.log

php-fpm 代理轉發日誌檔名: /logs/php-fpm/error.log

會話持久化

php 環境redis

打包redis容器映象,採用birgde網路協議提供給業務呼叫
  redis IP預設
  server:redis_ip:6379

1 、涉及到redis應用,將redis資訊配置到active_front/suites/config/config.xml檔案,資訊如下:
  $config['sess_driver'] = 'redis';
  $config['sess_cookie_name'] = 'nlf_front_session';
  $config['sess_expiration'] = 7200;
  $config['sess_save_path'] = '127.0.0.1:6379?auth=Redis@2017';
  $config['sess_match_ip'] = FALSE;
  $config['sess_time_to_update'] = 300;
  $config['sess_regenerate_destroy'] = FALSE;

程式碼路徑:active_front/suites/config/config.xml

tomcat 環境redis

打包redis容器映象,採用birgde網路協議提供給業務呼叫
  redis IP預設
  server:redis_ip:6379

1 、涉及到redis應用,將redis資訊配置到tomcat\context.Xml檔案,資訊如下:
  <Valve   className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve"   /> 
  <Manager   className="com.orangefunction.tomcat.redissessions.RedisSessionManager" 
             maxInactiveInterval="60"
             sentinelMaster="mymaster"   
             sentinels="redis_ip:6379"    />
  2、提供相關檔案變更路徑及所需變更欄位資訊
  3、context.xml檔案中更改active_front為"/front"

context.xml 檔案路徑位置:
  context.xml檔案中更改active_front為"/front"

持久化有狀態資料

介面與附件

透過docker -V資料卷引數將容器中的檔案轉存到外部共享儲存

開發提供介面與附件路徑

NFS 共享儲存路徑:
  /sharefs/cecrm_acitivtycenter/admincert
  容器路徑:
  /var/www/cecrm_acitivtycenter/uploads

中介軟體效能引數

tomcat 引數

將相關配置到容器

提供相關的效能引數

配置檔案資訊及相對路徑:tomcat/conf/
  jdk版本:1.7.0.76
  中介軟體版本:tomcat 7.0.42

nginx 引數

將相關配置到容器
  server {
      listen       8080;
      server_name  127.0.0.1;
          large_client_header_buffers 4   16k;
          client_max_body_size 300m;
          client_body_buffer_size 128k;
          proxy_connect_timeout 600;
          proxy_read_timeout 600;
          proxy_send_timeout 600;
          proxy_buffer_size 64k;
          proxy_buffers   32 32k;
          proxy_busy_buffers_size 64k;
          proxy_temp_file_write_size 64k;

提供相關的效能引數

配置檔案資訊及相對路徑:
  /etc/nginx/conf.d/website.nginx.conf
  版本號:1.10.3

php 引數

將相關效能引數配置到容器
  sed -e 's/127.0.0.1:9000/9000/' \
  -e '/allowed_clients/d' \
  -e '/catch_workers_output/s/^;//' \
  -e '/error_log/d' \
  -e 's/;listen.backlog = 511/listen.backlog = 1024/' \
  -e 's/pm.max_children = 50/pm.max_children = 300/' \
  -e 's/pm.start_servers = 5/pm.start_servers = 30/' \
  -e 's/pm.min_spare_servers = 5/pm.min_spare_servers = 30/' \
  -e 's/pm.max_spare_servers = 35/pm.max_spare_servers = 60/' \
  -e 's/;pm.max_requests = 500/pm.max_requests = 10240/' \
  -e 's/;request_slowlog_timeout = 0/request_slowlog_timeout = 2/' \
  -e 's/;request_terminate_timeout = 0/request_terminate_timeout = 600/' \
  -e 's/;rlimit_files = 1024/rlimit_files = 65535/' \
  -i    /etc/opt/remi/php70/php-fpm.d/ && \
  sed -e 's/max_execution_time = 30/max_execution_time = 600/' \
  -e 's/max_input_time = 60/max_input_time = 300/' \
  -i /etc/opt/remi/php70/php.ini && \
  sed -e 's/daemonize = yes/daemonize = no/' \
  -e 's/;rlimit_files = 1024/rlimit_files = 65535/' -i   /etc/opt/remi/php70/php-fpm.conf && \

提供相關的效能引數

配置檔案資訊及相對路徑:
  /etc/opt/remi/php70/php-fpm.conf
  /etc/opt/remi/php70/php.ini
  版本號:7.0

應用開發改造

熱點資料改造

提供redis映象包

熱點資料快取放到redis、應用無狀態開發、應用上配置的定時任務及應用分離、應用資料儲存到共享儲存(參考應用改造方案)


 

在實際專案中容器化改造這部分是整個專案中的一個難點,不僅是在應用改造過程會有技術中的一些難點,而最最關鍵的還是應用開發商配合才能一起順利完成應用容器化改造,才能正常將應用容器釋出到DCOS雲平臺來進行驗收測試。雖然改造過程是反反覆覆的重複工作,但經過此次專案的經驗對容器化應用改造積累下來不少經驗,為後續DCOS新專案的開始打下了堅實的基礎。

接下來對應用容器化改造做如下幾點總結:

1)   建議應用改造優先順序可選擇,先新系統後到老系統、先小系統後到大系統、先非核心繫統後到核心系統。

2)   建議應用改造可選擇新系統或非核心又不復雜的系統做試點測試。

3)   建議應用改造可選那些能找得到原始碼的程式。

4)   建議應用改造可選那些開發商能主動配合一起改造的系統。

5)   建議應用改造先做原始應用容器化改造交付,後做應用微服務解耦改造。

6)   建議應用改造一定要有詳細的改造方案才能實施。

有需要的朋友可以關注我的公眾號,文章每日一更


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28833846/viewspace-2723801/,如需轉載,請註明出處,否則將追究法律責任。

相關文章