Categories
程式開發

如何搭建可用於生產環境的Kubernetes基礎設施?


11月14日,我們發布了Pulumi Crosswalk for Kubernetes,其中包括開源工具、庫和使用手冊,幫助開發人員和操作人員一起將Kubernetes引入他們的組織。這其中囊括了過去一年,我們與組織合作從零開始為他們的基礎設施和應用程序工作負載引入Kubernetes的經驗教訓。我們希望通過以開源的方式發布這些內容,幫助企業在Kubernetes項目中獲得成功。

如何將基礎設施即代碼用於Kubernetes

一年多前,我們啟動了使用Pulumi的開源基礎設施即代碼工具來管理Kubernetes資源的支持。除了Helm 、Charts的整個生態系統之外,你可以在自己選擇的語言中使用所有受支持版本的全部Kubernetes對像模型——包括JavaScript、TypeScript和Python。這為新發布的Kubernetes版本提供了100%的API資源兼容和當日支持。

通過利用通用語言,你可以獲得豐富的功能,如for循環、函數和類、共享和重用最佳實踐的能力(消除複製和粘貼),以及使用你喜歡的工具(包括編輯器、測試框架和靜態分析工具)。

圖片

這對於我們中任何一個與“YAML或JSON之牆”作鬥爭的人來說都是令人興奮的——但這還不是全部。

統一的基礎設施即代碼方法提供了健壯的交付工作流,不僅支持跨Kubernetes資源管理配置,還支持跨任何集群的底層公有或私有云基礎設施,包括AWS、Azure、Google Cloud、vSphere等。

當時,我們沒有意識到這種統一的方法會有多麼強大。例如,正確地配置一個Amazon EKS集群不僅需要在AWS上編排部署,還需要來回使用Kubernetes資源。我們設計了Pulumi,讓你可以使用一個一致的平台和工作流來完成這項工作,從而取代了通常需要集成多個工具的“大量Bash”。

這是一個令人興奮的開始,我們有許多終端用戶和組織,他們很快就找上門來,在我們的幫助下採用Kubernetes。

為什麼在生產環境中使用Kubernetes很困難

下面是我們面臨的以及我們努力幫助解決的挑戰:

Kubernetes基礎設施不是一座孤島。儘管AWS、Azure和GCP提供了託管的Kubernetes服務,但是大多數擁有成熟基礎設施的組織發現很難配置和管理集群基礎設施。這通常是因為要投入生產應用,就需要將集群連接到許多周圍的基礎設施——包括IAM、網絡、加密服務、私有Docker註冊中心等等。特定於kubernets的工具只能幫助解決部分問題並且會創建筒倉。

賦能整個組織非常困難。大多數採用Kubernetes的組織都試圖協調“房子的兩邊”——開發人員和運營人員。基礎設施運營團隊負責管理集群和底層基礎設施,而開發人員則嘗試向集群交付應用程序和服務(通常還使用其他公共雲服務,如對象存儲)。儘管Kubernetes的體系結構非常適合這一點,但是團隊很難在基礎設施和應用程序交付方面標準化工具、工作流和實踐。

第二階段比第一階段更難。許多團隊決定在Kubernetes上“全力以赴”,結果卻發現,保護、擴展和實施Kubernetes比他們想像的要復雜得多。你可以執行零停機升級嗎?如何在區域之間執行故障轉移?將新的容器鏡像從dev提升到staging,再提升到數十個生產集群的速度有多快?

更複雜的是,這些挑戰會因為你的目標雲環境而有所不同。儘管Kubernetes幫助你標準化了容器計算層,以及擴展負載均衡服務,但是它並沒有抽像出雲之間的所有基礎設施功能,比如IAM、容器註冊中心和數據服務。

在過去的一年中,我們與許多客戶有過這樣的直接接觸。我們致力於為客戶開發三個特定領域的全套解決方案:

  • 基礎設施操作手冊

  • 使Kubernetes更便於開發人員使用

  • 大規模交付和可觀測性洞察

接下來讓我們逐條說明。

開發集群基礎設施操作手冊

