Sağlama aracısı olmadan genelleştirilmiş görüntüler oluşturma

Şunlar için geçerlidir: ✔️ Linux VM'leri ✔️ Esnek ölçek kümeleri

Microsoft Azure, Linux VM'leri için walinuxagent veya cloud-init biçiminde sağlama aracıları sağlar (önerilir). Ancak sağlama aracınız için bu uygulamalardan herhangi birini kullanmak istemediğiniz bir senaryo olabilir, örneğin:

  • Linux dağıtımınız/sürümünüz cloud-init/Linux Agent'ı desteklemiyor.
  • Konak adı gibi belirli VM özelliklerinin ayarlanması gerekir.

Not

Herhangi bir özelliğin ayarlanmasını veya herhangi bir sağlama biçiminin gerçekleşmesini istemiyorsanız, özel bir görüntü oluşturmayı düşünmelisiniz.

Bu makalede, sağlama aracısı yüklemeden Azure platform gereksinimlerini karşılamak ve konak adını ayarlamak için VM görüntünüzü nasıl ayarlayabileceğiniz gösterilir.

Ağ ve raporlama hazır

Linux VM'nizin Azure bileşenleriyle iletişim kurmasını sağlamak için bir DHCP istemcisi gerekir. İstemci, sanal ağdan bir ana bilgisayar IP'sini, DNS çözümlemesini ve yol yönetimini almak için kullanılır. Dağıtımların çoğu bu yardımcı programlarla birlikte kullanıma açılır. Linux dağıtım satıcıları tarafından Azure'da test edilen araçlar arasında , network-managersystemd-networkd ve diğerleri bulunurdhclient.

Not

Şu anda sağlama aracısı olmadan genelleştirilmiş görüntüler oluşturulurken yalnızca DHCP özellikli VM'ler desteklenir.

Ağ ayarlandıktan ve yapılandırıldıktan sonra "rapor hazır" seçeneğini belirleyin. Bu, Azure'a VM'nin başarıyla sağlandığını bildirir.

Önemli

Azure'a hazır raporun başarısız olması VM'nizin yeniden başlatılmasına neden olur!

Tanıtım/örnek

Linux Aracısı (walinuxagent) kaldırılmış ve özel python betiği eklenmiş mevcut bir Market görüntüsü (bu örnekte bir Debian Buster VM), Azure'a VM'nin "hazır" olduğunu söylemenin en kolay yoludur.

Kaynak grubunu ve temel VM'yi oluşturun:

$ az group create --location eastus --name demo1

Temel VM'yi oluşturma:

$ az vm create \
    --resource-group demo1 \
    --name demo1 \
    --location eastus \
    --ssh-key-value <ssh_pub_key_path> \
    --public-ip-address-dns-name demo1 \
    --image "debian:debian-10:10:latest"

Görüntü sağlama Aracısını kaldırma

VM sağlandıktan sonra SSH aracılığıyla vm'ye bağlanabilir ve Linux Aracısı'nı kaldırabilirsiniz:

$ sudo apt purge -y waagent
$ sudo rm -rf /var/lib/waagent /etc/waagent.conf /var/log/waagent.log

Vm'ye gerekli kodu ekleme

Ayrıca VM'nin içinde, Azure Linux Aracısı'nı kaldırdığımız için hazır raporlamaya yönelik bir mekanizma sağlamamız gerekir.

Python betiği

import http.client
import sys
from xml.etree import ElementTree

wireserver_ip = '168.63.129.16'
wireserver_conn = http.client.HTTPConnection(wireserver_ip)

print('Retrieving goal state from the Wireserver')
wireserver_conn.request(
    'GET',
    '/machine?comp=goalstate',
    headers={'x-ms-version': '2012-11-30'}
)

resp = wireserver_conn.getresponse()

if resp.status != 200:
    print('Unable to connect with wireserver')
    sys.exit(1)

wireserver_goalstate = resp.read().decode('utf-8')

xml_el = ElementTree.fromstring(wireserver_goalstate)

container_id = xml_el.findtext('Container/ContainerId')
instance_id = xml_el.findtext('Container/RoleInstanceList/RoleInstance/InstanceId')
incarnation = xml_el.findtext('Incarnation')
print(f'ContainerId: {container_id}')
print(f'InstanceId: {instance_id}')
print(f'Incarnation: {incarnation}')

# Construct the XML response we need to send to Wireserver to report ready.
health = ElementTree.Element('Health')
goalstate_incarnation = ElementTree.SubElement(health, 'GoalStateIncarnation')
goalstate_incarnation.text = incarnation
container = ElementTree.SubElement(health, 'Container')
container_id_el = ElementTree.SubElement(container, 'ContainerId')
container_id_el.text = container_id
role_instance_list = ElementTree.SubElement(container, 'RoleInstanceList')
role = ElementTree.SubElement(role_instance_list, 'Role')
instance_id_el = ElementTree.SubElement(role, 'InstanceId')
instance_id_el.text = instance_id
health_second = ElementTree.SubElement(role, 'Health')
state = ElementTree.SubElement(health_second, 'State')
state.text = 'Ready'

