Szybki start: wdrażanie maszyny wirtualnej platformy Azure za pomocą szablonu i zestawu Azure SDK dla języka Go

Ten przewodnik Szybki start przedstawia sposób wdrażania zasobów z szablonu usługi Azure Resource Manager przy użyciu zestawu Azure SDK dla języka Go. Szablony są migawkami wszystkich zasobów zawartych w grupie zasobów platformy Azure. W ramach tej procedury poznasz funkcje i konwencje zestawu SDK.

Na końcu tego przewodnika znajdują się dane działającej maszyny wirtualnej, na której możesz się zalogować się przy użyciu nazwy użytkownika i hasła.

Uwaga

Aby zobaczyć tworzenie maszyny wirtualnej w języku Go bez użycia szablonu usługi Resource Manager, przejdź do przykładu przedstawiającego sposób tworzenia i konfigurowania wszystkich zasobów maszyn wirtualnych za pomocą zestawu SDK. Zastosowanie szablonu w tym przykładzie umożliwia skupienie się na konwencjach zestawu SDK bez zagłębiania się w zbyt wiele szczegółów dotyczących architektury usługi platformy Azure.

Jeśli nie masz subskrypcji platformy Azure, przed rozpoczęciem utwórz bezpłatne konto.

Uruchamianie usługi Azure Cloud Shell

Azure Cloud Shell to rodzaj interaktywnej powłoki działającej na platformie Azure. Udostępnia ona wstępnie zainstalowane i najczęściej używane narzędzia, które są skonfigurowane do użycia na koncie. Wybierz pozycję Kopiuj , aby skopiować kod, wklej go do usługi Cloud Shell, a następnie naciśnij klawisz Enter, aby go uruchomić.

Istnieje kilka sposobów uruchomienia usługi Cloud Shell:

Wybierz pozycję Wypróbuj w prawym górnym rogu bloku kodu.

Cloud Shell in this article

Otwórz usługę Cloud Shell w swojej przeglądarce.

https://shell.azure.com/bash

Wybierz przycisk Cloud Shell w menu w prawym górnym rogu witryny Azure Portal.

Cloud Shell in the portal

W przypadku instalacji lokalnej interfejsu wiersza polecenia platformy Azure ten przewodnik Szybki start wymaga interfejsu wiersza polecenia w wersji 2.0.28 lub nowszej. Uruchom polecenie az --version, aby upewnić się, że dany interfejs wiersza polecenia spełnia ten wymóg. Jeśli konieczna będzie instalacja lub uaktualnienie interfejsu, zobacz Instalowanie interfejsu wiersza polecenia platformy Azure.

Instalowanie zestawu Azure SDK dla języka Go

Zestaw Azure SDK dla języka Go jest zgodny z językiem Go w wersji 1.8 lub nowszej. W przypadku środowisk korzystających z profilów Azure Stack wymagana jest wersja 1.9 lub nowsza. Jeśli chcesz zainstalować język Go, wykonaj instrukcje instalacji języka Go.

Zestaw Azure SDK dla języka Go i jego zależności można pobrać za pomocą polecenia go get.

go get -u -d github.com/Azure/azure-sdk-for-go/...

Ostrzeżenie

Ciąg Azure w adresie URL musi zaczynać się wielką literą. W przeciwnym razie podczas pracy z zestawem SDK mogą wystąpić problemy związane z wielkością liter. Ciąg Azure musi zaczynać się wielką literą także w Twoich instrukcjach importu.

Tworzenie jednostki usługi

Aby można było zalogować się do platformy Azure za pomocą aplikacji w sposób nieinterakcyjny, potrzebna jest jednostka usługi. Jednostki usługi stanowią część kontroli dostępu na podstawie ról (RBAC) tworzącej unikatową tożsamość użytkownika. Aby utworzyć nową jednostkę usługi za pomocą interfejsu wiersza polecenia, uruchom następujące polecenie:

az ad sp create-for-rbac --role Contributor \
    --scopes /subscriptions/<subscription_id> \
    --sdk-auth > quickstart.auth

Ustaw zmienną środowiskową AZURE_AUTH_LOCATION tak, aby była pełną ścieżką do tego pliku. Następnie zestaw SDK zlokalizuje i odczyta poświadczenia bezpośrednio z tego pliku, bez konieczności wprowadzania zmian ani rejestrowania informacji z jednostki usługi.

Uzyskiwanie kodu

Kod szybkiego startu oraz wszystkie jego zależności można pobrać, korzystając z polecenia go get.

go get -u -d github.com/Azure-Samples/azure-sdk-for-go-samples/quickstarts/deploy-vm/...

