<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>7. Terraform with Pipeline on Terraform Basics on Azure Training</title><link>/docs/07_pipeline/</link><description>Recent content in 7. Terraform with Pipeline on Terraform Basics on Azure Training</description><generator>Hugo</generator><language>en-us</language><atom:link href="/docs/07_pipeline/index.xml" rel="self" type="application/rss+xml"/><item><title>7.1. Introduction to GitLab CI/CD</title><link>/docs/07_pipeline/1-introduction/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/docs/07_pipeline/1-introduction/</guid><description>&lt;h2 id="building-blocks-of-a-gitlab-pipeline"&gt;Building Blocks of a GitLab Pipeline&lt;/h2&gt;
&lt;p&gt;Before writing any Terraform CI/CD configuration, let&amp;rsquo;s understand the key concepts.&lt;/p&gt;
&lt;p&gt;A GitLab pipeline is defined in a file called &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; at the root of your repository.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Concept&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Pipeline&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;The top-level process triggered by a git push or manually&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Stage&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;A named phase (&lt;code&gt;build&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;deploy&lt;/code&gt;). Stages run sequentially&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Job&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;A unit of work inside a stage. Jobs in the same stage run in parallel&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Runner&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;An agent (VM or container) that executes job scripts&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Variable&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;A key/value pair, either defined in &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; or in GitLab project settings&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="preparation"&gt;Preparation&lt;/h2&gt;
&lt;p&gt;Create a new GitLab project and clone it:&lt;/p&gt;</description></item><item><title>7.2. Azure Credentials for CI/CD</title><link>/docs/07_pipeline/2-azure-credentials/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/docs/07_pipeline/2-azure-credentials/</guid><description>&lt;p&gt;Terraform needs an Azure &lt;strong&gt;service principal&lt;/strong&gt; to authenticate from a pipeline runner — a
non-interactive identity with scoped permissions. In this lab you create the service principal
with the Azure CLI and store the resulting credentials as masked GitLab CI/CD variables.&lt;/p&gt;
&lt;h2 id="preparation"&gt;Preparation&lt;/h2&gt;
&lt;p&gt;Make sure you are logged in to the Azure CLI and have the correct subscription selected:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az login
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az account show
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you need to switch subscription:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az account &lt;span style="color:#204a87"&gt;set&lt;/span&gt; --subscription &lt;span style="color:#4e9a06"&gt;&amp;#34;&amp;lt;your-subscription-id&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="step-721-create-a-service-principal"&gt;Step 7.2.1: Create a service principal&lt;/h2&gt;
&lt;p&gt;Create a service principal scoped to your subscription with the &lt;strong&gt;Contributor&lt;/strong&gt; role:&lt;/p&gt;</description></item><item><title>7.3. GitLab Runner on Azure</title><link>/docs/07_pipeline/3-gitlab-runner/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/docs/07_pipeline/3-gitlab-runner/</guid><description>&lt;p&gt;Shared GitLab runners work for many scenarios, but teams that deploy to Azure often need a
&lt;strong&gt;self-hosted runner&lt;/strong&gt; that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Has network access to private Azure resources&lt;/li&gt;
&lt;li&gt;Can cache Terraform provider plugins locally to speed up pipelines&lt;/li&gt;
&lt;li&gt;Can be tagged so only specific pipelines use it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this lab we provision a dedicated GitLab Runner on an Azure Linux VM using Terraform.
The overall flow looks like this: a local Terraform apply bootstraps an Azure VM, registers
a runner token with GitLab, and then uses SSH provisioners to install Docker and start the
GitLab Runner container on the VM.&lt;/p&gt;</description></item><item><title>7.4. Build a Pipeline Image with Kaniko</title><link>/docs/07_pipeline/4-build-docker-image/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/docs/07_pipeline/4-build-docker-image/</guid><description>&lt;p&gt;Building a custom Docker image inside a CI pipeline — without access to a Docker daemon — is a
common requirement when using container-based runners.
&lt;a href="https://github.com/GoogleContainerTools/kaniko" target="_blank" rel="noopener"&gt;Kaniko&lt;/a&gt;
 solves this by executing each Dockerfile
instruction in user-space, writing directly to container filesystem layers instead of relying on
the host Docker socket.&lt;/p&gt;
&lt;p&gt;In this lab you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extend the Terraform code from Lab 7.3 to grant the service principal &lt;strong&gt;AcrPush&lt;/strong&gt; access on
the Azure Container Registry created in Chapter 6.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;dedicated GitLab repository&lt;/strong&gt; for the builder image — separate from the
Terraform pipeline repository used in Chapters 7.1–7.3.&lt;/li&gt;
&lt;li&gt;Write a &lt;code&gt;Dockerfile&lt;/code&gt; that bundles &lt;code&gt;terraform&lt;/code&gt; and &lt;code&gt;tflint&lt;/code&gt; for use in pipeline jobs.&lt;/li&gt;
&lt;li&gt;Add a simple &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; that uses Kaniko to build and push the image to ACR whenever
the &lt;code&gt;Dockerfile&lt;/code&gt; changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Keeping the image repository separate from the Terraform code repository is a common
practice: the two repositories have different lifecycles (the image changes when tool versions
change; Terraform code changes when infrastructure changes) and different access-control
requirements.&lt;/p&gt;</description></item><item><title>7.5. Linting in CI</title><link>/docs/07_pipeline/5-linting/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/docs/07_pipeline/5-linting/</guid><description>&lt;p&gt;Code quality checks catch mistakes early. For Terraform we can run three levels of linting:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Tool&lt;/th&gt;
 &lt;th&gt;What it checks&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;terraform fmt -check&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Canonical formatting (whitespace, indentation)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;terraform validate&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Syntactic and semantic validity&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;tflint&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Provider-specific rules, best practices, unused variables&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In this lab we run these checks locally and wire them up as a GitLab CI linting stage using
the Docker image built and pushed to ACR in Lab 7.4.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 user --&amp;gt; |run|fmt
 user --&amp;gt; |run|tflint
 subgraph local
 fmt(terraform fmt)
 tflint
 end
 subgraph pipeline
 linting
 end
 local --&amp;gt; |automate|pipeline&lt;/pre&gt;
&lt;h2 id="preparation"&gt;Preparation&lt;/h2&gt;
&lt;p&gt;Navigate to your existing Terraform working directory:&lt;/p&gt;</description></item></channel></rss>