大多數實踐者只能自己去尋找Kubernetes基礎設施中最困難的問題的解決方案。在幫助數十個客戶使用AWS EKS、Azure AKS、谷歌Cloud GKE和Kubernetes內部基礎設施進行生產之後,我們決定將最佳實踐開發成一套操作手冊。這有助於組織避免重複勞動,以及減少安全、可靠性和可維護性方面的潛在缺陷。

這些操作手冊涵蓋了許多領域,比如包括下面這樣的主題:

控制平面。每個Kubernetes集群都有一個由控制器、狀態管理和其他集中服務組成的控制平面。每個提供商都提供了創建、部署和管理控制平面的獨有方法。

工作節點。每個集群還需要工作節點來實際運行計算。根據你的計算、存儲和安全需求,這些節點(通常使用多個節點池)的配置和管理有很大的不同。正確處理這一問題對於在成本和性能之間取得良好的平衡至關重要。

身份標識。所有這些還需要與團隊的安全策略集成,包括身份和訪問管理(IAM)以及基於角色的訪問控制(RBAC)。如果你在AWS上,你無疑想要連接到AWS IAM;如果你在Azure中,你想利用現有的ActiveDirectory設置;如果你在GCP中,你會想要使用GCP IAM;如果你使用的是自定義配置,那就更複雜了。這是在組織內部署Kubernetes的一個重要部分。

集群服務。每個集群都需要部署到集群中的集群範圍內的服務,包括性能和監視服務(AWS CloudWatch、Azure日誌分析和監視、Datadog、Prometheus等)、服務網格、容器註冊中心、CRD和操作人員。

應用程序交付。應用程序需要進行容器化、打包並部署到私有容器註冊中心,然後部署到集群,通常是連續不斷的。

應用程序服務。除了應用程序本身之外,雲原生應用程序通常還需要額外的服務。這包括進入控制器、DNS和證書管理服務等。升級集群。最後,同樣重要的是,集群升級是整個操作的重要組成部分。 Kubernetes發展很快,所以經常需要升級,但是要自信地部署升級並不總是很容易,特別是當你要考慮零停機和持久化工作負載時。

這種層次結構如下圖所示:

圖片

我們相信,任何希望在任何公有云中甚或是本地創建可生產使用的基礎設施的人,都將受益於這份資料。它也是開源的,所以我們希望在未來幾週內與社區合作來改進和完善它。

開發人員如何使用Kubernetes

除了必須翻過YAML這堵牆之外,還需要重複進行大量慣用的Kubernetes配置。事實上,它常常讓人感覺手工編寫Kubernetes YAML類似於用彙編語言編寫軟件,而不是用高級語言。

Pulumi公開了全部的Kubernetes API,這意味著你可以使用現代語言實踐來馴服這些低級的混亂。但是,在Crosswalk中提供的新的庫結構通過消除常見的樣板模式將這一問題提升到了另一個層次。

例如,YAML這堵牆:

apiVersion: v1
kind: ConfigMap
data:
  config: very important data
metadata:
  name: app-config
---
apiVersion: v1
kind: Secret
data:
  app-password: JikkMz9mK2hIRDo3
  database-password: Y29uZmlnLmRhdGFiYXNlUGFzc3dvcmQ=
metadata:
  name: app-secrets
type: Opaque
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - env:
            - name: APP_CONFIG_PATH
              value: /app/config
            - name: APP_USER
              value: config.user
            - name: APP_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: app-password
                  name: app-secrets
            - name: APP_DATABASE_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: database-password
                  name: app-secrets
          image: nginx
          imagePullPolicy: Always
          name: nginx
          ports:
            - containerPort: 80
              name: http
          volumeMounts:
            - mountPath: /app/config
              name: app-config-rsg88x4g
      restartPolicy: Always
      volumes:
        - configMap:
            name: app-config
          name: app-config
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

提煉出它的精髓,少了許多繁瑣和重複:

