CNCF 會重蹈 OpenStack 的覆轍嗎?|航海日誌 Vol.25

DaoCloud發表於2019-02-17

CNCF 會重蹈 OpenStack 的覆轍嗎?|航海日誌 Vol.25

➤ CNCF 會重蹈 OpenStack 的覆轍嗎?

CNCF 會重蹈 OpenStack 的覆轍嗎?|航海日誌 Vol.25

CNCF(Cloud Native Computing Foundation),即雲原生計算基金會,於 2015 年 7 月成立,隸屬於 Linux 基金會,初衷圍繞“雲原生”服務雲端計算,致力於維護和整合開源技術,支援編排容器化微服務架構應用。


由於最近大佬級別的雲提供商的加入,雲原生計算基金會(CNCF)很快就站在了開源容器世界的中心。在過去的幾個星期裡, CNCF 吸引了微軟和亞馬遜的 Web 服務 (AWS)的加入。他們的加入對於這個本來就隸屬於 Linux 基金會的組織來說,無疑是如虎添翼。

而伴隨著 Kubernetes 的成功,和市場對於容器技術的需求逐漸擴大,CNCF 的聲勢也日漸浩大。微軟和 AWS 相繼加入 CNCF,對於 CNCF、開源和 Kubernetes 來說, 也是一個巨大的勝利。


儘管這些會給 CNCF 帶來規模和潛在的影響,但組織仍然面臨挑戰。


CNCF 執行董事 Dan Kohn 表示:


CNCF 一直非常專注於確保所有成員在迅速擴張的組織中都有各自的代表性。CNCF 的最大優勢是他們足夠新興,所以他們能夠向前人學習,其的願景是隻犯新的錯誤, 而不是照搬過去的錯誤。所以推斷 CNCF 會重蹈 OpenStack 的覆轍,這樣的論斷是錯誤的。


而對 OpenStack 來說,許多運營商早期的時候使用 OpenStack 來實現他們的 SDN 計劃,而現在供應商社群則無法提供所需的解決方案。同時,OpenStack 存在的一些問題還歸咎於它無法處理一些較大成員的不同需求。


而為了規避這樣的問題,CNCF 留出了在供應商之上新增更多產品的餘地,讓社群來決定其有用性。這樣他們的生存和死亡由自身的優勢決定,但 OpenStack 社群人為地支撐著將死的平臺。


同時,Dan Kohn 也承認 Kubernetes 一直處於爆炸性增長的狀態。如果能管理這一增長,則能實現組織目前最大的成就。

➤ Kubernetes 1.7.4 版本釋出

CNCF 會重蹈 OpenStack 的覆轍嗎?|航海日誌 Vol.25

8 月 17 日, Kubernetes 1.7.4 版本釋出,相比 1.7.3 版本共有 17 處明顯變化,例如:


  • 修復建立或更新 ELB 會修改全域性定義的 Security Group Bug

  • 修復 kubefed 在不同版本 RBAC 建立問題

  • 修復 API Server Watch Cache 中一個 Bug

  • Azure:允許 VNet 在一個單獨的資源組中

  • Cluster Autoscaler -修復了與 taints 相關的問題,並更新了 kube – proxy cpu請求

  • 以 Stackdriver 模式收集來自 Heapster 的 Metrics

  • GCE:Bump GLBC 版本更新到 0.9.6

  • 更新 Heapster 版本 1.4.1


➤ Docker Tips:將容器的檔案重定向到您的 Docker 主機

CNCF 會重蹈 OpenStack 的覆轍嗎?|航海日誌 Vol.25

每隔一段時間,我都需要將容器的檔案轉存到我的 Docker 主機上。在這裡向大家提供一種簡單的方法。

有時為了除錯,您可能想將容器內部的配置檔案的內容複製到 Docker 主機,以便您在自己喜歡的程式碼編輯器中開啟它,或將其傳送給別人。這對於已經執行的 Docker 容器來說非常方便,並且您不希望用 volume 重新啟動它,因為你想要立刻就獲取這個檔案。

完成以下兩點你就可以達成目的:

# 重寫那個映象的 Dockerfile 的 CMD, 來cat到你想要的檔案
docker run --rm alpine cat /etc/hosts複製程式碼

以上步驟將列印出容器的 /etc/hosts 檔案的內容

