CNCF 會重蹈 OpenStack 的覆轍嗎?
CNCF(Cloud Native Computing Foundation),即云原生計算基金會,于 2015 年 7 月成立,隸屬于 Linux 基金會,初衷圍繞“云原生”服務(wù)云計算,致力于維護和集成開源技術(shù),支持編排容器化微服務(wù)架構(gòu)應(yīng)用。
由于最近大佬級別的云提供商的加入,云原生計算基金會(CNCF)很快就站在了開源容器世界的中心。在過去的幾個星期里, CNCF 吸引了微軟和亞馬遜的 Web 服務(wù) (AWS)的加入。他們的加入對于這個本來就隸屬于 Linux 基金會的組織來說,無疑是如虎添翼。
而伴隨著 Kubernetes 的成功,和市場對于容器技術(shù)的需求逐漸擴大,CNCF 的聲勢也日漸浩大。微軟和 AWS 相繼加入 CNCF,對于 CNCF、開源和 Kubernetes 來說, 也是一個巨大的勝利。
盡管這些會給 CNCF 帶來規(guī)模和潛在的影響,但組織仍然面臨挑戰(zhàn)。
CNCF 執(zhí)行董事 Dan Kohn 表示:
CNCF 一直非常專注于確保所有成員在迅速擴張的組織中都有各自的代表性。CNCF 的最大優(yōu)勢是他們足夠新興,所以他們能夠向前人學習,其的愿景是只犯新的錯誤, 而不是照搬過去的錯誤。所以推斷 CNCF 會重蹈 OpenStack 的覆轍,這樣的論斷是錯誤的。
而對 OpenStack 來說,許多運營商早期的時候使用 OpenStack 來實現(xiàn)他們的 SDN 計劃,而現(xiàn)在供應(yīng)商社區(qū)則無法提供所需的解決方案。同時,OpenStack 存在的一些問題還歸咎于它無法處理一些較大成員的不同需求。
而為了規(guī)避這樣的問題,CNCF 留出了在供應(yīng)商之上添加更多產(chǎn)品的余地,讓社區(qū)來決定其有用性。這樣他們的生存和死亡由自身的優(yōu)勢決定,但 OpenStack 社區(qū)人為地支撐著將死的平臺。
同時,Dan Kohn 也承認 Kubernetes 一直處于爆炸性增長的狀態(tài)。如果能管理這一增長,則能實現(xiàn)組織目前最大的成就。
Kubernetes 1.7.4 版本發(fā)布
8 月 17 日, Kubernetes 1.7.4 版本發(fā)布,相比 1.7.3 版本共有 17 處明顯變化,例如:
- 修復創(chuàng)建或更新 ELB 會修改全局定義的 Security Group Bug
- 修復 kubefed 在不同版本 RBAC 創(chuàng)建問題
- 修復 API Server Watch Cache 中一個 Bug
- Azure:允許 VNet 在一個單獨的資源組中
- Cluster Autoscaler -修復了與 taints 相關(guān)的問題,并更新了 kube – proxy cpu請求
- 以 Stackdriver 模式收集來自 Heapster 的 Metrics
- GCE:Bump GLBC 版本更新到 0.9.6
- 更新 Heapster 版本 1.4.1
Docker Tips:將容器的文件重定向到您的 Docker 主機
每隔一段時間,我都需要將容器的文件轉(zhuǎn)存到我的 Docker 主機上。在這里向大家提供一種簡單的方法。
有時為了調(diào)試,您可能想將容器內(nèi)部的配置文件的內(nèi)容復制到 Docker 主機,以便您在自己喜歡的代碼編輯器中打開它,或?qū)⑵浒l(fā)送給別人。這對于已經(jīng)運行的 Docker 容器來說非常方便,并且您不希望用 volume 重新啟動它,因為你想要立刻就獲取這個文件。
完成以下兩點你就可以達成目的:
- # 重寫那個鏡像的 Dockerfile 的 CMD, 來cat到你想要的文件
- docker run --rm alpine cat /etc/hosts
以上步驟將打印出容器的 /etc/hosts 文件的內(nèi)容
- # 修改命令將該輸出重定向到 Docker 主機上的新文件。
- docker run --rm alpine cat /etc/hosts > /tmp/alpinehosts
你可以運行命令ls -la /tmp | grep alpinehosts來進行驗證。
當然,如果您在 Docker 主機上運行 Windows 而不是 MacOS 或 Linux,則你的命令需要進行一些小的調(diào)整。例如,在 Windows 上不起作用。如果您使用 PowerShell 等,您將需要 Google 一下如何將輸出重定向到文件。
另外,在這兩種情況下,您都需要將Cat指令安裝在 Docker 鏡像中,但所有主要的 Linux 版本都已經(jīng)默認安裝了(包括 Alpine)。
從環(huán)境變量到 Docker secrets
1. 12 Factor app
12 Factor app 中的第三項告訴我們要將配置存儲在環(huán)境中。
它還提供了以下內(nèi)容的示例:
- 資源處理數(shù)據(jù)庫,Memcached 和其他后臺服務(wù)
- 對外部服務(wù)的認證,如 Amazon S3 或 Twitter
- 部署的規(guī)范主機名
我們想知道如今是否仍然推薦這種方法,并且使用它的風險程度。在這篇文章中,我們將一個簡單的應(yīng)用程序為例,看看如何修改它以更安全的方式來處理這些敏感的信息。
2. 在 Docker 世界運行的應(yīng)用
在過去的幾年中,我們看到了許多應(yīng)用在開發(fā)和部署方面都產(chǎn)生了變化。這主要是因為Docker 平臺的流行。應(yīng)用程序現(xiàn)在主要采用微服務(wù)體系結(jié)構(gòu):它們由多個隔離式服務(wù)組成。使用 Docker Compose 文件格式定義微服務(wù)應(yīng)用程序現(xiàn)在非常普遍。此格式定義了服務(wù)及其使用的組件(網(wǎng)絡(luò),卷,...)。以下是用于定義由以下組成的 Web 應(yīng)用程序的 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:
3. 使用環(huán)境變量處理 AWS 憑據(jù)
當我們深入了解 api 服務(wù),假設(shè)這需要 AWS S3 的一些憑據(jù)。api 服務(wù)是在 Node.js 中編寫的。使用 aws-sdk npm 模塊連接到 Amazon API 的代碼類似于以下內(nèi)容。
- // 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();
- }
- }
以上代碼中所需的配置模塊在一些其他配置內(nèi)容中定義了 AWS 憑據(jù)。我們在這里看到,每個元素從一個環(huán)境變量獲取它的值。
- // 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 運行應(yīng)用程序時,我們通過環(huán)境鍵指定這些環(huán)境變量。
- 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
這的確是處理這個問題的一個方式,但是,將這些敏感信息以純文本格式化是非常危險的。
4. 處理具有 Docker secrets 的 AWS 憑據(jù)
有幾種方式可以以安全的方式處理這些信息。使用 Docker secrets 就是其中之一。
我們不再在環(huán)境變量中以純文本定義憑據(jù)信息,而是從中創(chuàng)建 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 創(chuàng)建成功。使用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
但他們的內(nèi)容無法被檢索。例如,如果我們檢查與關(guān)鍵字 AWSACCESSKEY_ID 相關(guān)聯(lián)的 secret,我們只會獲取元數(shù)據(jù),而不是其實際內(nèi)容。
- $ 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": {}
- }
- }
- ]
創(chuàng)建了 secret 以后,我們就可以在 Docker Compose 文件中引用它們。
- secrets:
- AWS_BUCKET_NAME:
- external: true
- AWS_ACCESS_KEY_ID:
- external: true
- AWS_SECRET_ACCESS_KEY:
- external: true
在 Docker Compose 文件中,我們還需要修改 api 服務(wù)的描述,以便使用這些 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
當一個服務(wù)需要訪問一個 secret 時,默認情況下,它被安裝在該服務(wù)的每個容器中的臨時文件系統(tǒng)中。
由于我們的應(yīng)用程序僅在此階段檢查環(huán)境變量,因此需要進行更新。
這可以用一個簡單的模塊來實現(xiàn),只需要從`/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 函數(shù):
- ...
- "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 存在。如果沒有的話,我們?nèi)匀皇褂铆h(huán)境變量。
【本文是51CTO專欄機構(gòu)“道客船長”的原創(chuàng)文章,轉(zhuǎn)載請通過微信公眾號(daocloudpublic)聯(lián)系原作者】