In diesem Artikel

Kubernetes zu meistern ist hart und zeitaufwendig. Mit Kubernetes in Azure als .NET Core-Entwickler zu beginnen ist hingegen relativ einfach. Man benötigt sechs Schritte, um eine Anwendung in Azure Kubernetes Service (AKS) zu starten und zum Laufen zu bringen, beginnend mit einer einfachen .NET Core Web API.

Dieser Artikel führt Sie durch den gesamten Prozess und erklärt alle Schritte im Detail, damit Sie verfolgen können, wie Ihre Anwendung in Kubernetes ausgeführt und über das Internet bereitgestellt wird.

Dieser Artikel ist eine deutsche Übersetzung. Den Originalartikel in englischer Sprache finden Sie in Thorsten Hans' Blog.

Thematischer Rahmen

Die Idee ist, Sie in diesem Artikel innerhalb weniger Absätze fit zu machen, um starten zu können. Um dies zu erreichen, sind einige wichtige Themen nicht Gegenstand dieses Artikels. Sie müssen sich jedoch um Diese kümmern, wenn Sie sowohl Docker-Images als auch Ihre Azure-Infrastruktur für die Produktionsumgebung erstellen.

Um nur einige dieser Themen zu nennen:

  • Docker-Images absichern
  • Minimieren der Image-Layer und Größe von Docker-Images
  • Absicherung der Azure Container Registry (ACR)
  • Absicherung von Azure Kubernetes Service (AKS)
  • Verwenden eines dedizierten Ingress-Controllers zum Weiterleiten von eingehendem Datenverkehr in AKS
  • Kontinuierliche Überwachung mit dem Azure Security Center

Zu Demonstrationszwecken nutze ich den von Microsoft erstellten „Weather Forecast" Web-API-Blueprint durch die Verwendung von dotnet new webapi -lang c# -n HelloAKS.

Version Information:

  • .NET Core 3.1 (Vorgehensweise für .NET 5.0 ist äquivalent)

Anforderungen

Um dieser Anleitung zu folgen, sollten auf Ihrem Computer drei Dinge installiert und konfiguriert sein:

  • Docker
  • Azure CLI 2.0
  • Ein Editor (ich verwende Visual Studio Code)

Wenn diese Tools installiert und konfiguriert sind, können wir loslegen und die .NET Core-Anwendung in einen neuen AKS-Cluster bringen.

1. Ein Docker-Image erzeugen

Mit der neu erzeugten .NET Core-Anwendung auf Ihrem lokalen Computer, müssen Sie anschließend ein Docker-Image erzeugen. Erstellen Sie dazu zwei neue Dateien im Hauptprojektordner: Dockerfile und .dockerignore. Bevor wir mit dem Schreiben des Dockerfile beginnen, fügen wir einige typische Patterns für .NET-Anwendungen zur .dockerignore hinzu, um zu verhindern, dass diese Dateien und Ordner beim Erstellen des Docker-Images an den Docker Daemon übertragen werden:

# .dockerignore
/bin/
/obj/

Das Erstellen von Docker-Images für .NET Core-Anwendungen ist unkompliziert. Microsoft stellt alle erforderlichen Base-Images bereit, damit Ihre Anwendung in einem Linux-basierten Container ausgeführt werden kann. Wir werden ein sogenanntes mehrstufiges Docker-Image erstellen.

Das bedeutet, dass wir mit einem Basis-Image beginnen, welches das .NET Core SDK enthält, um die Anwendung in diesem Image zu kompilieren und zu veröffentlichen. Sobald dies erledigt ist, nutzen wir ein weiteres Basis-Image nur mit allen erforderlichen Dingen, um .NET Core-Anwendungen auszuführen, und kopieren unsere zuvor veröffentlichte Anwendung in das neue Basis-Image. Von hier aus exponieren wir den gewünschten Port und starten die Anwendung.

Wenn wir diesem Pattern folgen, können wir die Größe des resultierenden Docker-Images deutlich reduzieren, wie Sie hier sehen können:

mcr.microsoft.com/dotnet/core/sdk      3.1-buster         a0dbfc5da130    692MB
mcr.microsoft.com/dotnet/core/aspnet   3.1-buster-slim    4bee399eb313    207MB

Nun widmen wir uns dem Dockerfile, fügen Sie den folgenden Inhalt ein:

#Dockerfile

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS builder
WORKDIR /src
COPY ./HelloAKS.csproj .
RUN dotnet restore HelloAKS.csproj
COPY . .
RUN dotnet build HelloAKS.csproj -c Debug -o /src/out

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim
WORKDIR /app
COPY --from=builder /src/out .