# 修改命令將該輸出重定向到 Docker 主機上的新檔案。
docker run --rm alpine cat /etc/hosts > /tmp/alpinehosts複製程式碼

你可以執行命令ls -la /tmp | grep alpinehosts來進行驗證。

當然,如果您在 Docker 主機上執行 Windows 而不是 MacOS 或 Linux,則你的命令需要進行一些小的調整。例如,在 Windows 上不起作用。如果您使用 PowerShell 等,您將需要 Google 一下如何將輸出重定向到檔案。

另外,在這兩種情況下,您都需要將Cat指令安裝在 Docker 映象中,但所有主要的 Linux 版本都已經預設安裝了(包括 Alpine)。


➤ 從環境變數到 Docker secrets

12 Factor app

12 Factor app 中的第三項告訴我們要將配置儲存在環境中。

它還提供了以下內容的示例:

  • 資源處理資料庫,Memcached 和其他後臺服務

  • 對外部服務的認證,如 Amazon S3 或 Twitter

  • 部署的規範主機名

我們想知道如今是否仍然推薦這種方法,並且使用它的風險程度。在這篇文章中,我們將一個簡單的應用程式為例,看看如何修改它以更安全的方式來處理這些敏感的資訊。

在 Docker 世界執行的應用

在過去的幾年中,我們看到了許多應用在開發和部署方面都產生了變化。這主要是因為Docker 平臺的流行。應用程式現在主要採用微服務體系結構:它們由多個隔離式服務組成。使用 Docker Compose 檔案格式定義微服務應用程式現在非常普遍。此格式定義了服務及其使用的元件(網路,卷,...)。以下是用於定義由以下組成的 Web 應用程式的 Docker Compose 檔案(其預設名稱為 docker-compose.yml)的簡單示例:

version: "3.3"
services:
  db:
    image: mongo:3.4
    network:
      - backend
    volumes:
      — mongo-data:/data/db
    deploy:
      restart_policy:
        condition: on-failure
  api:
    image: lucj/api:1.0
    networks:
      - backend    
    deploy:
      restart_policy:
        condition: on-failure
  web:
    image: lucj/web:1.0
    networks:
      - frontend
      - backend    
    deploy:
      restart_policy:
        condition: on-failure    
volumes:
  mongo-data:
networks:
  frontend:  
  backend:複製程式碼

使用環境變數處理 AWS 憑據

當我們深入瞭解 api 服務,假設這需要 AWS S3 的一些憑據。api 服務是在 Node.js 中編寫的。使用 aws-sdk npm 模組連線到 Amazon API 的程式碼類似於以下內容。

// Middleware handling user's profile images
const AWS = require('aws-sdk'),
      config = require(‘../config’),
      aws_config = config.amazon;
