2018 年 11 月

第 33 卷 12

容器-啟動並執行使用 Azure Kubernetes 服務

藉由Chander Dhall

在容器協調流程的世界裡,每個人似乎正在談論 Kubernetes。原本是設計由 Google,Kubernetes 是開放原始碼平台協調 Docker (或任何開啟的 Container Initiative) 的容器到叢集中的虛擬機器 (Vm)、 部署、 復原、 調整和許多其他功能的支援。管理 Kubernetes 叢集可以是複雜的工作,因此,Azure 團隊已提供一個受管理的解決方案,稱為 Azure Kubernetes Service (AKS) 大幅簡化此程序。

在本文中,我將示範如何部署 AKS 叢集、 建立安全的 Azure Container Registry (ACR),部署 ASP.NET Web API 應用程式,以及該應用程式透過 Kubernetes 輸入和 Azure DNS 在網際網路上的公開 (expose)。這不是預期會深入探討的文章,Kubernetes,但而不是所需的一切來啟動並執行快速地與應用程式使用 Azure AKS 供應項目。

Azure AKS 的好處之一是可完全管理控制平面,主要和組態的節點所組成。Kubernetes 控制平面通常包含至少一個主要節點和一個、 三或五個 etcd 組態節點。您可以想像得到,管理這些核心服務可以是耗費心力和金錢。有了 AKS,您可以升級的核心服務,或相應放大] 按鈕按一下的額外背景工作節點。此外,在這個階段有這些管理節點不需額外付費。您只需支付執行您的服務的背景工作節點。

這篇文章中討論的程式碼,請參閱bit.ly/2zaFQeq。在存放庫中包含的是基本的 ASP.NET Web API 應用程式,以及 Dockerfile 和 Kubernetes 資訊清單。

建立 Kubernetes AKS 叢集

Azure CLI 用來建立和管理 Azure 雲端訂用帳戶中的資源。可從bit.ly/2OcwFQb。在本文中,整個 l 將用它來管理各種 Azure 服務。Azure Cloud Shell (bit.ly/2yESmTP) 是 Web 型 shell,可讓開發人員不需安裝在本機的 CLI 執行命令。

讓我們開始建立資源群組來保存 AKS 叢集和容器登錄中的,以這小段程式碼:

> group create --name my-aks-cluster --location eastus2

一旦建立資源群組時,我會建立具有單一節點的叢集。為小型的 Vm 時,允許使用 B1 高載映像,建議使用至少 2 核心,7 GB 記憶體執行個體 (D 系列或更新版本)。較小的任何項目都有會調整,並將叢集升級時不可靠的傾向。您也需要列入考量,AKS 目前僅支援節點的單一型別,因此您無法決定要在稍後相應增加為較大的 VM 執行個體。將支援多個節點的集區,未來的新增不同類型的節點,但現在,您必須選擇適合您計劃執行的服務需求的節點大小。

上一躺,請耐心等候建立叢集時,因為通常需要一段 upward of 10 至 12 分鐘的時間。以下是開始執行作業的程式碼:

> az aks create --resource-group my-aks-cluster --name my-aks-cluster
  --node-count 1 --generate-ssh-keys --kubernetes-version 1.11.2
  --node-vm-size Standard_D2s_v3

取得在 AKS 叢集中的 Docker 映像需要 Docker 登錄的使用者。使用公用 Docker 登錄是可接受的開放原始碼散發套件,但大部分的專案會想要安全的私人登錄中的應用程式程式碼。

Azure 提供安全、 受管理的 Docker 登錄的解決方案與 Azure Container Registry (ACR)。若要設定 ACR 執行個體,執行下列命令:

> az acr create --resource-group my-aks-cluster
  --name <REGISTRY_NAME> --sku Basic --admin-enabled true

請注意,所有在 Azure 上裝載 ACR 登錄名稱必須是唯一的登錄庫名稱。

Kubernetes CLI