Nie trzeba wprowadzać modyfikacji kodu źródłowego, jeśli zmienna AZURE_AUTH_LOCATION została poprawnie ustawiona. Po uruchomieniu program ładuje wszystkie niezbędne informacje dotyczące uwierzytelniania z tego miejsca.

Wykonywanie kodu

Uruchom szybki start za pomocą polecenia go run.

cd $GOPATH/src/github.com/Azure-Samples/azure-sdk-for-go-samples/quickstarts/deploy-vm
go run main.go

Jeśli wdrażanie zakończy się pomyślnie, zostanie wyświetlony komunikat zawierający nazwę użytkownika, adres IP i hasło umożliwiające zalogowanie się na nowo utworzonej maszynie wirtualnej. Spróbuj zalogować się do tej maszyny wirtualnej za pomocą protokołu SSH, aby sprawdzić, czy jest uruchomiona i działa.

Czyszczenie

Wyczyść zasoby utworzone w ramach tego szybkiego startu, usuwając grupę zasobów przy użyciu interfejsu wiersza polecenia.

az group delete -n GoVMQuickstart

Usuń również utworzoną wcześniej jednostkę usługi. W pliku quickstart.auth znajduje się klucz JSON dla elementu clientId. Skopiuj tę wartość do zmiennej środowiskowej CLIENT_ID_VALUE i uruchom następujące polecenie w wierszu polecenia platformy Azure:

az ad sp delete --id ${CLIENT_ID_VALUE}

Tu podaj wartość CLIENT_ID_VALUE pobraną z pliku quickstart.auth.

Ostrzeżenie

Nie można usunąć jednostki usługi dla tej aplikacji pozostawia ją aktywną w dzierżawie firmy Microsoft Entra. Chociaż zarówno nazwa, jak i hasło dla jednostki usługi są generowane jako identyfikatory UUID, upewnij się, że stosujesz dobre rozwiązania w zakresie zabezpieczeń, usuwając wszystkie nieużywane jednostki usługi i aplikacje Firmy Microsoft Entra.

Szczegóły kodu

Działanie kodu szybkiego startu jest podzielone na bloki zmiennych i kilka małych funkcji. Opisano je poniżej.

Zmienne, stałe i typy

Ponieważ przewodnik Szybki start jest używany jako samodzielny dokument, są w nim stosowane stałe i zmienne.

const (
    resourceGroupName     = "GoVMQuickstart"
    resourceGroupLocation = "eastus"

    deploymentName = "VMDeployQuickstart"
    templateFile   = "vm-quickstart-template.json"
    parametersFile = "vm-quickstart-params.json"
)

// Information loaded from the authorization file to identify the client
type clientInfo struct {
    SubscriptionID string
    VMPassword     string
}

var (
    ctx        = context.Background()
    clientData clientInfo
    authorizer autorest.Authorizer
)

Deklarowane wartości zapewniają nazwy utworzonych zasobów. Podano tutaj także lokalizację. Można ją zmienić, aby sprawdzić zachowanie wdrożeń w innych centrach danych. Nie każde centrum danych ma dostępne wszystkie wymagane zasoby.

Typ clientInfo przechowuje informacje załadowane z pliku uwierzytelniania w celu skonfigurowania klientów w zestawie SDK i ustawienia hasła maszyny wirtualnej.

Stałe templateFile i parametersFile wskazują pliki potrzebne do wdrożenia. Element authorizer zostanie skonfigurowany przez zestaw SDK języka Go w celu uwierzytelnienia, a zmienna ctx to kontekst języka Go dla operacji sieciowych.

Uwierzytelnianie i inicjowanie

Funkcja init konfiguruje uwierzytelnianie. Uwierzytelnianie jest warunkiem wstępnym w każdym procesie szybkiego startu, a zatem warto uczynić je częścią inicjowania. Powoduje ono również pobieranie niektórych potrzebnych informacji z pliku uwierzytelniania w celu skonfigurowania klientów i maszyny wirtualnej.

func init() {
    var err error
    authorizer, err = auth.NewAuthorizerFromFile(azure.PublicCloud.ResourceManagerEndpoint)
    if err != nil {
        log.Fatalf("Failed to get OAuth config: %v", err)
    }

    authInfo, err := readJSON(os.Getenv("AZURE_AUTH_LOCATION"))
    clientData.SubscriptionID = (*authInfo)["subscriptionId"].(string)
    clientData.VMPassword = (*authInfo)["clientSecret"].(string)
}