out_xml = ElementTree.tostring(
    health,
    encoding='unicode',
    method='xml'
)
print('Sending the following data to Wireserver:')
print(out_xml)

wireserver_conn.request(
    'POST',
    '/machine?comp=health',
    headers={
        'x-ms-version': '2012-11-30',
        'Content-Type': 'text/xml;charset=utf-8',
        'x-ms-agent-name': 'custom-provisioning'
    },
    body=out_xml
)

resp = wireserver_conn.getresponse()
print(f'Response: {resp.status} {resp.reason}')

wireserver_conn.close()

Bash betiği

#!/bin/bash

attempts=1
until [ "$attempts" -gt 5 ]
do
    echo "obtaining goal state - attempt $attempts"
    goalstate=$(curl --fail -v -X 'GET' -H "x-ms-agent-name: azure-vm-register" \
                                        -H "Content-Type: text/xml;charset=utf-8" \
                                        -H "x-ms-version: 2012-11-30" \
                                           "http://168.63.129.16/machine/?comp=goalstate")
    if [ $? -eq 0 ]
    then
       echo "successfully retrieved goal state"
       retrieved_goal_state=true
       break
    fi
    sleep 5
    attempts=$((attempts+1))
done

if [ "$retrieved_goal_state" != "true" ]
then
    echo "failed to obtain goal state - cannot register this VM"
    exit 1
fi

container_id=$(grep ContainerId <<< "$goalstate" | sed 's/\s*<\/*ContainerId>//g' | sed 's/\r$//')
instance_id=$(grep InstanceId <<< "$goalstate" | sed 's/\s*<\/*InstanceId>//g' | sed 's/\r$//')

ready_doc=$(cat << EOF
<?xml version="1.0" encoding="utf-8"?>
<Health xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <GoalStateIncarnation>1</GoalStateIncarnation>
  <Container>
    <ContainerId>$container_id</ContainerId>
    <RoleInstanceList>
      <Role>
        <InstanceId>$instance_id</InstanceId>
        <Health>
          <State>Ready</State>
        </Health>
      </Role>
    </RoleInstanceList>
  </Container>
</Health>
EOF
)

attempts=1
until [ "$attempts" -gt 5 ]
do
    echo "registering with Azure - attempt $attempts"
    curl --fail -v -X 'POST' -H "x-ms-agent-name: azure-vm-register" \
                             -H "Content-Type: text/xml;charset=utf-8" \
                             -H "x-ms-version: 2012-11-30" \
                             -d "$ready_doc" \
                             "http://168.63.129.16/machine?comp=health"
    if [ $? -eq 0 ]
    then
       echo "successfully register with Azure"
       break
    fi
    sleep 5 # sleep to prevent throttling from wire server
done

Genel adımlar (Python veya Bash kullanılmıyorsa)

VM'nizde Python yüklü veya kullanılabilir değilse, aşağıdaki adımlarla yukarıdaki betik mantığını program aracılığıyla yeniden oluşturabilirsiniz:

  1. ContainerIdYanıtı WireServer' dan ayrıştırarak , InstanceIdve Incarnation alın: curl -X GET -H 'x-ms-version: 2012-11-30' http://168.63.129.16/machine?comp=goalstate.

  2. Ayrıştırılmış ContainerId, InstanceIdve Incarnation öğesini yukarıdaki adımdan arak aşağıdaki XML verilerini oluşturma:

    <Health>
      <GoalStateIncarnation>INCARNATION</GoalStateIncarnation>
      <Container>
        <ContainerId>CONTAINER_ID</ContainerId>
        <RoleInstanceList>
          <Role>
            <InstanceId>INSTANCE_ID</InstanceId>
            <Health>
              <State>Ready</State>
            </Health>
          </Role>
        </RoleInstanceList>
      </Container>
    </Health>
    
  3. Bu verileri WireServer'a gönderin: curl -X POST -H 'x-ms-version: 2012-11-30' -H "x-ms-agent-name: WALinuxAgent" -H "Content-Type: text/xml;charset=utf-8" -d "$REPORT_READY_XML" http://168.63.129.16/machine?comp=health

İlk önyüklemede kodu çalıştırmayı otomatikleştirme

Bu tanıtımda, modern Linux dağıtımlarında en yaygın init sistemi olan systemd kullanılır. Bu nedenle, bu rapora hazır mekanizmanın doğru zamanda çalıştığından emin olmak için en kolay ve en yerel yol, sistemli bir hizmet birimi oluşturmaktır. Aşağıdaki birim dosyasını 'a /etc/systemd/system ekleyebilirsiniz (bu örnek, birim dosyasını azure-provisioning.serviceadlandırabilir):

[Unit]
Description=Azure Provisioning

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /usr/local/azure-provisioning.py
ExecStart=/bin/bash -c "hostnamectl set-hostname $(curl \
    -H 'metadata: true' \
    'http://169.254.169.254/metadata/instance/compute/name?api-version=2019-06-01&format=text')"