// 定义应用程序配置和秘密
const configs = new kx.ConfigMap("app-config", {
    data: { "config": "very important data" }
});
const secrets = new kx.Secret("app-secrets", {
    stringData: {
        "app-password": new kx.RandomPassword("app-password"),
        "database-password": config.databasePassword
    }
});
// 定义应用程序Pod.
const appConfigPath = "/app/config";
const appPod = new kx.PodBuilder({
    containers: ({
        image: "app:1.0.0",
        env: {
            "APP_CONFIG_PATH": appConfigPath,
            "APP_USER": config.user,
            "APP_PASSWORD": secrets.asEnvValue("app-password"),
            "APP_DATABASE_PASSWORD": secrets.asEnvValue("database-password"),
        },
        volumeMounts: (
            configs.mount(appConfigPath)
        ),
    }),
});
// 使用之前的Pod定义创建一个Kubernetes部署
const deployment = new kx.Deployment("nginx", {
    spec: appPod.asDeploymentSpec({ replicas: 3 }),
});
// 使用Kubernetes Service通过负载均衡器暴露部署
const service = deployment.createService({
    type: kx.types.ServiceType.LoadBalancer,
});

這些庫擴展被設計為與現有的Kubernetes配置共存,這樣你就可以逐漸減少複雜性,而結果仍然是熟悉且完整統一的。
除了以這些方式使Kubernetes配置更容易訪問之外,我們還看到了應用程序配置的其他好處,這包括:

數據服務。對於我們許多人來說,在Kubernetes中管理持續的工作負載是不值得的。雖然可以管理污染、移除和遷移的複雜過程,但我們的許多客戶都依賴於託管的數據存儲產品——比如Amazon S3、RDS、Azure Cosmos DB或谷歌的Cloud BigTable——以及Kubernetes無狀態計算。使用託管服務帶來了擴展、備份和管理等固有的優點,而且不會很麻煩。 Pulumi允許你混合使用Kubernetes和公有云基礎設施即代碼。

容器註冊。大多數最終用戶需要使用私有容器註冊中心來承載應用程序鏡像。此外,我們大多數人都希望使用雲提供商的原生產品,比如Amazon彈性容器註冊中心、Azure容器註冊中心或谷歌容器註冊中心,因為它集成了IAM。使用Pulumi,與支持應用程序基礎設施相比,你不需要單獨的容器部署管道。

無服務器。如果你想要使用最好且最經濟的無服務器功能,那麼你可能想要使用AWS Lambda、Azure函數或谷歌云函數。我們看到終端用戶一直在使用無服務器擴展增強基於容器的應用程序。

架構即代碼。由於Pulumi將真正的語言用於基礎設施即代碼,最終用戶能夠將復雜性抽象並封裝成可重用的形式,例如函數和類。這甚至可以幫助你在Kx解決的基本Kubernetes配置挑戰之外,將雲原生架構中重複出現的模式編成代碼。

除此之外,我們一直在努力開發一種新的試驗性“觀看模式”功能,與上述功能相結合,以一種全新的方式將所有Kubernetes內容展示給你。我們很高興下週能在KubeCon的展位上展示這個!

如何實現大規模交付?

在掌握了基礎設施和應用程序編寫的挑戰之後,困難就轉移到第二階段及後續的工作中。在這個階段,組織需要弄清楚如何持續地向不斷增加的環境交付變更。

自從去年我們首次發布以來,我們已經添加了許多不同的CI/CD集成,包括對GitLab、Codefresh、Azure DevOps、Octopus Deploy、GitHub Action等等的支持。這使全球範圍的交付成為可能。事實上,我們的一個客戶不斷地部署橫跨開發和基礎設施運營團隊的80個不同的環境。

最後,我們很高興能夠在這個預覽版中發布一項新技術、一個新的查詢命令和Kubernetes查詢庫,它利用Pulumi對像模型來請求關於集群及其應用程序的操作查詢。這包括“在我的集群中運行了多少個不同版本的MySQL?”,“哪些Pod通過負載平衡服務暴露在了互聯網上?”等等。

例如,這個查詢顯示了集群中不同版本的MySQL:

import * as kq from "@pulumi/query-kubernetes";
// 找出集群中运行的所有不同版本的MySQL
const mySqlVersions = kq
    .list("v1", "Pod")
    .flatMap(pod => pod.spec.containers)
    .map(container => container.image)
    .filter(imageName => imageName.includes("mysql"))
    .distinct();
mySqlVersions.forEach(console.log);

CQL還支持實時流查詢,CLI將實時顯示查詢結果。

原文鏈接:

https://www.pulumi.com/blog/crosswalk-kubernetes/