Najpierw plik auth.NewAuthorizerFromFile jest wywoływany w celu załadowania informacji dotyczących uwierzytelniania z pliku znajdującego się w lokalizacji AZURE_AUTH_LOCATION. Następnie ten plik jest ładowany ręcznie przez funkcję readJSON (pominiętą w tym miejscu) w celu ściągnięcia dwóch wartości potrzebnych do uruchomienia pozostałej części programu: identyfikator subskrypcji klienta i wpis tajny jednostki usługi, który jest również używany na potrzeby hasła maszyny wirtualnej.

Ostrzeżenie

W celu uproszczenia przewodnika Szybki start zostanie ponownie użyte hasło jednostki usługi. Pamiętaj, aby w środowisku produkcyjnym nigdy nie używać ponownie hasła zapewniającego dostępu do zasobów platformy Azure.

Przepływ operacji w funkcji main()

Funkcja main jest prosta — wskazuje tylko przepływ operacji i przeprowadza sprawdzanie błędów.

func main() {
    group, err := createGroup()
    if err != nil {
        log.Fatalf("failed to create group: %v", err)
    }
    log.Printf("Created group: %v", *group.Name)

    log.Printf("Starting deployment: %s", deploymentName)
    result, err := createDeployment()
    if err != nil {
        log.Fatalf("Failed to deploy: %v", err)
    }
    if result.Name != nil {
        log.Printf("Completed deployment %v: %v", deploymentName, *result.Properties.ProvisioningState)
    } else {
        log.Printf("Completed deployment %v (no data returned to SDK)", deploymentName)
    }
    getLogin()
}

Oto działania wykonywane przez kod (z zachowaniem kolejności):

  • Utworzenie grupy zasobów, w której ma zostać przeprowadzone wdrażanie (createGroup)
  • Utworzenie wdrożenia w tej grupie (createDeployment)
  • Uzyskiwanie i wyświetlanie danych logowania dotyczących wdrożonej maszyny wirtualnej (getLogin)

Tworzenie grupy zasobów

Funkcja createGroup umożliwia utworzenie grupy zasobów. Przepływ wywołań i argumenty pozwalają zapoznać się ze strukturą interakcji z usługami w zestawie SDK.

func createGroup() (group resources.Group, err error) {
    groupsClient := resources.NewGroupsClient(clientData.SubscriptionID)
    groupsClient.Authorizer = authorizer

        return groupsClient.CreateOrUpdate(
                ctx,
                resourceGroupName,
                resources.Group{
                        Location: to.StringPtr(resourceGroupLocation)})
}

Ogólny przebieg interakcji z usługą platformy Azure wygląda następująco:

  • Utworzenie klienta przy użyciu metody service.New*Client(), gdzie * to typ zasobu service, z którym ma nastąpić interakcja. Ta funkcja zawsze pobiera identyfikator subskrypcji.
  • Ustawienie metody autoryzacji klienta z uwzględnieniem interakcji ze zdalnym interfejsem API.
  • Wywołanie metody na kliencie odpowiadającym zdalnemu interfejsowi API. Metody klienta usługi zazwyczaj pobierają nazwę zasobu i obiektu metadanych.

Funkcja to.StringPtr służy tutaj do przeprowadzania konwersji typów. Parametry metod zestawu SDK przyjmują niemal wyłącznie wskaźniki, dlatego są udostępniane są metody ułatwiające konwersję typów. Pełną listę konwerterów i opis ich zachowania można znaleźć w dokumentacji modułu autorest/to.

Metoda groupsClient.CreateOrUpdate zwraca wskaźnik do typu danych reprezentującego grupę zasobów. Bezpośrednia zwracana wartość tego rodzaju wskazuje krótkotrwałą operację, która ma być synchroniczna. W następnej sekcji przedstawimy przykład długotrwałej operacji i sposób interakcji z nią.

Wykonywanie wdrożenia

Po utworzeniu grupy zasobów można uruchomić wdrożenie. Ten kod został podzielony na mniejsze części w celu wyróżnienia różnych części logiki kodu.