// Configure AWS SDK
AWS.config.update(aws_config.credentials);
// Define S3 bucket
var s3Bucket = new AWS.S3( { params: {Bucket: aws_config.bucket} } )
...
// Upload image object
s3Bucket.putObject(obj, function(err){
    if (err) {
        log.error(err);
        return next(err);
    } else {
          return next();
    }
}複製程式碼

以上程式碼中所需的配置模組在一些其他配置內容中定義了 AWS 憑據。我們在這裡看到,每個元素從一個環境變數獲取它的值。

// config.js
module.exports = {
...
  "amazon":{
    "credentials": {
      "accessKeyID": process.env.AWS_ACCESS_KEY_ID,
      "secretAccessKey": process.env.AWS_SECRET_ACCESS_KEY,
    },
    "bucketName": process.env.AWS_BUCKET_NAME
  }
};複製程式碼

然後,當通過 Docker Compose 執行應用程式時,我們通過環境鍵指定這些環境變數。

api:
 image: lucj/api:1.0
networks:
      - backend    
    deploy:
      restart_policy:
        condition: on-failure
 environment:
   — AWS_BUCKET_NAME=BucketName
   — AWS_ACCESS_KEY_ID=AccessKeyID
   — AWS_SECRET_ACCESS_KEY=SecretAccessKey複製程式碼

這的確是處理這個問題的一個方式,但是,將這些敏感資訊以純文字格式化是非常危險的。

處理具有 Docker secrets 的 AWS 憑據

有幾種方式可以以安全的方式處理這些資訊。使用 Docker secrets 就是其中之一。

我們不再在環境變數中以純文字定義憑據資訊,而是從中建立 docker secrets。

$ echo "BucketName"| docker secret create AWS_BUCKET_NAME -
vjp5zh8hwb9dqkvohtyvtifl1
$ echo "AccessKeyID" | docker secret create AWS_ACCESS_KEY_ID -
5txxg3fslf9g5z1o4i19vvmcr
$echo "SecretAccessKey"|docker secret create AWS_SECRET_ACCESS_KEY -
v8g65iwcx1eb6uuwsjzknyi7g複製程式碼

secrets 建立成功。使用docker secret ls

$ docker secret ls
ID NAME CREATED UPDATED
5x..vm AWS_ACCESS_KEY_ID About a minute ago About a minute ago
v8..7g AWS_SECRET_ACCESS_KEY About a minute ago About a minute ago
vj..l1 AWS_BUCKET_NAME About a minute ago About a minute ago複製程式碼

但他們的內容無法被檢索。例如,如果我們檢查與關鍵字 AWS

ACCESS
KEY_ID 相關聯的 secret,我們只會獲取後設資料,而不是其實際內容。

$ docker secret inspect 5txxg3fslf9g5z1o4i19vvmcr
[
  {
    "ID": "5txxg3fslf9g5z1o4i19vvmcr",
    "Version": {
      "Index": 12
    },
    "CreatedAt": "2017–08–13T12:58:50.54021338Z",
    "UpdatedAt": "2017–08–13T12:58:50.54021338Z",
    "Spec": {
      "Name": "AWS_ACCESS_KEY_ID",
      "Labels": {}
    }
  }
]複製程式碼

建立了 secret 以後,我們就可以在 Docker Compose 檔案中引用它們。

secrets:
  AWS_BUCKET_NAME:
    external: true
  AWS_ACCESS_KEY_ID:
    external: true
  AWS_SECRET_ACCESS_KEY:
    external: true 
 
複製程式碼

在 Docker Compose 檔案中,我們還需要修改 api 服務的描述,以便使用這些 secrets。

api:
 image: lucj/api:2.0
 secrets:
   — AWS_BUCKET_NAME
   — AWS_ACCESS_KEY_ID
   — AWS_SECRET_ACCESS_KEY
 networks:
   — backend
 deploy:
   restart_policy:
     condition: on-failure複製程式碼

當一個服務需要訪問一個 secret 時,預設情況下,它被安裝在該服務的每個容器中的臨時檔案系統中。


由於我們的應用程式僅在此階段檢查環境變數,因此需要進行更新。


這可以用一個簡單的模組來實現,只需要從`/run/secrets`中讀取一個 secret。這在以下程式碼中說明。

// secrets.js
const fs = require("fs"),
      util = require("util");
module.exports = {
  // Get a secret from its name
  get(secret){
    try{
      // Swarm secret are accessible within tmpfs /run/secrets dir
      return fs.readFileSync(util.format(“/run/secrets/%s”, secret), "utf8").trim();
     }
     catch(e){
       return false;
     }
  }
};複製程式碼

然後,我們可以修改配置檔案,以便它使用 secrets.js 模組的 get 函式:

...
"amazon":{
  "credentials": {
    "accessKeyId": secrets.get(“AWS_ACCESS_KEY_ID”) || process.env.AWS_ACCESS_KEY_ID,
    "secretAccessKey": secrets.get(“AWS_SECRET_ACCESS_KEY”) || process.env.AWS_SECRET_ACCESS_KEY,
  },
 "bucket": secrets.get("AWS_BUCKET_NAME") || process.env.AWS_BUCKET_NAME
 }複製程式碼

對於每個 key,我們首先檢查它是否作為 secret 存在。如果沒有的話,我們仍然使用環境變數。

這一期的『航海日誌』就到這裡,下期再浪~


參考連結


作者介紹

莫非 Beck:DaoCloud 微服務攻城獅,吃飽了就困的一流段子手。

劉璽元 Boring:DaoCloud 市場部門(偽)程式猿。


Discussion | 你對今天的哪條新聞最感興趣?

  • 你對今天的哪條新聞最感興趣?你有什麼獨到的見解?

  • 本週你還有什麼更具爆炸性的容器圈新聞嗎?歡迎在留言區爆料!


點這兒,回顧一下船長的過去

CNCF 會重蹈 OpenStack 的覆轍嗎?|航海日誌 Vol.25


相關文章