EXPOSE 80
ENTRYPOINT ["dotnet", "HelloAKS.dll"]

Jetzt erstellen wir das Docker-Image mithilfe der Docker CLI:

# build Docker image
docker build . -t HelloAKS:0.0.1
# Watch Docker

# pulling the images from MCR if they are not on your machine
# building .NET Application and creating the Docker Image

Nun da wir ein Docker-Image haben (Sie können jederzeit alle Docker-Images auf Ihrem System mithilfe von docker images auflisten), können wir zum nächsten Schritt weitergehen.

2. Erstellen einer ACR Instanz

Ich verwende zur Bereitstellung des Images die ACR, da es sich gut in AKS, Azure Active Directory (Azure AD), Azure Security Center (ASC) und andere Dienste integrieren lässt. Wenn Sie sich ACR gründlicher widmen möchten, lesen Sie die Artikel meiner Azure Container Registry Unleashed Artikelserie.

Wir werden alle unseren Azure-Ressourcen in einer dedizierten Azure-Ressourcengruppe namens hello-aks gruppieren. Wir erstellen diese mit dem Azure CLI:

# create the resource group
az group create -n hello-aks -l westeurope

Sobald die Ressourcengruppe erstellt wurde, können wir eine neue ACR-Instanz provisionieren. Für diesen Artikel genügt eine „Basic" Edition, die ca 0,15 Euro pro Tag kostet. Der Name einer ACR-Instanz muss weltweit eindeutig sein. Sie sollten daher az acr check-name verwenden, um zu überprüfen, ob der gewünschte Service-Name noch verfügbar ist.

# check if your desired name is available
az acr check-name -n thorstenhans

# create the ACR instance
az acr create -n thorstenhans \
  -g hello-aks \
  --admin-enabled false \
  --sku Basic

Nach dem Erstellen der ACR sollten Sie den folgenden Befehl verwenden, um die eindeutige Cloud-Ressourcen-ID in einer Variablen zu speichern. Wir werden die ID in ein paar Minuten brauchen:

# store unique ACR id in ACR_ID
ACR_ID=$(az acr show -n thorstenhans -g hello-aks --query id -o tsv)

3. Docker-Image in die ACR schieben

Wir können das zuvor erstellte Docker-Image nicht einfach so in die Azure Container Registry pushen. Docker-Images müssen den ACR-Image-Namenskonventionen (unique-acr-name.azurecr.io/imagename:tag) folgen, um sie in die ACR zu veröffentlichen. Wir können unser Image ganz einfach mit docker tag neu taggen, wie hier gezeigt:

# re-tag the existing Docker Image
docker tag hello-aks:0.0.1 thorstenhans.azurecr.io/hello-aks:0.0.1

Außerdem müssen wir uns für den Zugriff auf die ACR authentifizieren:

# authenticate against ACR
az acr login -n thorstenhans

Sobald die Anmeldung erfolgreich war, verwenden wir die Standard-Docker-Befehle, um unser Docker-Image in die ACR zu pushen. Docker weiß aufgrund des ACR- Präfixes, wohin das Image während des push-Vorgangs geleitet werden muss.

# push the docker image to ACR
docker push thorstenhans.azurecr.io/hello-aks:0.0.1

Sie können entweder die Azure CLI oder das Azure-Portal verwenden, um zu überprüfen, ob das Docker-Image in die ACR veröffentlicht wurde. (az acr repository list -n thorstenhans)

Azure Container Registry - Docker Image in ACR

4. Einen Kubernetes Cluster erstellen

Wir verwenden nun die Azure CLI, um einen neuen AKS-Cluster zu erstellen. Zu Demonstrationszwecken besteht unser Cluster nur aus einem einzigen Worker-Node. Das Betreiben eines Kubernetes Clusters mit einem einzelnen Worker-Node wird nicht für Produktionsszenarien empfohlen. Ich mache es hier nur, um die Gesamtkosten der Azure-Dienste so gering wie möglich zu halten. Als Teil des Erstellungsprozesses werden wir auch unsere ACR-Instanz an AKS anhängen. Dies ist auch mit vorhandenen AKS-Clustern mit dem Befehl az aks update möglich.

# create the AKS cluster
az aks create -n aks-demo \
  -g hello-aks \
  --enable-managed-identity \
  --attach-acr $ACR_ID \
  --node-count 1

Wenn die Azure CLI die Bereitstellung des AKS-Clusters abgeschlossen hat (dies kann einige Minuten dauern), müssen wir kubectl (die Kubernetes CLI) einrichten, welche Sie für die Kommunikation mit einem beliebigen Kubernetes Cluster verwenden. Wenn Sie kubectl bereits installiert haben, können Sie den folgenden Befehl überspringen und mit dem Herunterladen der Cluster-Konfiguration für kubectl fortfahren.