func createDeployment() (deployment resources.DeploymentExtended, err error) {
    template, err := readJSON(templateFile)
    if err != nil {
        return
    }
    params, err := readJSON(parametersFile)
    if err != nil {
        return
    }
    (*params)["vm_password"] = map[string]string{
        "value": clientData.VMPassword,
    }
        // ...

Pliki wdrożenia są ładowane przez element readJSON (szczegóły zostały tutaj pominięte). Ta funkcja zwraca typ *map[string]interface{} używany podczas tworzenia metadanych dla wywołania wdrażania zasobów. Hasło maszyny wirtualnej jest również ustawiane ręcznie w obszarze parametrów wdrożenia.

        // ...

    deploymentsClient := resources.NewDeploymentsClient(clientData.SubscriptionID)
    deploymentsClient.Authorizer = authorizer

    deploymentFuture, err := deploymentsClient.CreateOrUpdate(
        ctx,
        resourceGroupName,
        deploymentName,
        resources.Deployment{
            Properties: &resources.DeploymentProperties{
                Template:   template,
                Parameters: params,
                Mode:       resources.Incremental,
            },
        },
    )
    if err != nil {
        return
    }

Ten kod jest zgodny z tym samym wzorcem używanym podczas tworzenia grupy zasobów. Zostaje utworzony nowy klient (pod warunkiem, że uwierzytelnienie w usłudze Azure jest możliwe), a następnie zostaje wywołana metoda. Metoda ma nawet taką samą nazwę (CreateOrUpdate) co analogiczna metoda dotycząca grupy zasobów. Ten wzorzec jest widoczny w zestawie SDK. Metody, które mają podobne działanie, mają zwykle taką samą nazwę.

Największa różnica dotyczy wartości zwracanej przez metodę deploymentsClient.CreateOrUpdate. Ta wartość ma typ Future zgodny z wzorcem projektowym obiektu future. Obiekty future reprezentują długotrwałą operację na platformie Azure, którą można sondować, anulować lub blokować po ich wykonaniu.

        //...
    err = deploymentFuture.Future.WaitForCompletion(ctx, deploymentsClient.BaseClient.Client)
    if err != nil {
        return
    }
    return deploymentFuture.Result(deploymentsClient)
}

W przypadku tego przykładu najlepiej zaczekać na ukończenie operacji. Oczekiwanie na obiekt future wymaga zarówno obiektu kontekstu, jak i klienta, który utworzył obiekt Future. Istnieją tutaj dwa możliwe źródła błędu: błąd występujący po stronie klienta podczas próby wywołania metody oraz odpowiedź serwera z informacją o błędzie. Ta druga jest zwracana jako część wywołania deploymentFuture.Result.

Uzyskiwanie przypisanego adresu IP

Aby można było korzystać z nowo utworzonej maszyny wirtualnej, trzeba mieć przypisany adres IP. Adresy IP stanowią oddzielne zasoby platformy Azure powiązane z zasobami kontrolera interfejsu sieciowego.

func getLogin() {
    params, err := readJSON(parametersFile)
    if err != nil {
        log.Fatalf("Unable to read parameters. Get login information with `az network public-ip list -g %s", resourceGroupName)
    }

    addressClient := network.NewPublicIPAddressesClient(clientData.SubscriptionID)
    addressClient.Authorizer = authorizer
    ipName := (*params)["publicIPAddresses_QuickstartVM_ip_name"].(map[string]interface{})
    ipAddress, err := addressClient.Get(ctx, resourceGroupName, ipName["value"].(string), "")
    if err != nil {
        log.Fatalf("Unable to get IP information. Try using `az network public-ip list -g %s", resourceGroupName)
    }

    vmUser := (*params)["vm_user"].(map[string]interface{})

    log.Printf("Log in with ssh: %s@%s, password: %s",
        vmUser["value"].(string),
        *ipAddress.PublicIPAddressPropertiesFormat.IPAddress,
        clientData.VMPassword)
}

Ta metoda korzysta z informacji przechowywanych w pliku parametrów. Kod może wysłać zapytanie bezpośrednio do maszyny wirtualnej, aby uzyskać dane jej kontrolera interfejsu sieciowego, wysłać zapytanie do kontrolera interfejsu sieciowego, aby uzyskać jego adres IP, a następnie wysłać zapytanie bezpośrednio do zasobu z danym adresem IP. Jest to długi łańcuch zależności. Wymaga on wykonania wielu operacji, przez co jest kosztowny. Ponieważ dane JSON są lokalne, można je załadować zamiast wykonywania powyższych operacji.

Wartość dla użytkownika maszyny wirtualnej jest również ładowana z kodu JSON. Hasło maszyny wirtualnej zostało wcześniej załadowane z pliku uwierzytelniania.

Następne kroki

W tym przewodniku Szybki start istniejący szablon został wdrożony za pomocą języka Go. Następnie nastąpiło nawiązanie połączenia z nowo utworzoną maszyną wirtualną za pośrednictwem protokołu SSH.

Aby uzyskać więcej informacji o pracy z maszynami wirtualnymi w środowisku platformy Azure z użyciem języka Go, zapoznaj się z przykładami dotyczącymi obliczeń na platformie Azure dla języka Go lub przykładami dotyczącymi zarządzania zasobami na platformie Azure dla języka Go.

Aby dowiedzieć się więcej na temat metod uwierzytelniania dostępnych w zestawie SDK oraz obsługiwanych przez typów uwierzytelniania, zobacz Uwierzytelnianie przy użyciu zestawu Azure SDK dla języka Go.