Kubectl 用來與 AKS 叢集進行互動。它適用於所有作業系統,並有多種安裝。您可以找到更多資訊bit.ly/2Q58CnJ。也是 Web 型儀表板可以是很有幫助,用於取得叢集狀態的快速概觀,但它未涵蓋每個可用的 API 作業,您可能會經常發現自己回到 kubectl CLI。即使您不是經過一段時間,您可能會成長到領會 kubectl 的命令列的作業。搭配 Azure CLI,您可以執行任何作業,而不需要離開殼層。

一旦已安裝 kubectl,認證可以匯入本機驗證叢集使用下列命令:

> az aks get-credentials --resource-group my-aks-cluster
  --name my-aks-cluster

執行此命令會更新 ~/.kube/config 與您的叢集 uri 和簽署授權單位和認證。它也會加入做為目前的組態設定叢集的內容。Kubectl 組態可以保存多個叢集,可以輕鬆地切換使用 kubectl 組態命令的內容。此外,還有可用來進行切換內容更容易 (kubectx 和 kubectxwin) 的開放原始碼公用程式。

一旦已匯入的認證,可以藉由列出使用 kubectl get 節點命令的執行節點測試連線到叢集。您應該會看到類似如下:

> kubectl get nodes
NAME                     STATUS    ROLES     AGE       VERSION
aks-default-34827916-0   Ready     agent     1d        v1.11.2

新增部署的容器登錄密碼

Kubernetes 已儲存的密碼使用的敏感性資料安全的方式。比方說,若要避免 ACR 認證儲存在原始程式碼中,祕密可建立並從 Kubernetes 部署資訊清單參考。若要擷取的 ACR 服務的認證,請執行下列命令:

> az acr credential show --name <REGISTRY_NAME>

接下來,使用 kubectl 來產生祕密 (docker registry),特別是用來儲存 Docker 所提供的認證權杖設計的一種特殊類型。後面的程式碼會建立稱為 my-docker-認證使用的認證,從 ACR 查詢所擷取的密碼。請注意,使用者名稱會區分大小寫,ACR 就變得小寫的內建的系統管理員帳戶的預設值:

> kubectl create secret docker-registry my-docker-creds
  --docker-server=<REGISTRY_NAME>.azurecr.io --docker-username=<REGISTRY_USERNAMEE>
  --docker-password=<REGISTRY_PASSWORD> --docker-email=<ANY_EMAIL>

最後,確認已藉由執行下列命令中建立的祕密:

> kubectl describe secrets my-docker-creds
Name:         my-docker-creds
Namespace:    default
Type:  kubernetes.io/dockerconfigjson
Data
====
.dockerconfigjson:  223 bytes

建立 Docker 容器

在 AKS 中的所有應用程式會部署為 Docker 容器。以下是建立可以寄送到叢集中的 Docker 映像的 Dockerfile 的程式碼:

FROM microsoft/dotnet:2.1-sdk AS builder
COPY . /app
WORKDIR /app
RUN dotnet publish -f netcoreapp2.1 -c Debug -o /publish
FROM microsoft/dotnet:2.1.3-aspnetcore-runtime
COPY --from=builder /publish .
ENTRYPOINT ["/bin/bash", "-c", "dotnet WebApiApp.dll"]

這個 Dockerfile 中使用分割成不同的階段,用於建置和執行階段建置的多階段方法。這可減少整體映像的大小大幅不能包含適用於散發的整個 SDK。

將映像推送至登錄

Docker 適用於本機映像和容器,以執行映像的概念。無法推送 Docker 映像,直接到叢集。相反地,映像必須裝載在可以存取 Kubernetes 叢集,在本機提取映像的位置。ACR 登錄是安全的位置,可讓開發、 持續整合和叢集環境之間集中管理的映像。

必須建置映像,並加上格式 < 登錄 > / < 存放庫 > / < 映像 >: < 標記 > 因此 Docker 會知道上游推送映像的位置。儲存機制,可以使用任何名稱,可用來區隔出登錄成邏輯群組的映像。下列程式碼示範如何建置和標記映像推送至 ACR 之前。雖然支援最新的標記,強烈建議您在使用語意版本設定它使用 Kubernetes 時。它可以讓管理部署和復原更容易,您可以利用版本號碼。請看看下面這個程式碼:

> az acr login --name <REGISTRY_NAME>
> docker build -t <REGISTRY_NAME>.azurecr.io/api/my-webapi-app:1.0 .
> docker push <REGISTRY_NAME>.azurecr.io/api/my-webapi-app:1.0
baf6b1178a5b: Pushed
b3f8eefa2758: Pushed
393dd8f4a879: Pushed
0ad9ffac9ae9: Pushed
8ea427f58308: Pushed
cdb3f9544e4c: Pushed
1.0: digest: sha256:47399f3b2365a9 size: 1579

現在先確認執行已推送上游映像:

> az acr login --name <REGISTRY_NAME>
> az acr repository list --name <REGISTRY_NAME>

部署應用程式

Kubernetes 會使用資訊清單來描述叢集中的每個物件。資訊清單是透過 Kubernetes API 管理的 yaml 檔案。部署資訊清單的類型用來描述資源、 映像的來源和所需的應用程式狀態。[圖 1是簡單的資訊清單,會告訴 Kubernetes 使用,數目的容器所需執行的容器和標籤的執行個體 」,以協助說明在叢集中的應用程式。它也會新增提取遠端的映像時,向 ACR 驗證密碼的名稱。

[圖 1 Deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-webapi-app
spec:
  selector:
    matchLabels:
      app: my-webapi-app
  replicas: 2
  template:
    metadata:
      labels:
        app: my-webapi-app
    spec:
      containers:
      - name: my-webapi-app
        image: <REGISTRY_NAME>.azurecr.io/api/my-webapi-app:1.0
        livenessProbe:
          initialDelaySeconds: 10
          path: /health
          periodSeconds: 5
        ports:
        - containerPort: 80
      imagePullSecrets:
      - name: my-docker-creds

部署資訊清單中的,使用下列命令:

> kubectl apply -f ./deployment.yaml

Kubernetes 會使用稱為 pod 的概念來分組邏輯、 可調整的執行個體,在叢集內的一個或多個容器。一般而言,您將有一個容器,每一 pod。這可讓您獨立地調整您的應用程式的任何服務。常見的誤解就是讓應用程式的所有服務,例如 Web 應用程式和資料庫 — 單一 pod 中。如此一來,不允許您從資料庫中,個別擴充的 Web 前端,您將會因此遺失許多 Kubernetes 的優點。

沒有接受的 pod 中有額外的容器是常見的案例 — 它是稱為 「 側車的概念。想像一下,會遵守您的應用程式容器,並提供計量或記錄的容器。將這兩個容器放在單一 pod 中提供這個執行個體中真正的優點。否則,最好是通常每一 pod 保留一個容器的比率,直到您已充分了解的群組容器的限制 (和優點)。

部署完成後,可以檢查應用程式 pod 的狀態,使用下列命令:

> kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE
my-webapi-app-64cdf6b449-9hsks   2/2       Running   0          2m

請注意,為了滿足複本執行的 pod 的兩個執行個體設定。

建立服務

現在,應用程式的 Docker 容器部署到叢集時,服務,才能使其可。Kubernetes 服務可讓您的 pod 可以探索到叢集內的其他 pod。它會藉由使用叢集的內部 DNS 進行自我登錄。它也提供負載平衡的 pod 複本中,所有,並在 pod 升級期間管理 pod 可用性。服務是非常強大的 Kubernetes 概念所需期間輪流、 藍色/綠色,且 canary 部署升級應用程式提供可用性。下列命令會建立部署的服務:

> kubectl expose deployment/my-webapi-app
service "my-webapi-app" exposed

現在,請執行下列命令來檢視叢集中執行的服務:

> kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
my-web-api   ClusterIP   10.0.0.157   <none>        443/TCP   1d

根據預設,服務才可從叢集中,因此存取的外部 ip 不存在。Kubectl CLI 提供便於開啟本機電腦與叢集之間的 proxy,以互動方式檢查它是否在執行,可以看到這段程式碼:

> kubectl port-forward services/my-webapi-app 8080:80
> curl http://localhost:8080
StatusCode        : 200
StatusDescription : OK
Content           : Hello from our Kubernetes hosted service!

新增 HTTP 路由

Kubernetes 是安全的預設值,您必須明確地公開您想要從叢集外部存取的服務。這是安全性的觀點而言,一種絕佳的設計功能,但會造成混淆的第一次使用者。若要存取叢集內的 HTTP 服務的最常見方式是使用 Kubernetes 輸入控制器。輸入控制器可用來將要求路由至內部主機名稱和透過 HTTP proxy 進入點的路徑為基礎的服務。

加入至 Kubernetes 輸入之前,公開服務的主要方式是使用負載平衡器服務類型。這會導致過多的負載平衡器,其中每個服務 —,每個需要分開管理。輸入叢集中的每個服務可以存取由單一的 Azure Load Balancer,大幅降低成本及複雜度。 

AKS 提供方便的附加元件,才能擴充 Nginx proxy 做為輸入控制器來處理這些要求的叢集。它可透過 Azure CLI,使用下列命令:

> az aks enable-addons --resource-group my-aks-cluster
  --name my-aks-cluster --addons http_application_routing

您可以確認路由服務正在執行的發出命令所示**[圖 2**。

[圖 2 可讓您確認執行路由服務

> kubectl get pods --all-namespaces
NAMESPACE     NAME                                                              READY     
kube-system   addon-http-application-routing-default-http-backend-74d455htfw9   1/1      
kube-system   addon-http-application-routing-external-dns-7cf57b9cc7-lqhl5      1/1     
kube-system   addon-http-application-routing-nginx-ingress-controller-5595b2v   1/1

您應該會看到三個新的控制站清單中。輸入控制器、 外部 DNS 和預設後端。預設後端用來加入現有的服務找不到路由時提供給用戶端的回應。它是 404 找不到處理常式中典型的 ASP.NET 應用程式,非常類似,不同之處在於它會執行為個別的 Docker 容器。值得注意的是,最適合用於實驗 HTTP 附加元件時,它並不適用於實際執行環境。

公開服務

輸入是輸入控制器和輸入定義的組合。每個服務必須告訴輸入控制器如何公開服務的輸入定義。下列命令會取得叢集的 DNS 名稱:

> az aks show --resource-group my-aks-cluster
  --name my-aks-cluster --query
  addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName
  -o table
Result
--------------------------------------
<CLUSTER_PREFIX>.eastus2.aksapp.io

輸入註解 kubernetes.io/ingress.class 通知來處理此規格中,輸入控制器,如中所示**[圖 3**。使用稍早解析叢集 DNS 名稱,將"/"的根路徑以及主機新增子網域。此外,服務名稱和其在內部公開的連接埠必須新增以告知輸入控制器在叢集內將要求路由傳送的位置。

[圖 3 Ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-webapi-app
  annotations:
    kubernetes.io/ingress.class: addon-http-application-routing
spec:
  rules:
  - host: my-webapi-app.<CLUSTER_PREFIX>.eastus2.aksapp.io
    http:
      paths:
      - path: /
        backend:
          serviceName: my-webapi-app
          servicePort: 80

使用此命令時,您可以接著套用輸入資訊清單:

> kubectl apply -f ./ingress.yaml

它可能需要幾分鐘的 DNS 項目,以建立並傳播,因此請耐心等候。可以在 Azure 入口網站中,從檢查 DNS 服務的狀態就像這樣:

> curl http://my-webapi-app.<CLUSTER_PREFIX>.eastus2.aksapp.io
StatusCode        : 200
StatusDescription : OK
Content           : Hello from our Kubernetes hosted service!

總結

到目前為止,我們會有與裝載應用程式 Docker 映像有安全的祕密的 ACR 服務一起執行的單一節點 AKS 叢集。這應該是好的切入點,來探索 Azure AKS 的 Kubernetes 可提供的許多其他功能。我有簡單的原理,「 購買功能可讓您和建置您區分 」。 如您所見,Azure 會簡化 Kubernetes,如此開發人員和 DevOps 專業人員可以專注於更重要的工作。


Chander Dhall*,CEO 的 Cazton 是八次授與的 Microsoft MVP,架構設計和實作解決方案中的 Google 開發人員專業與全球知名的技術領導者。*

感謝您向 Microsoft 提供的這篇文章的技術檢閱:Brendan Burns


MSDN Magazine 論壇中的這篇文章的討論