ExecStart=/usr/bin/systemctl disable azure-provisioning.service

[Install]
WantedBy=multi-user.target

Bu sistemli hizmet, temel sağlama için üç şey yapar:

  1. Azure'a hazır raporlar (başarılı olduğunu belirtmek için).
  2. Bu verileri Azure Örnek Meta Veri Hizmeti'nden (IMDS) çekerek kullanıcı tarafından sağlanan VM adını temel alarak VM'yi yeniden adlandırır. Not IMDS, konak adından daha fazlasını ayarlayabilmeniz için SSH Ortak Anahtarları gibi başka örnek meta verileri de sağlar.
  3. Kendisini, sonraki yeniden başlatmalarda değil yalnızca ilk önyüklemede çalışacak şekilde devre dışı bırakır.

Dosya sistemindeki üniteyle, etkinleştirmek için aşağıdakileri çalıştırın:

$ sudo systemctl enable azure-provisioning.service

Artık VM genelleştirilmeye hazırdır ve sanal makineden bir görüntü oluşturulur.

Görüntünün hazırlanması tamamlanıyor

Geliştirme makinenize döndüğünüzde, temel VM'den görüntü oluşturmaya hazırlanmak için aşağıdakileri çalıştırın:

$ az vm deallocate --resource-group demo1 --name demo1
$ az vm generalize --resource-group demo1 --name demo1

Görüntüyü bu VM'den oluşturun:

$ az image create \
    --resource-group demo1 \
    --source demo1 \
    --location eastus \
    --name demo1img

Artık görüntüden yeni bir VM oluşturmaya hazırız. Bu, birden çok VM oluşturmak için de kullanılabilir:

$ IMAGE_ID=$(az image show -g demo1 -n demo1img --query id -o tsv)
$ az vm create \
    --resource-group demo12 \
    --name demo12 \
    --location eastus \
    --ssh-key-value <ssh_pub_key_path> \
    --public-ip-address-dns-name demo12 \
    --image "$IMAGE_ID"
    --enable-agent false

Not

Walinuxagent görüntüden oluşturulacak bu VM'de mevcut olmadığından olarak ayarlanması --enable-agent false önemlidir.

VM başarıyla sağlanmalıdır. Yeni sağlama VM'sinde oturum açtıktan sonra rapora hazır sistemli hizmetin çıkışını görebilmeniz gerekir:

$ sudo journalctl -u azure-provisioning.service
-- Logs begin at Thu 2020-06-11 20:28:45 UTC, end at Thu 2020-06-11 20:31:24 UTC. --
Jun 11 20:28:49 thstringnopa systemd[1]: Starting Azure Provisioning...
Jun 11 20:28:54 thstringnopa python3[320]: Retrieving goal state from the Wireserver
Jun 11 20:28:54 thstringnopa python3[320]: ContainerId: 7b324f53-983a-43bc-b919-1775d6077608
Jun 11 20:28:54 thstringnopa python3[320]: InstanceId: fbb84507-46cd-4f4e-bd78-a2edaa9d059b._thstringnopa2
Jun 11 20:28:54 thstringnopa python3[320]: Sending the following data to Wireserver:
Jun 11 20:28:54 thstringnopa python3[320]: <Health><GoalStateIncarnation>1</GoalStateIncarnation><Container><ContainerId>7b324f53-983a-43bc-b919-1775d6077608</ContainerId><RoleInstanceList><Role><InstanceId>fbb84507-46cd-4f4e-bd78-a2edaa9d059b._thstringnopa2</InstanceId><Health><State>Ready</State></Health></Role></RoleInstanceList></Container></Health>
Jun 11 20:28:54 thstringnopa python3[320]: Response: 200 OK
Jun 11 20:28:56 thstringnopa bash[472]:   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Jun 11 20:28:56 thstringnopa bash[472]:                                  Dload  Upload   Total   Spent    Left  Speed
Jun 11 20:28:56 thstringnopa bash[472]: [158B blob data]
Jun 11 20:28:56 thstringnopa2 systemctl[475]: Removed /etc/systemd/system/multi-user.target.wants/azure-provisioning.service.
Jun 11 20:28:56 thstringnopa2 systemd[1]: azure-provisioning.service: Succeeded.
Jun 11 20:28:56 thstringnopa2 systemd[1]: Started Azure Provisioning.

Destek

Kendi sağlama kodunuzu/aracınızı uygularsanız, bu kodun desteği size aittir, Microsoft desteği yalnızca sağlama arabirimlerinin kullanılamamasıyla ilgili sorunları araştırır. Bu alanda sürekli iyileştirmeler ve değişiklikler yapıyoruz, bu nedenle API değişikliklerini sağlamak için cloud-init ve Azure Linux Aracısı'ndaki değişiklikleri izlemeniz gerekir.

Sonraki adımlar

Daha fazla bilgi için bkz . Linux sağlama.