Aracılığıyla paylaş


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 Aracısı'nın 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, özelleştirilmiş bir görüntü oluşturmayı göz önünde bulundurmalısınız.

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

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. Çoğu dağıtım, bu yardımcı programlarla birlikte kullanıma açılır. Azure'da Linux dağıtım satıcıları tarafından test edilen araçlar arasında dhclient, network-managersystemd-networkd ve diğerleri bulunur.

Not

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

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 bildirimin başarısız olması VM'nizin yeniden başlatılmasına neden olur!

Tanıtım/örnek

Linux Aracısı'nın (walinuxagent) kaldırıldığı ve özel bir python betiğinin eklendiği 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şturun:

$ 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. ContainerIdWireServer' dan yanıtı 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. Yukarıdaki adımdan ayrıştırılmış ContainerId, InstanceIdve Incarnation eklenerek 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 örnekte birim dosyası azure-provisioning.serviceolarak adlandırılabilir):

[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ıyla karşılandığını belirtmek için).
  2. Bu verileri Azure Instance Metadata Service'ten (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 devre dışı bırakır, böylece yalnızca ilk önyüklemede çalışır ve sonraki yeniden başlatmalarda çalışmaz.

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

$ sudo systemctl enable azure-provisioning.service

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

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-agentfalse ö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.