# Install kubectl
az aks install-cli

Sobald kubectl auf Ihrem Rechner installiert ist, benötigen wir die Konfiguration für den aks-demo Cluster. Auch hier bietet Azure CLI den entsprechenden Befehl:

# download cluster configuration for kubectl
az aks get-credentials \
  -n aks-demo \
  -g hello-aks

# verify kubectl context
kubectl config get-contexts
# prints all cluster contexts

# if kubectl does not point to aks-demo, switch context
kubectl config use-context aks-demo

5. Kubernetes Bereitstellungs-Manifeste erstellen

In Kubernetes stellen wir Docker-Images nicht direkt bereit. Die kleinste Arbeitseinheit in Kubernetes ist ein sogenannter Pod. Ein Pod bietet eine Reihe von Konfigurationsmöglichkeiten, um den gesamten Lebenszyklus einer containerisierten Anwendung zu steuern.

Wenn Sie Kubernetes gründlicher kennenlernen, lernen Sie andere Bausteine wie ReplicaSet oder Deployment kennen, die Wrapper für einen Pod sind. Diese fügen noch mehr Funktionen wie Replikationen und feingranulare Aktualisierungsstrategien hinzu. Aber jetzt beginnen wir mit Ihrem ersten Pod. Erstellen Sie im Hauptordner eine neue Datei mit dem Namen pod.yml und fügen Sie den folgenden Inhalt hinzu. Wir werden die wichtigsten Teile in Kürze besprechen.

# pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: first-netcore-app
  labels:
    app: hello-aks
    component: netcore-app
spec:
  containers:
    - image: thorstenhans.azurecr.io/hello-aks:0.0.1
      name: webapi
      ports:
        - containerPort: 80

Wie Sie sehen, haben wir für unseren Pod zwei Labels angegeben. app: hello-aks und component: netcore-app. In Kubernetes verwenden wir Labels und Label-Selektoren, um Komponenten lose zu koppeln. Labels sind super-effizient und dennoch einfach. Betrachten Sie diese als Klebezettel, die Sie in diesem Fall an verschiedene Dinge wie den Pod anbringen.

Die spec beschreibt die tatsächlichen Eigenschaften des Pods. Hier spezifizieren wir unser zuvor veröffentlichtes Image und konfigurieren die Port-Freigabe. Wir weisen Kubernetes an, Netzwerkverkehr für unseren Docker Container auf Port 80 zuzulassen.

Neben dem Pod möchten wir unsere API der Öffentlichkeit zugänglich machen. Um Pods zugänglich zu machen (entweder im ganzen Cluster oder extern), müssen wir einen Service in Kubernetes erstellen. Erstellen Sie erneut im Stammordner des Projekts eine neue Datei namens service.yml und fügen Sie Folgendes hinzu:

# service.yml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-aks
  name: hello-aks
spec:
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 80
  selector:
    app: hello-aks
    component: netcore-app
  type: LoadBalancer

Bei der Überprüfung der Service-Definition sollten Sie sich auf spec konzentrieren. Die spec definiert, dass wir einen Service vom Typ LoadBalancer erstellen wollen. Dadurch wird Azure angewiesen, eine öffentliche IP-Adresse zuzuweisen, einen Azure Load Balancer zu erstellen und Datenverkehr aus dem öffentlichen Internet an unseren Kubernetes Cluster zu leiten.

Kubernetes unterstützt verschiedene Arten von Services. In realen Projekten verwenden Sie normalerweise keinen LoadBalancer; Stattdessen verwenden Sie einen Ingress Controller (wie beispielsweise NGINX Ingress), der den eingehenden Datenverkehr steuert. Interne Services des Clusters wären vom Typ NodePort oder ClusterIP.

Der Teil spec.selector definiert, wohin der Datenverkehr geleitet werden soll. Diese Konfiguration leitet den gesamten Verkehr auf Port 8080 an Port 80 zu allen Artefakten innerhalb des Clusters weiter, denen die Labels app: hello-aks und component:netcore-app zugeordnet sind.

Sie haben somit gerade beschrieben, dass der Netzwerkverkehr dynamisch in Ihren Cluster geleitet wird, ohne die Ressourcen eng miteinander zu verbinden. Wenn alles bereit ist, können wir zum letzten Schritt übergehen und alles in AKS bereitstellen.

6. Ihre Anwendung bereitstellen

Die Bereitstellung von Artefakten in Kubernetes ist unkompliziert; wir verwenden kubectl apply, um alles in Kubernetes bereitzustellen.

