{"id":1562,"date":"2019-09-09T14:44:46","date_gmt":"2019-09-09T14:44:46","guid":{"rendered":"https:\/\/cloudsurfers.it\/2019\/09\/09\/pubblicazione-di-unapplicazione-web-su-azure-kubernetes-service\/"},"modified":"2019-09-09T15:00:32","modified_gmt":"2019-09-09T15:00:32","slug":"pubblicazione-di-unapplicazione-web-su-azure-kubernetes-service","status":"publish","type":"post","link":"https:\/\/cloudsurfers.it\/index.php\/pubblicazione-di-unapplicazione-web-su-azure-kubernetes-service\/","title":{"rendered":"Pubblicazione di un&#8217;applicazione web su Azure Kubernetes Service"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1445\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKS.png\" alt=\"WebApp su AKS\" width=\"1200\" height=\"400\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKS.png 1200w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKS-600x200.png 600w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKS-300x100.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKS-768x256.png 768w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKS-1024x341.png 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/p>\n<p>In questa guida verr\u00e0 mostrata la procedura di pubblicazione di un&#8217;applicazione Web su <a href=\"https:\/\/azure.microsoft.com\"><strong>Azure<\/strong><\/a> utilizzando il servizio <a href=\"https:\/\/azure.microsoft.com\/it-it\/services\/kubernetes-service\/\"><strong>AKS<\/strong><\/a> (<em>Azure Kubernetes Service<\/em>).<\/p>\n<p>Verr\u00e0 fatta inoltre la distinzione sulla tecnica di pubblicazione nel caso in cui l&#8217;applicazione venga sviluppata utilizzando <strong>.NET Framework<\/strong>, oppure <strong>dotNET Core<\/strong>.<\/p>\n<p>Le applicazioni Web verranno containerizzate utilizzando <strong><a href=\"https:\/\/www.docker.com\/\">Docker<\/a>.<\/strong><\/p>\n<h2>Premessa<\/h2>\n<p>A seconda della tecnologia utilizzata per lo sviluppo dell&#8217;applicazione Web, <em>.NET Framework<\/em> o <em>dotNET Core<\/em>, \u00e8 necessario scegliere un sistema operativo compatibile da utilizzare all&#8217;interno del contenitore <em>Docker<\/em>: <strong>Windows Server Core<\/strong> per applicazioni <em>.NET Framework<\/em>, oppure <strong>Windows Nano Server<\/strong> o <strong>Linux<\/strong> per applicazioni <em>dotNET Core<\/em>.<\/p>\n<p>Di seguito uno schema con le differenze per una scelta adeguata allo scopo.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1466\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKSSchema.png\" alt=\"WebApp su AKS Schema\" width=\"1200\" height=\"400\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKSSchema.png 1200w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKSSchema-600x200.png 600w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKSSchema-300x100.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKSSchema-768x256.png 768w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/WebAppAKSSchema-1024x341.png 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/p>\n<h2>Caso 1: Applicazione sviluppata in .NET Framework<\/h2>\n<p>Come anticipato all&#8217;interno della premessa, nel caso in cui vogliamo pubblicare un&#8217;applicazione sviluppata utilizzando <em>.NET Framework<\/em>, \u00e8 necessario creare un&#8217;immagine <em>Docker<\/em> con sistema operativo <strong>Windows Server Core<\/strong>.<\/p>\n<p>Vediamo nello specifico i vari passaggi:<\/p>\n<ol start=\"1\">\n<li>Scaricare ed installare <strong>Docker Desktop for Windows<\/strong> sulla macchina locale (<a href=\"https:\/\/hub.docker.com\/editions\/community\/docker-ce-desktop-windows\">link<\/a>);<\/li>\n<li>Una volta installato, impostare il contenitore sulla piattaforma <em>Windows<\/em> dall&#8217;icona di <em>Docker<\/em> presente all&#8217;interno della barra delle notifiche;<\/li>\n<\/ol>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1472 size-full\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/AKS_ContainerSwitch1.gif\" alt=\"WebApp su AKS Switch Contenitore\" width=\"1312\" height=\"723\" \/><\/p>\n<ol start=\"3\">\n<li>Aprire il progetto della <em>WebApp<\/em> che si intende pubblicare con <em>Visual Studio<\/em> ed effettuare la compilazione della soluzione;<\/li>\n<li>Aggiungere il supporto per <strong>Docker Compose<\/strong> alla <em>WebApp<\/em> appena compilata: tasto destro del mouse sul progetto della <em>WebApp<\/em>, <em>Aggiungi<\/em>, Supporto per l&#8217;agente di orchestrazione del container e selezionare <em>Docker Compose<\/em>;<\/li>\n<\/ol>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1473\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/04\/AKS_SelectDockerCompose.gif\" alt=\"WebApp su AKS Select Docker Compose\" width=\"1136\" height=\"681\" \/><\/p>\n<ol start=\"5\">\n<li>All&#8217;interno del <em>Dockerfile<\/em> modificare la riga:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFROM mcr.microsoft.com\/dotnet\/framework\/aspnet:4.7.2-windowsservercore-ltsc2019\r\n<\/pre>\n<p>con la seguente riga:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFROM microsoft\/aspnet:4.7.1-windowsservercore-10.0.14393.1884\r\n<\/pre>\n<p>Questa operazione \u00e8 necessaria perch\u00e9 gli <strong>ACI<\/strong> (<em>Azure Container Instance<\/em>) non supportano una versione di <em>Windows<\/em> superiore alla <em>10.0.14393 <\/em>nel caso di applicazione .NET Framework;<\/li>\n<li>Aggiungere quindi un nuovo profilo di pubblicazione: tasto destro del mouse sul progetto della <em>WebApp<\/em>, <em>Pubblica<\/em>, selezionare come target <em>Cartella<\/em>, impostare il percorso di output ed effettuare la pubblicazione della soluzione;<\/li>\n<li>Editare il file <strong>docker-compose.yml<\/strong> modificando il valore del campo <em>image<\/em> con uno a proprio piacimento, per esempio:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nimage: webapp452\r\n<\/pre>\n<p>Il nome scelto verr\u00e0 salvato all&#8217;interno della variabile <span style=\"color: #ff0000;\"><strong>$DOCKER_IMAGE<\/strong><\/span>;<\/li>\n<li>Avviare <strong>Windows PowerShell<\/strong> e, una volta posizionati al percorso in cui \u00e8 contenuto il file <em>docker-compose.yml<\/em>, lanciare il seguente comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker-compose build\r\n<\/pre>\n<\/li>\n<li>Accedere al <strong>Portale Azure<\/strong> ed aggiungere un nuovo gruppo risorse: <em>Resource Groups<\/em>, <em>Add<\/em> e successivamente impostare un nome (<em>nel nostro caso &#8220;RG_Webapp4.5.2&#8221;<\/em>). Il nome della risorsa verr\u00e0 salvato nella variabile <span style=\"color: #ff0000;\"><strong>$RESOURCE_GROUP<\/strong><\/span>;<\/li>\n<li>Sempre dal <em>Portale Azure<\/em>, aggiungere un nuovo contenitore impostando un nome, il gruppo risorse creato in precedenza, ed abilitando l&#8217;utente amministratore.Ad esempio: <em>Container registries<\/em>, <em>Add<\/em> ed impostare come segue:<br \/>\n<strong>Name:<\/strong> &#8220;<em>containerwebapp452<\/em>&#8221; (<span style=\"color: #ff0000;\"><strong><em>$CONTAINER_NAME<\/em><\/strong><\/span>)<br \/>\n<strong>Resource Group:<\/strong> <span style=\"color: #ff0000;\"><strong>$RESOURCE_GROUP<\/strong><\/span><br \/>\n<strong>Admin User:<\/strong> <em>Enable<\/em><\/li>\n<li>Restando sul <em>Portale Azure<\/em>, entrare all&#8217;interno del contenitore appena creato ed accedere alla sezione <em>Access keys<\/em>. Qui prelevare le informazioni dei campi <strong>Username<\/strong> e <strong>Password<\/strong>;<\/li>\n<li>Tornare alla finestra <em>PowerShell<\/em> e digitare il comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker login &lt;$CONTAINER_NAME&gt;.azurecr.io -u &lt;$CONTAINER_USERNAME&gt; -p &lt;$CONTAINER_PASSWORD&gt;\r\n<\/pre>\n<p>Dove <span style=\"color: #ff0000;\"><strong>&lt;$CONTAINER_USERNAME&gt;<\/strong><\/span> e <span style=\"color: #ff0000;\"><strong>&lt;<\/strong><\/span><span style=\"color: #ff0000;\"><strong>$CONTAINER_PASSWORD&gt;<\/strong><\/span> sono i campi prelevati dal <em>Portale Azure<\/em> nel punto precedente;<\/li>\n<li>Lanciare quindi il comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker tag &lt;$DOCKER_IMAGE&gt; &lt;$CONTAINER_NAME&gt;.azurecr.io\/&lt;$DOCKER_IMAGE&gt;\r\n<\/pre>\n<p>per applicare il <em>TAG<\/em> all&#8217;immagine, e successivamente:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker push &lt;$CONTAINER_NAME&gt;.azurecr.io\/&lt;$DOCKER_IMAGE&gt;\r\n<\/pre>\n<p>per effettuare il <em>PUSH<\/em> dell&#8217;immagine su <em>Docker<\/em>;<\/li>\n<li>Al termine dell&#8217;operazione di <em>PUSH<\/em>, \u00e8 necessario procedere con la creazione di un utente di servizio che avr\u00e0 accesso al cluster <em>AKS<\/em> (<em>Azure Kubernetes Service<\/em>) che andremo a creare successivamente. Lanciare quindi il comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz ad sp create-for-rbac --skip-assignment\r\n<\/pre>\n<p>e, dal risultato ottenuto appuntarsi i valori di <strong>appId<\/strong> e <strong>password<\/strong>;<\/li>\n<li>A questo punto bisogna assegnare il ruolo di <strong>Reader<\/strong> all&#8217;utente appena creato per permettergli di effettuare l&#8217;operazione di <em>PULL,<\/em> della risorsa oggetto dell&#8217;operazione di <em>PUSH<\/em> precedente. In sequenza ecco i due comandi necessari:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz acr show --resource-group &lt;$RESOURCE_GROUP&gt; --name &lt;$CONTAINER_NAME&gt; --query &quot;id&quot; --output tsv\r\n<\/pre>\n<p>Appuntarsi quindi il parametro <strong>&lt;$acrId&gt;<\/strong> ed utilizzarlo all&#8217;interno del seguente comando:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz role assignment create --assignee &lt;$appId&gt; --scope &lt;$acrId&gt; --role Reader\r\n<\/pre>\n<\/li>\n<li>Ora si pu\u00f2 procedere con la creazione del cluster <em>AKS<\/em> mediante il seguente comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz aks create --resource-group &lt;$RESOURCE_GROUP&gt; --name &lt;$CLUSTER_NAME&gt; --node-count 1 --service-principal &lt;$appId&gt; --client-secret &lt;$password&gt; --generate-ssh-keys --kubernetes-version 1.11.5\r\n<\/pre>\n<p>In questo caso verr\u00e0 creato un cluster con singolo nodo. La configurazione rimane comunque editabile anche in un secondo momento e si pu\u00f2 inoltre cambiare il numero di nodi iniziali agendo sul valore del parametro &#8220;<em>&#8211;node-count<\/em>&#8220;.<\/p>\n<p><span style=\"color: #ff0000;\"><strong>N.B.<\/strong><\/span> Nel caso venga riscontrato l&#8217;errore:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz aks create: error: Incorrect padding\r\n<\/pre>\n<p>all&#8217;interno della <em>PowerShell<\/em>, \u00e8 possibile lanciare il comando di creazione del cluster direttamente dal <em>Portale Azure<\/em> mediante l&#8217;uso della <strong>Cloud Shell<\/strong>.<\/p>\n<p>Se all&#8217;interno della <strong>Kubernates services<\/strong> del <em>Portale Azure<\/em> appare il cluster appena creato con lo stato &#8220;<em>Succeeded<\/em>&#8220;, l&#8217;operazione \u00e8 terminata con successo ed \u00e8 possibile continuare con la pubblicazione.<\/li>\n<li>Lanciare il comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz aks install-cli\r\n<\/pre>\n<p>e successivamente effettuare la connessione al cluster:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz aks get-credentials --resource-group &lt;$RESOURCE_GROUP&gt; --name &lt;$CLUSTER_NAME&gt;\r\n<\/pre>\n<\/li>\n<\/ol>\n<h3>Installazione Virtual Kubelet<\/h3>\n<p><strong>AKS<\/strong> (<em>Azure Kubernetes Service<\/em>) riesce a gestire in modo automatico dei nodi virtuali verso delle <strong>ACI<\/strong> (<em>Azure Container Instance<\/em>) solamente se il contenitore usa un&#8217;immagine <em>Linux.<\/em> Per <em>Windows<\/em>\u00a0invece, \u00e8 necessario l&#8217;utilizzo di uno strumento chiamato <strong>Virtual Kubelet<\/strong>.<\/p>\n<p><span style=\"color: #ff0000;\"><strong>N.B.<\/strong><\/span> Per installare <em>Virtual Kubelet<\/em> bisogna installare anche <strong>Helm<\/strong>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1492\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/05\/WebAppAKSSchemaNodi.png\" alt=\"WebApp AKS Schema Nodi\" width=\"1200\" height=\"400\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/05\/WebAppAKSSchemaNodi.png 1200w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/05\/WebAppAKSSchemaNodi-600x200.png 600w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/05\/WebAppAKSSchemaNodi-300x100.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/05\/WebAppAKSSchemaNodi-768x256.png 768w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2019\/05\/WebAppAKSSchemaNodi-1024x341.png 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/p>\n<ol start=\"18\">\n<li style=\"list-style-type: none;\">\n<ol start=\"18\">\n<li>Creare un file di testo vuoto chiamato <strong>rbac-virtual-kubelet.yaml<\/strong> e copiarci il seguente testo:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\napiVersion: v1\r\nkind: ServiceAccount\r\nmetadata:\r\n    name: tiller\r\n    namespace: kube-system\r\n---\r\napiVersion: rbac.authorization.k8s.io\/v1\r\nkind: ClusterRoleBinding\r\nmetadata:\r\n    name: tiller\r\nroleRef:\r\n    apiGroup: rbac.authorization.k8s.io\r\n    kind: ClusterRole\r\n    name: cluster-admin\r\nsubjects:\r\n    - kind: ServiceAccount\r\n      name: tiller\r\n      namespace: kube-system\r\n<\/pre>\n<\/li>\n<li>Posizionarsi all&#8217;interno della cartella nel quale \u00e8 stato creato il file e lanciare i seguenti comandi:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nkubectl apply -f rbac-virtual-kubelet.yaml\r\nhelm init --service-account tiller\r\naz aks install-connector --resource-group &lt;$RESOURCE_GROUP&gt; --name &lt;$CLUSTER_NAME&gt; --connector-name virtual-kubelet --os-type Windows\r\n<\/pre>\n<p>A questo punto, mediante il comando:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nkubectl get nodes\r\n<\/pre>\n<p>si dovrebbero vedere due nodi: l&#8217;<strong>agent<\/strong>, creato al momento della creazione del cluster <em>AKS<\/em>, e il nuovo nodo <strong>virtual-kubelet<\/strong> appena creato, da utilizzare come connettore verso i contenitori <em>Windows<\/em>;<\/li>\n<li>L&#8217;utilizzo dei <em>Virtual Kubelet<\/em> rende necessaria la creazione di una <u>chiave segreta<\/u>, questo per poter effettuare il <em>PULL<\/em> dell&#8217;immagine. Tramite <em>PowerShell<\/em>, usare quindi la seguente sequenza di comandi, sostituendo le variabili con i valori assegnati precedentemente:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n$ACR_NAME=&quot;&lt;$CONTAINER_NAME&gt;&quot;\r\n$SERVICE_PRINCIPAL_NAME=&quot;&lt;$CONTAINER_USERNAME&gt;&quot;\r\n$ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --query loginServer --output tsv)\r\n$ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)\r\n$SP_PASSWD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --role acrpull --scopes $ACR_REGISTRY_ID --query password --output tsv)\r\n$CLIENT_ID=$(az ad sp show --id http:\/\/$SERVICE_PRINCIPAL_NAME --query appId --output tsv)\r\nkubectl create secret docker-registry acr-auth --docker-server $ACR_LOGIN_SERVER --docker-username $SERVICE_PRINCIPAL_NAME --docker-password &lt;$CONTAINER_PASSWORD&gt; --docker-email &lt;$ACCOUNT_EMAIL&gt;\r\n<\/pre>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<h3>Pubblicazione dell&#8217;immagine<\/h3>\n<p>A questo punto siamo pronti per la pubblicazione, sul cluster, dell&#8217;immagine caricata all&#8217;interno del contenitore <em>ACI<\/em> (<em>Azure Container Instance<\/em>).<\/p>\n<ol start=\"21\">\n<li>Per procedere, va creato un file di testo vuoto chiamato, ad esempio, <strong>virtual-kubelet-windows.yaml<\/strong> contenente:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\napiVersion: apps\/v1\r\nkind: Deployment\r\nmetadata:\r\n    name: &lt;$DOCKER_IMAGE&gt;\r\nspec:\r\n    replicas: &lt;$PODS_NUMBER&gt;\r\n    selector:\r\n        matchLabels:\r\n            app: &lt;$DOCKER_IMAGE&gt;\r\n    template:\r\n        metadata:\r\n            labels:\r\n                app: &lt;$DOCKER_IMAGE&gt;\r\n        spec:\r\n            containers:\r\n            - name: &lt;$DOCKER_IMAGE&gt;\r\n              image: &lt;$CONTAINER_NAME&gt;.azurecr.io\/&lt;$DOCKER_IMAGE&gt;\r\n              ports:\r\n              - containerPort: 80\r\n              imagePullPolicy: Always\r\n            imagePullSecrets:\r\n            - name: acr-auth\r\n            nodeSelector:\r\n                beta.kubernetes.io\/os: windows\r\n                kubernetes.io\/role: agent\r\n                type: virtual-kubelet\r\n            tolerations:\r\n            - key: virtual-kubelet.io\/provider\r\n              operator: Equal\r\n              value: azure\r\n              effect: NoSchedule\r\n---\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n    name: &lt;$DOCKER_IMAGE&gt;\r\nspec:\r\n    type: LoadBalancer\r\n    ports:\r\n    - port: 80\r\n    selector:\r\n        app: &lt;$DOCKER_IMAGE&gt;\r\n<\/pre>\n<p>Le variabili: <span style=\"color: #ff0000;\"><strong>&lt;$DOCKER_IMAGE&gt;<\/strong><\/span>, <span style=\"color: #ff0000;\"><strong>&lt;$PODS_NUMBER&gt;<\/strong><\/span> e <span style=\"color: #ff0000;\"><strong>&lt;$CONTAINER_NAME&gt;<\/strong><\/span> vanno sostituite con i parametri di configurazione assegnati precedentemente;<\/li>\n<li>Tramite <em>PowerShell<\/em>, posizionarsi all&#8217;interno del percorso che contiene il file appena creato e lanciare il seguente comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nkubectl apply -f virtual-kubelet-windows.yaml\r\n<\/pre>\n<p>Cos\u00ec facendo, verranno originati diversi <em>POD<\/em>, ognuno dei quali punter\u00e0 ad una <em>ACI<\/em>, e saranno tutti gestiti dal <em>Virtual Kubelet<\/em> creato in precedenza.<\/p>\n<p>Il completamento dell&#8217;operazione dura in genere alcuni minuti, anche in base al numero di <em>POD<\/em> che deve generare.<\/p>\n<p>Per monitorarne lo stato di creazione \u00e8 possibile accedere alla sezione <strong>Container Instances<\/strong> del <em>Portale Azure<\/em>. Lo stato &#8220;<em>Creating<\/em>&#8221; indica che l&#8217;operazione \u00e8 ancora in corso.<\/li>\n<\/ol>\n<p>Dal <em>Portale Azure<\/em> \u00e8 anche possibile conoscere l&#8217;<em>IP<\/em> pubblico con cui accedere al set di <em>POD<\/em> appena creato. Per farlo:<\/p>\n<ol>\n<li>Cliccare su uno dei <em>POD<\/em> appena creato;<\/li>\n<li>Tramite il link <em>Resource Group<\/em> si apriranno gli elementi associati al gruppo di risorse, selezionare quello con il parametro <em>Type<\/em> assegnato come <em>Load Balancer<\/em>;<\/li>\n<li>Tra le molteplici informazioni mostrate, vi \u00e8 anche <em>Public IP address<\/em>, l&#8217;indirizzo pubblico con cui accedere al cluster creato.<\/li>\n<\/ol>\n<h2>Caso 2: Applicazione sviluppata in .NET Core<\/h2>\n<p>Nel caso avessimo a che fare con un applicazione sviluppata con tecnologia .<strong>NET Core<\/strong>, all&#8217;interno del contenitore <em>Docker<\/em> \u00e8 possibile utilizzare sia il sistema operativo <strong>Windows Nano Server<\/strong>, oppure <strong>Linux<\/strong>.<\/p>\n<p>Vediamo anche per questo caso i vari passaggi:<\/p>\n<ol>\n<li>\u00a0Seguire i passaggi <em>1<\/em> e <em>2<\/em> descritti nel <strong>Caso 1<\/strong>, per scaricare ed installare <strong>Docker Desktop for Windows<\/strong>;<\/li>\n<li>Aprire il progetto <em>WebApp<\/em> su <em>Visual Studio<\/em> ed aggiungere un file di nome <strong>Dockerfile<\/strong> all&#8217;interno della root;<\/li>\n<li>All&#8217;interno del <strong>Dockerfile<\/strong> aggiungere il seguente testo:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFROM microsoft\/dotnet:2.2-aspnetcore-runtime\r\nARG source=.\r\nWORKDIR \/app\r\nEXPOSE 80\r\nCOPY $source .\r\nENTRYPOINT &#x5B;&quot;dotnet&quot;, &quot;&lt;$DLL_STARTUP_PROJECT&gt;&quot;]\r\n<\/pre>\n<p>Dove il parametro <span style=\"color: #ff0000;\"><strong>&lt;$DLL_STARTUP_PROJECT&gt;<\/strong><\/span> dovr\u00e0 essere sostituito con il nome della <em><strong>dll<\/strong><\/em> del progetto di partenza.<\/p>\n<p>Inoltre il <em>Dockerfile<\/em> deve sempre essere copiato all&#8217;interno della directory di output (<em>&#8220;<strong>Copy Always<\/strong>&#8221; nelle propriet\u00e0 del file<\/em>);<\/li>\n<li>Creare un profilo di pubblicazione della <em>WebApp<\/em>, impostare l&#8217;output su <em>FileSystem<\/em> e chiamarlo <strong>DockerProfile<\/strong>.<br \/>\nCome impostazioni di pubblicazione usare le seguenti:<br \/>\n<strong>Configurazione:<\/strong> <em>Release<\/em><br \/>\n<strong>Modalit\u00e0 destinazione:<\/strong> <em>Dipendente del framework<\/em><br \/>\n<strong>Runtime:<\/strong> <em>Linux-64<\/em><br \/>\n<strong>Opzioni pubblicazione:<\/strong> <em>Elimina tutti i file esistenti<\/em><\/li>\n<li>Avviare quindi la pubblicazione ed attendere l&#8217;esito;<\/li>\n<li>Aprire <em>PowerShell<\/em> e creare l&#8217;immagine <em>Docker<\/em> tramite il seguente comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker build &lt;$PUBLISH_FOLDER&gt; -t &lt;$CONTAINER_NAME&gt;.azurecr.io\/&lt;$DOCKER_IMAGE&gt;:0\r\n<\/pre>\n<\/li>\n<li>Al termine della creazione dell&#8217;immagine, effettuarne il <em>PUSH<\/em> verso <em>ACI<\/em> (<em>Azure Container Instance<\/em>) con il comando:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker push &lt;$CONTAINER_NAME&gt;.azurecr.io\/&lt;$DOCKER_IMAGE&gt;:0\r\n<\/pre>\n<\/li>\n<li>Seguire dal punto <em>14<\/em> al <em>17<\/em> mostrati all&#8217;interno del <strong>Caso 1<\/strong>;<\/li>\n<li>A questo punto l&#8217;immagine caricata sul contenitore <em>ACI<\/em> \u00e8 pronta per la pubblicazione.Creare quindi un nuovo file chiamato <strong>webapp.yaml<\/strong> e copiarci al suo interno il seguente testo:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\napiVersion: apps\/v1\r\nkind: Deployment\r\nmetadata:\r\n    name: &lt;$DOCKER_IMAGE&gt;\r\nspec:\r\n    replicas: &lt;$PODS_NUMBER&gt;\r\n    selector:\r\n        matchLabels:\r\n            app: &lt;$DOCKER_IMAGE&gt;\r\n    template:\r\n        metadata:\r\n            labels:\r\n                app: &lt;$DOCKER_IMAGE&gt;\r\n        spec:\r\n            containers:\r\n            - name: &lt;$DOCKER_IMAGE&gt;\r\n              image: &lt;$CONTAINER_NAME&gt;.azurecr.io\/&lt;$DOCKER_IMAGE&gt;\r\n              ports:\r\n              - containerPort: 80\r\n              imagePullPolicy: Always\r\n            imagePullSecrets:\r\n            - name: acr-auth\r\n---\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n    name: &lt;$DOCKER_IMAGE&gt;\r\nspec:\r\n    type: LoadBalancer\r\n    ports:\r\n    - port: 80\r\n    selector:\r\n        app: &lt;$DOCKER_IMAGE&gt;\r\n<\/pre>\n<p>Sostituire le variabili: <span style=\"color: #ff0000;\"><strong>&lt;$DOCKER_IMAGE&gt;<\/strong><\/span>, <span style=\"color: #ff0000;\"><strong>&lt;$PODS_NUMBER&gt;<\/strong><\/span> e <span style=\"color: #ff0000;\"><strong>&lt;$CONTAINER_NAME&gt;<\/strong><\/span> con i parametri opportuni di configurazione;<\/li>\n<li>Tramite <em>PowerShell<\/em> posizionarsi al percorso nel quale \u00e8 stato creato il file <strong>webapp.yaml<\/strong> e lanciare il seguente comando per procedere con la pubblicazione finale:\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nkubectl apply -f webapp.yaml\r\n<\/pre>\n<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>In questa guida verr\u00e0 mostrata la procedura di pubblicazione di un&#8217;applicazione Web su Azure utilizzando il servizio AKS (Azure Kubernetes Service). Verr\u00e0 fatta inoltre la distinzione sulla tecnica di pubblicazione &#8230;<\/p>\n","protected":false},"author":3,"featured_media":1563,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wds_primary_category":0,"footnotes":""},"categories":[76,71],"tags":[80,83,82],"class_list":["post-1562","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-en","category-guides","tag-application","tag-docker-en","tag-k8s-en"],"_links":{"self":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts\/1562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/comments?post=1562"}],"version-history":[{"count":0,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts\/1562\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/media\/1563"}],"wp:attachment":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/media?parent=1562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/categories?post=1562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/tags?post=1562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}