{"id":2122,"date":"2018-11-13T14:09:36","date_gmt":"2018-11-13T06:09:36","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/iotdev\/?p=2122"},"modified":"2019-02-15T10:27:04","modified_gmt":"2019-02-15T02:27:04","slug":"setup-azure-iot-edge-ci-cd-pipeline-with-arm-agent","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/iotdev\/setup-azure-iot-edge-ci-cd-pipeline-with-arm-agent\/","title":{"rendered":"Setup Azure IoT Edge CI\/CD Pipeline with ARM Agent"},"content":{"rendered":"<p><a href=\"https:\/\/azure.microsoft.com\/en-us\/services\/iot-edge\/\">Azure IoT Edge<\/a> is a fully managed service that delivers cloud intelligence locally by deploying and running artificial intelligence (AI), Azure services, and custom logic directly on cross-platform IoT devices. An Edge solution contains one or more <a href=\"https:\/\/docs.microsoft.com\/en-gb\/azure\/iot-edge\/iot-edge-modules\">modules<\/a>, which are hosted as docker images and run in docker container on Edge device. In order for an Edge solution to be applied to target Edge device(s), a <a href=\"https:\/\/docs.microsoft.com\/en-gb\/azure\/iot-edge\/module-deployment-monitoring\">deployment<\/a> needs to be created in IoT Hub.<\/p>\n<p>The <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=vsc-iot.iot-edge-build-deploy\">Azure IoT Edge for Azure Pipelines<\/a> extension is a tool for you to easily setup CI\/CD pipelines on Azure DevOps. It provides Build and Push task for continuous integration and Deploy to IoT Edge devices task for continuous delivery.<\/p>\n<ul>\n<li>For Build and Push, you can specify which modules to build and the target container registry for the docker images<\/li>\n<li>For Deploy to IoT Edge devices, you will set IoT Hub as the target of deployment and configure other parameters (priority, target condition).<\/li>\n<\/ul>\n<p>You can use <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=vsc-iot.iot-edge-build-deploy\">Azure IoT Edge for Azure Pipelines<\/a> to setup CI\/CD on different platforms, amd64, windows-amd64 or arm. For amd64 and windows-amd64, Azure DevOps already provides a set of hosted agents for CI\/CD (You can find more information in our <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/iot-edge\/how-to-ci-cd\">official documentation<\/a>).<\/p>\n<p>In this thread, we will introduce CI\/CD on ARM platform agent. Since Azure DevOps doesn\u2019t provide hosted ARM agent currently, we need to setup a private ARM agent.<\/p>\n<h2><a id=\"post-2122-_Toc529884323\"><\/a>Environment<\/h2>\n<p>&nbsp;<\/p>\n<h3>Hardware<\/h3>\n<p>Test on Raspberry Pi 3 (other ARM devices with Linux kernel not tested, but should be able to work)<\/p>\n<h3>OS version<\/h3>\n<p>Raspbian STRETCH<\/p>\n<h3>Run Edge runtime and build agent on same device<\/h3>\n<p>For most of the cases, we would set build agent on an ARM device and use another ARM device as the Edge device running Edge runtime. But if you only have one ARM device, don\u2019t worry, you can setup the device for 2 roles: build agent and Edge device.<\/p>\n<p>&nbsp;<\/p>\n<h2><a id=\"post-2122-_Toc529884324\"><\/a>Prerequisites<\/h2>\n<p>&nbsp;<\/p>\n<h3>Docker<\/h3>\n<p>The CI\/CD task will use <strong>docker<\/strong> command to build and push docker images. So docker is a requirement. You can refer to <a href=\"https:\/\/docs.docker.com\/install\/linux\/docker-ce\/debian\/\">Get Docker CE for Debian<\/a> to setup Docker-CE on ARM device.<\/p>\n<table>\n<tbody>\n<tr>\n<td><a id=\"post-2122-_Hlk529877803\"><\/a> If your Pi is already installed with IoT Edge runtime, then the moby-based container engine is already installed. Docker CE\/EE container images are compatible with the Moby-based runtime, so you can skip this step to setup Docker runtime.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Python<\/h3>\n<p>You need to install python and pip.<\/p>\n<table>\n<tbody>\n<tr>\n<td>The test version of python is 2.7.13, pip is 18.1. But other versions (including python3) should be able to work.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Azure CLI<\/h3>\n<p>You can follow <a href=\"https:\/\/docs.microsoft.com\/en-us\/cli\/azure\/install-azure-cli-linux?view=azure-cli-latest\">Install Azure CLI on Linux manually<\/a> to install Azure CLI. After installation complete, you can execute <strong>az \u2013version<\/strong> to check if Azure CLI is successfully installed.<\/p>\n<p>&nbsp;<\/p>\n<h2><a id=\"post-2122-_Toc529884325\"><\/a>Setup build agent<\/h2>\n<p>Follow <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/devops\/pipelines\/agents\/v2-linux?view=vsts\">Deploy an agent on Linux<\/a> to download package and set the ARM device as a build agent.<\/p>\n<table>\n<tbody>\n<tr>\n<td>In the step <strong>Get agent<\/strong>, you need to select <strong>Linux<\/strong> and <strong>ARM<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>After that, you can see the new <strong>ARM <\/strong>agent pool with the agent <strong>pi-agent<\/strong> in Online state.<\/p>\n<p><img decoding=\"async\" width=\"1559\" height=\"844\" class=\"wp-image-2123\" src=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image.png\" srcset=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image.png 1559w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-300x162.png 300w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-768x416.png 768w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-1024x554.png 1024w\" sizes=\"(max-width: 1559px) 100vw, 1559px\" \/><\/p>\n<h2><\/h2>\n<h2>Prepare sample Edge solution<\/h2>\n<p>For quick start, you can use an existing <a href=\"https:\/\/github.com\/michaeljqzq\/azure-iot-edge-sample-arm\">sample solution<\/a>, it is the basic Edge solution that contains only one custom module which will pipe the message from simulated temperature sensor.<\/p>\n<table>\n<tbody>\n<tr>\n<td>To use this sample solution, first fork it to your own repository. And then replace the file modules\/SampleModule\/module.json<\/p>\n<p>\u201czhiqing.azurecr.io\u201d with your own container registry. In the later step to set the container registry in build pipeline, use the same settings.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><\/h2>\n<h2><a id=\"post-2122-_Toc529884327\"><\/a>Setup CI\/CD pipeline<\/h2>\n<p>Follow <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/iot-edge\/how-to-ci-cd#configure-azure-pipeline-for-continuous-integration\">this guide<\/a> to setup your DevOps account, and setup the CI\/CD pipeline.<\/p>\n<p>Regarding the <strong>source setting<\/strong> in CI, you need to set the <strong>source<\/strong> as the forked repository in the previous step.<\/p>\n<p><img decoding=\"async\" width=\"1007\" height=\"941\" class=\"wp-image-2124\" src=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-1.png\" srcset=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-1.png 1007w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-1-300x280.png 300w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-1-768x718.png 768w\" sizes=\"(max-width: 1007px) 100vw, 1007px\" \/><\/p>\n<ul>\n<li>For continuous integration (build pipeline), when setting <strong>Agent pool<\/strong>, you need to specify the one in the <strong>Setup build agent<\/strong> step.<\/li>\n<\/ul>\n<p><img decoding=\"async\" width=\"562\" height=\"542\" class=\"wp-image-2125\" src=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-2.png\" srcset=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-2.png 562w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-2-300x289.png 300w\" sizes=\"(max-width: 562px) 100vw, 562px\" \/><\/p>\n<ul>\n<li>For continuous delivery (release pipeline), it is not platform sensitive. So, you can use <strong>Hosted VS2017 <\/strong>or <strong>Hosted Ubuntu 1604<\/strong> to do the deployment for better performance. <strong>ARM<\/strong> agent is also able to use.<\/li>\n<\/ul>\n<h2><\/h2>\n<h2><a id=\"post-2122-_Toc529884328\"><\/a>Trigger pipeline and verify<\/h2>\n<p>You can manually queue a new build in build pipeline. It will build and push docker images in build pipeline, and then trigger release pipeline to deploy to IoT Hub. After CI\/CD pipeline finished, you will be able to see the deployment on Azure Portal -&gt; IoT Hub -&gt; IoT Edge.<\/p>\n<p><img decoding=\"async\" width=\"1917\" height=\"1141\" class=\"wp-image-2126\" src=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-3.png\" srcset=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-3.png 1917w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-3-300x179.png 300w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-3-768x457.png 768w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-3-1024x609.png 1024w\" sizes=\"(max-width: 1917px) 100vw, 1917px\" \/><\/p>\n<p>In Edge device details, we can see that all the 4 modules are already deployed to the target device and in running state.<\/p>\n<p><img decoding=\"async\" width=\"2459\" height=\"1100\" class=\"wp-image-2127\" src=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-4.png\" srcset=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-4.png 2459w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-4-300x134.png 300w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-4-768x344.png 768w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-4-1024x458.png 1024w\" sizes=\"(max-width: 2459px) 100vw, 2459px\" \/><\/p>\n<p>You can use <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=vsciot-vscode.azure-iot-toolkit\">Azure IoT Toolkit<\/a> to monitor D2C message sent by the Edge device.<\/p>\n<p><img decoding=\"async\" width=\"2484\" height=\"903\" class=\"wp-image-2128\" src=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-5.png\" srcset=\"https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-5.png 2484w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-5-300x109.png 300w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-5-768x279.png 768w, https:\/\/devblogs.microsoft.com\/iotdev\/wp-content\/uploads\/sites\/24\/2018\/12\/word-image-5-1024x372.png 1024w\" sizes=\"(max-width: 2484px) 100vw, 2484px\" \/><\/p>\n<h2><\/h2>\n<p>&nbsp;<\/p>\n<h2>Troubleshooting<\/h2>\n<ul>\n<li><span style=\"color: #ff6600\">Meet error (&#8216;Connection aborted.&#8217;, error(13, &#8216;Permission denied&#8217;)) in build pipeline<\/span><\/li>\n<\/ul>\n<p style=\"padding-left: 30px\">The Docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user <strong>root<\/strong> and other users can only access it using <strong>sudo<\/strong>. But the build task won\u2019t be executed as user <strong>root<\/strong>. Follow the <a href=\"https:\/\/docs.docker.com\/install\/linux\/linux-postinstall\/\">Post-installation steps for Linux<\/a> to resolve this issue.<\/p>\n<ul>\n<li><span style=\"color: #ff6600\">Meet error Unable to locate executable file: &#8216;iotedgedev&#8217; in build pipeline<\/span><\/li>\n<\/ul>\n<p style=\"padding-left: 30px\">The build task leverages the tool \u2018iotedgedev\u2019 for docker related work. In the beginning of the task, it will try to install this dependency. But under some circumstances, the installation process will fail. Please raise issue on the repo of <a href=\"https:\/\/github.com\/Microsoft\/azure-iot-edge-vsts-extension#azure-iot-edge-for-vsts\">Azure IoT Edge For Azure Pipelines<\/a>. As a word around, manually install iotedgedev with this <a href=\"https:\/\/github.com\/Azure\/iotedgedev\/wiki\/manual-dev-machine-setup\">guide<\/a>.<\/p>\n<h2>Feedback<\/h2>\n<p>Now Azure IoT Edge is already an in-house task in Azure Pipelines. You can search and add it in your pipeline. We would love to know your feeling or suggestions with this extension, feel free to provide your feedback via the <a href=\"https:\/\/github.com\/Microsoft\/azure-iot-edge-vsts-extension\/\">Github repository<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Azure IoT Edge is a fully managed service that delivers cloud intelligence locally by deploying and running artificial intelligence (AI), Azure services, and custom logic directly on cross-platform IoT devices. An Edge solution contains one or more modules, which are hosted as docker images and run in docker container on Edge device. In order for [&hellip;]<\/p>\n","protected":false},"author":530,"featured_media":2138,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[166,5,6,164,165],"class_list":["post-2122","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-iot-dev","tag-arm","tag-azure","tag-azure-iot","tag-azure-iot-edge","tag-ci-cd"],"acf":[],"blog_post_summary":"<p>Azure IoT Edge is a fully managed service that delivers cloud intelligence locally by deploying and running artificial intelligence (AI), Azure services, and custom logic directly on cross-platform IoT devices. An Edge solution contains one or more modules, which are hosted as docker images and run in docker container on Edge device. In order for [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/posts\/2122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/users\/530"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/comments?post=2122"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/posts\/2122\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/media\/2138"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/media?parent=2122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/categories?post=2122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/iotdev\/wp-json\/wp\/v2\/tags?post=2122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}