# deploy artifacts to AKS
kubectl apply -f pod.yml
kubectl apply -f service.yml

Kubernetes wird nun den Service hochfahren und unser Docker-Image aus ACR abrufen, um den Pod zu instanziieren. Insbesondere die Erstellung des Services kann einige Zeit in Anspruch nehmen, da die öffentliche IP zugewiesen und der Load Balancer bereitgestellt werden müssen. Sie können mit kubectl alle Services beobachten und warten, bis die externe IP zugeordnet ist.

# wait for service to receive its external IP
kubectl get svc -w

NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
hello-aks    LoadBalancer   10.0.139.177   51.105.199.90   8080:31924/TCP   10m
kubernetes   ClusterIP      10.0.0.1       <none>          443/TCP          16m

Sobald Sie die dem Service zugewiesene externe IP sehen, können Sie die Überwachung der Dienste mit [CTRL]+C beenden und eine Anforderung zum Abrufen von Wetterdaten von unserer .NET Core-Anwendung mit curl starten:

# get weather data from ASP.NET Core API in AKS
curl http://51.105.199.90:8080/weatherforecast | jq

[
    {
        "date": "2020-06-07T10:18:16.0014666+00:00",
        "temperatureC": -11,
        "temperatureF": 13,
        "summary": "Sweltering"
    },
    {
        "date": "2020-06-08T10:18:16.0014937+00:00",
        "temperatureC": 34,
        "temperatureF": 93,
        "summary": "Hot"
    },
    {
        "date": "2020-06-09T10:18:16.0015069+00:00",
        "temperatureC": 28,
        "temperatureF": 82,
        "summary": "Chilly"
    },
    {
        "date": "2020-06-10T10:18:16.0015195+00:00",
        "temperatureC": 41,
        "temperatureF": 105,
        "summary": "Warm"
    },
    {
        "date": "2020-06-11T10:18:16.0015348+00:00",
        "temperatureC": -4,
        "temperatureF": 25,
        "summary": "Warm"
    }
]

Sie sollten Ihren Pod auch mit kubectl get pods überprüfen. Hier sollten Sie -o wide anhängen, um die IP-Adresse des Pods zu erhalten. Um die Verbindung zwischen dem Dienst und dem Pod anzuzeigen, können Sie mit kubectl get endpoints nach Endpunkten suchen:

# get pods and endpoints
kubectl get pods -o wide
NAME                READY   STATUS    RESTARTS   AGE     IP
first-netcore-app   1/1     Running   0          6m58s   10.244.0.10

kubectl get endpoints
NAME         ENDPOINTS          AGE
hello-aks    10.244.0.10:80     15m
kubernetes   20.50.227.85:443   21m

Beachten Sie, dass der Endpunkt auf die IP-Adresse und den Port des Pods verweist.

Zusammenfassung

Das wäre geschafft. Sie haben sechs Schritte zum Einrichten und Ausführen Ihrer .NET Core Web-API in Kubernetes gesehen. Dies ist ein guter Ausgangspunkt. Von hier aus können Sie weitergehen und Funktionen wie Deployments, ConfigMaps und Secrets in Kubernetes anwenden. Darüber hinaus sollten Sie sich mit Dingen wie Systemdiagnosen, Ressourcenanforderungen und -limits befassen, um die Leistungsfähigkeit von Kubernetes auszuschöpfen und Ihre containerisierte Anwendung grundsolide zu machen.

Den gesamten Code dieses Artikels finden Sie im Projektarchiv auf GitHub unter https://github.com/ThorstenHans/six-steps-to-aks

Wenn Sie keine Artikel, Webinare und Screencast von meinen Kollegen und mir verpassen möchten, melden Sie sich zu unserem Dev-Newsletter an.

Related Articles

 | Thorsten Hans

Der Cluster Autoscaler für Azure Kubernetes Service (AKS) ist bereits seit geraumer Zeit verfügbar. Ich habe ihn bereits für mehrere Projekte verwendet. Dieser Beitrag erklärt alle Details des AKS Cluster Autoscalers. Er beschreibt, wie Sie ihn sowohl für neue als auch für…

Read article
 | Thorsten Hans

What is KEDA KEDA stands for Kubernetes Event-driven Autoscaling. It is a thin layer built on top of Kubernetes to scale applications dynamically based on metrics from external systems. Although it comes with first-class support for Azure Functions, it is not limited to Azure…

Read article
 | Steffen Jahr

Article Series Part 1: Introduction to Azure Cognitive Search Part 2: The search index Part 3: Index your Data Part 4: Integrate Azure Cognitive Search Into Your Application ⬅ To search the data, Azure Cognitive Search offers different ways (also different query types) to query…

Read article