<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tommy Heng-Chuan Lin</title>
    <description>The latest articles on DEV Community by Tommy Heng-Chuan Lin (@tommyhenchuanlin).</description>
    <link>https://dev.to/tommyhenchuanlin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1033506%2Fb6052720-bd2a-43af-9cb3-72eaeba57f98.jpeg</url>
      <title>DEV Community: Tommy Heng-Chuan Lin</title>
      <link>https://dev.to/tommyhenchuanlin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tommyhenchuanlin"/>
    <language>en</language>
    <item>
      <title>Pipeline example using Terraform, Jenkins, Ansible, and Docker on Google Cloud-Part 2</title>
      <dc:creator>Tommy Heng-Chuan Lin</dc:creator>
      <pubDate>Sun, 05 Mar 2023 15:29:29 +0000</pubDate>
      <link>https://dev.to/tommyhenchuanlin/pipeline-example-using-terraform-jenkins-ansible-and-docker-on-google-cloud-part-2-2kgj</link>
      <guid>https://dev.to/tommyhenchuanlin/pipeline-example-using-terraform-jenkins-ansible-and-docker-on-google-cloud-part-2-2kgj</guid>
      <description>&lt;p&gt;Today I will keep working on part 2&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone or Fork project folder
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/aks60808/AiGames" rel="noopener noreferrer"&gt;https://github.com/aks60808/AiGames&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;make sure you have this project in your repository!&lt;/p&gt;

&lt;h2&gt;
  
  
  Jenkins Plugin Install
&lt;/h2&gt;

&lt;p&gt;Get into your Jenkins page &lt;a href="http://YOUR_CICD_SERVER_IP:8080/" rel="noopener noreferrer"&gt;http://YOUR_CICD_SERVER_IP:8080/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The followings are plugins we needed for this walkthrough&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ansible&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker Pipeline&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NodeJS&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ThinBackup&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Cloud Storage&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GO TO Dashboard ⇒ manage plugins&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxz16b3yde2dd5f2wtd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxz16b3yde2dd5f2wtd9.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Search and Tick all the required plugin to install (&lt;strong&gt;Click Download  &amp;amp; install with restart&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7pkj1ncdfxhe3yaqrdl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7pkj1ncdfxhe3yaqrdl.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configure Global tool
&lt;/h2&gt;

&lt;p&gt;once you had the required plugins installed, GO TO Dashboard ⇒ Global Tool Configuration&lt;/p&gt;

&lt;p&gt;We are going to configure some useful tool while building pipeline&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxsfj39xztohshuoqbrx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxsfj39xztohshuoqbrx.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Name the NodeJS plugins ⇒ MyNodeJS (this should match your naming in jenkinsfile)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm5uwpfhctxxtgzgxj61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm5uwpfhctxxtgzgxj61.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Name the Docker plugins ⇒ MyDocker (this should match your naming in jenkinsfile)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftas2ugohfiwe1xu42iah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftas2ugohfiwe1xu42iah.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Configure Depolyment Server
&lt;/h1&gt;

&lt;p&gt;to get into deployment server with ansible, we need to configure hosts/inventory again.&lt;/p&gt;
&lt;h2&gt;
  
  
  Generate ssh keys for cicd server
&lt;/h2&gt;

&lt;p&gt;first open terminal and ssh into cicd server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh YOUR_CICD_SERVER_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in your home directory, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;read the public key file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;copy the content on the terminal then paste to &lt;strong&gt;GOOGLE COMPUTE ENGINE page ⇒&lt;/strong&gt; &lt;strong&gt;metadata ⇒ ssh keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;then saved. (like what we did in part 1)&lt;/p&gt;

&lt;h2&gt;
  
  
  Put ssh private key into Jenkins
&lt;/h2&gt;

&lt;p&gt;During Jenkins building process, I found that it is hard to get in user’s home directory unless you specify the absolute path. Hence, the more secure and well-managed way is to put credentials in Jenkins-managed Credentials.&lt;/p&gt;

&lt;p&gt;Click Manage Credentials →SYSTEM → Global credentials → Add Credentials&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhwc0mzwc2qzn3620cl9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhwc0mzwc2qzn3620cl9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CICD ssh private key
&lt;/h2&gt;

&lt;p&gt;we need to put the private key we’ve created previously (~/.ssh/id_rsa).&lt;/p&gt;

&lt;p&gt;select SSH username with private and specify your credential ID, ssh login username and private key content.&lt;/p&gt;

&lt;p&gt;Please be noted that the ID should match the Credential ID setup in the Jenkinsfile pipeline script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkhygz42cs37ds25i707.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkhygz42cs37ds25i707.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;copy the content of the private key put into key section then saved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure hosts on CICD server
&lt;/h2&gt;

&lt;p&gt;We will use ansible to configure Deployment server throughout the CICD pipeline.&lt;/p&gt;

&lt;p&gt;Go to ansible folder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/ansible/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit hosts file with sudo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put following content into the hosts file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[depolyment]
x.x.x.x 
# replace above with depolyment server IP address
[depolyment:vars]
ansible_user=tommylin   
# replace above with your login username
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t forget to put deployment server ip and your ssh login username in the file!&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Deployment server
&lt;/h2&gt;

&lt;p&gt;in your local project directory, use text editor to open  &lt;strong&gt;ansible_playbook/deployment_server_init_config.yml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Docker&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;depolyment&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tommylin"&lt;/span&gt;
    &lt;span class="c1"&gt;# replace the above username with yours.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace with your ssh login user name for purpose of adding $USER to docker group.&lt;/p&gt;

&lt;p&gt;After that, in project directory run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible-playbook &lt;span class="nt"&gt;-i&lt;/span&gt; inventory ansible_playbook/deployment_server_init_config.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The playbook will configure deployment server with docker installation.&lt;/p&gt;

&lt;p&gt;Create a pipeline job&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnadq0mff49fs0vvnkdip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnadq0mff49fs0vvnkdip.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable Discard Old builds
&lt;/h2&gt;

&lt;p&gt;We will create docker image release throughout building action, we don’t need to keep every build as it could be tons of large build increase the burden of backup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz03j2y03kcwxyxdiyax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz03j2y03kcwxyxdiyax.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tick GitHub hook trigger
&lt;/h2&gt;

&lt;p&gt;This is where our github webhook magic enabled on Jenkins’ side!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4s57ndl4i2yk1ggtn9u4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4s57ndl4i2yk1ggtn9u4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  GET the pipeline Script from Github
&lt;/h2&gt;

&lt;p&gt;Put your project repo URL into Repositories URL blank. If your repo is private then Credentials is needed(Can configure it using Jenkins managed credentials). Other box I just leave them as default settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrdkeuieezzvxyo2be33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrdkeuieezzvxyo2be33.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rnw3ybp53l86eygrgnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rnw3ybp53l86eygrgnw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  GITHUB WEBOOK setup
&lt;/h2&gt;

&lt;p&gt;In your GitHub Repo page, click Settings icon ⇒ Webhooks ⇒ Add webhook&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mwebfy3o6a9lptc068u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mwebfy3o6a9lptc068u.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PUT IN  &lt;strong&gt;&lt;a href="http://CICD_SERVER_IP:8080/github-webhook" rel="noopener noreferrer"&gt;http://CICD_SERVER_IP:8080/github-webhook&lt;/a&gt;&lt;/strong&gt; into the Payload URL blank.&lt;/p&gt;

&lt;p&gt;DON’T FORGET to select JSON format as your Content type&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp01hyzlvl8paua359y7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp01hyzlvl8paua359y7u.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click Add webhook button then we are almost there!!&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the place where you store releases
&lt;/h3&gt;

&lt;p&gt;go to Google Container Registry console to configure visibility to public.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff43ejj5wi2w5bdzt1hj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff43ejj5wi2w5bdzt1hj4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Action triggered by GitHub push!
&lt;/h2&gt;

&lt;p&gt;you can make dummy commit then push to the master testing the automation. You can click the build number to get detailed information as Console output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5fu80lk3ys07kg42gvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5fu80lk3ys07kg42gvx.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb51idkd5jx1ezwx2ic72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb51idkd5jx1ezwx2ic72.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the release on Google Container Registry after build success.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpof3tsk9muujm93qdm5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpof3tsk9muujm93qdm5d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Well done! CHECK THE DEPLOYMENT SERVER!
&lt;/h2&gt;

&lt;p&gt;you can go visit  &lt;strong&gt;&lt;a href="http://YOUR_DEPLOYMENT_SERVER_IP:3000/AiGames/game/sudoku" rel="noopener noreferrer"&gt;http://YOUR_DEPLOYMENT_SERVER_IP:3000/AiGames/game/sudoku&lt;/a&gt;&lt;/strong&gt; to have some fun with these games&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsx6raurjspleezo13yw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsx6raurjspleezo13yw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Backup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setup ThinBackup
&lt;/h3&gt;

&lt;p&gt;In this walkthrough, Google Cloud Storage are used to backup jenkins. &lt;/p&gt;

&lt;p&gt;GO TO JENKINS Dashboard and &lt;strong&gt;SCROLL DOWN&lt;/strong&gt;, you will see the &lt;strong&gt;ThinBackup plugin&lt;/strong&gt; we just installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz540b7ks9ri5jvanwflq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz540b7ks9ri5jvanwflq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Click Settings
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo2osgeeuws67ts1myoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo2osgeeuws67ts1myoe.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the following
&lt;/h3&gt;

&lt;p&gt;Set Backup directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;${HOME}/.jenkins-backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Backup schedule ( I backup @7:00 AM everyday)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j9uhlc2kds93d7duj4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j9uhlc2kds93d7duj4a.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomwfaliql1ho6fg2kzji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomwfaliql1ho6fg2kzji.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
I only backed up build results, userContent folder and Backup plugins archives since I don’t need any build artifact being backup from Jenkins. I only backup my worksapce configuration.&lt;/p&gt;

&lt;p&gt;after click SAVE button, thinbackup will backup jenkins on your VM.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bring Backup to Google Cloud Storage
&lt;/h3&gt;
&lt;h3&gt;
  
  
  PUT Service account key into Jenkins-managed credentials
&lt;/h3&gt;

&lt;p&gt;Specify you &lt;strong&gt;GCP project ID&lt;/strong&gt; and &lt;strong&gt;service account key .json file&lt;/strong&gt; then click create.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxko5qttyuxxnel46cvka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxko5qttyuxxnel46cvka.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a pipeline job
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5t9o30suvv25q7m7sak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5t9o30suvv25q7m7sak.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
This job will start 9:00 AM everyday, right after thinbackup!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3igbudrq6kfgakyhfrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3igbudrq6kfgakyhfrr.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
In Pipeline Script section, Please copy and paste this snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;JENKINS_BACKUP_FILE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
         &lt;span class="n"&gt;SA_KEY_CRED_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'YOUR PROJECT ID(JENKINS MANAGED CRED)'&lt;/span&gt;
            &lt;span class="n"&gt;GCS_BUCKET_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'YOUR GCS BUCKET URL'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;
    &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Backing up Jenkins'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;JENKINS_BACKUP_FILE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="nl"&gt;script:&lt;/span&gt; &lt;span class="s1"&gt;'''#!/bin/bash
                            # find latest backup
                            thinbackup_path="$JENKINS_HOME/.jenkins-backup"
                            latest_backup_folder=$(ls -t $thinbackup_path | head -n1)
                            full_path="$thinbackup_path/$latest_backup_folder"

                            # pack it up
                            backup_name="$latest_backup_folder.tar.gz"
                            tar cvzf $backup_name $full_path
                            echo ${backup_name}
                            '''&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="nl"&gt;returnStdout:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
                    &lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;tokenize&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="n"&gt;$class&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'ClassicUploadStep'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;credentialsId:&lt;/span&gt; &lt;span class="s2"&gt;"${SA_KEY_CRED_ID}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  
                &lt;span class="nl"&gt;bucket:&lt;/span&gt; &lt;span class="s2"&gt;"${GCS_BUCKET_URL}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                      &lt;span class="nl"&gt;pattern:&lt;/span&gt; &lt;span class="n"&gt;JENKINS_BACKUP_FILE_NAME&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
                &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'''
                 rm '''&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;JENKINS_BACKUP_FILE_NAME&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;'''
                '''&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Go to Google Cloud Storage
&lt;/h3&gt;

&lt;p&gt;you can directly click build now to run the upload mission. you should see these kind of backup files in your cloud storage.&lt;/p&gt;

&lt;p&gt;Please be noted that in cicd_server.tf I’ve stated the lifecycle_rule age = 2 days for cloud storage. Dpn’t get confused if it only keep 2 copies all the time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz434uo8nobs79lxrqpaj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz434uo8nobs79lxrqpaj.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;In the end, don’t forget to cleanup using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DONT FORGET ENTER YES !&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary:
&lt;/h2&gt;

&lt;p&gt;In part 2, I use Jenkins, Anisble, and docker to host a web on Google Compute Engine. I understand that there are tons of act can be improved to obtain a more resilient and reliable pipeline. This is the very first pipeline I had ever built. If you are a beginner as me, hope this walkthrough can get you some feeling about how a pipeline being constructed. Thank you for your time reading this :)&lt;/p&gt;

</description>
      <category>devops</category>
      <category>beginners</category>
      <category>googlecloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Pipeline example using Terraform, Jenkins, Ansible, and Docker on Google Cloud-Part 1</title>
      <dc:creator>Tommy Heng-Chuan Lin</dc:creator>
      <pubDate>Sat, 25 Feb 2023 13:59:14 +0000</pubDate>
      <link>https://dev.to/tommyhenchuanlin/pipeline-example-using-terraform-jenkins-ansible-and-docker-on-google-cloud-4g1e</link>
      <guid>https://dev.to/tommyhenchuanlin/pipeline-example-using-terraform-jenkins-ansible-and-docker-on-google-cloud-4g1e</guid>
      <description>&lt;h2&gt;
  
  
  Project brief intro:
&lt;/h2&gt;

&lt;p&gt;This project I made is for the demonstration of pipelines. I utilised Terraform Cloud provisioning infras on GCP, using Ansible to configure remote VM instances for initiation and deployment, Docker image as artifact for deployment and finally, a Jenkins server integrating webhook from GitHub and further CICD process. &lt;/p&gt;

&lt;p&gt;This project was split into two articles for the sack of large context, I tried to template the source code so that it should be easy to follow stepwise. The first part would be the prerequisite walkthrough, provisioning infra and initialising Jenkins on CICD server. &lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gwljz352h99qfrahgsm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gwljz352h99qfrahgsm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;OS: Linux/MacOS&lt;/li&gt;
&lt;li&gt;Local installation of Terraform and Ansible&lt;/li&gt;
&lt;li&gt;Google Cloud Platform Account&lt;/li&gt;
&lt;li&gt;Terraform Cloud Account&lt;/li&gt;
&lt;li&gt;GCP CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enable GCP APIs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Compute Engine API&lt;/li&gt;
&lt;li&gt;Google Container Registry API&lt;/li&gt;
&lt;li&gt;Google Cloud Storage API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create Organization and Workspace on Terraform Cloud
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cloud.hashicorp.com/products/terraform" rel="noopener noreferrer"&gt;Terraform | HashiCorp Cloud Platform&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a new GCP project
&lt;/h2&gt;

&lt;p&gt;go to GCP console then create a new project and have your gcloud cli configured to that new project&lt;/p&gt;

&lt;p&gt;&lt;a href="https://console.cloud.google.com/" rel="noopener noreferrer"&gt;Google Console Page&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone Pipeline Project repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/aks60808/Devops-Aigames" rel="noopener noreferrer"&gt;Pipeline Project Links&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git clone https://github.com/aks60808/Devops-Aigames


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Configure GCP
&lt;/h2&gt;

&lt;p&gt;To make terraform cloud provisioning infra from GCP, the following are required to provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Service Account&lt;/li&gt;
&lt;li&gt;Grant permission for the role&lt;/li&gt;
&lt;li&gt;Create a Service Account Key for further authentication&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Login to GCP first
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

gcloud auth login


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Create Service Account
&lt;/h3&gt;

&lt;p&gt;replacing SA_NAME with your preferred Service Account name.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

gcloud iam service-accounts create SA_NAME &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"DESCRIPTION"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--display-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"DISPLAY_NAME"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Grant IAM as an editor role
&lt;/h3&gt;

&lt;p&gt;replacing PROJECT_ID with your PROJECT_ID on gcp console&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

gcloud projects add-iam-policy-binding PROJECT_ID &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/editor"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Create a service account key
&lt;/h3&gt;

&lt;p&gt;It’s up to you to determine the location of the service account key, which typically would be stored in ~/.ssh/ directory.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

gcloud iam service-accounts keys create YOUR_SA_KEY_PATH &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--iam-account&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;SA_NAME@PROJECT_ID.iam.gserviceaccount.com


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Configure Terraform to Terraform Cloud
&lt;/h2&gt;

&lt;p&gt;in these .tf files, they will provision several resources including&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Compute Instance *2 (e2.medium) for service hosting&lt;/li&gt;
&lt;li&gt;Google VPC and corresponding firewall rules allowing http and ssh&lt;/li&gt;
&lt;li&gt;Google Container registry for docker image push in Part 2.&lt;/li&gt;
&lt;li&gt;Google Cloud Storage for backing up Jenkins in Part 2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frist, Let's get into the project directory:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; /Devops-Aigames


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Modify the following main.tf&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# store terraform states on terraform cloud
terraform {
  cloud {
    # replace with your organization
    organization = "REPLACE WITH YOUR ORGANIZATION NAME"

    workspaces {
    # replace with your workspace name
      name = "REPLACE WITH YOUR WORKSPACE NAME"
    }
  }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;create a file named terraform.tfvars in project directory&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;touch &lt;/span&gt;terraform.tfvars


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;add the following content to terraform.tfvars&lt;br&gt;
Regions &amp;amp; their corresponding zones can be referred to &lt;a href="https://cloud.google.com/compute/docs/regions-zones" rel="noopener noreferrer"&gt;Google compute Regions-Zones List&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

project_id &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"REPLACE WITH　YOUR　GCP　PROJECT　ID"&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"REPLACE WITH　YOUR　PREFERRED　REGION"&lt;/span&gt;
zone &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"REPLACE WITH　YOUR　PREFERRED　ZONE"&lt;/span&gt;

&lt;span class="c"&gt;# these are variables that will be used in the terraform configuration&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Add your GCP service account key to Terraform Cloud
&lt;/h3&gt;

&lt;p&gt;Go to the Terraform Cloud service, select your right organization/workpace, click &lt;strong&gt;Variables&lt;/strong&gt; on the left Menu Bar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farthh3o32ofe6pro17np.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farthh3o32ofe6pro17np.png" alt="Menu Bar on terraform cloud"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click Add variable button&lt;/li&gt;
&lt;li&gt;Select Terraform variable&lt;/li&gt;
&lt;li&gt;In KEY section, you MUST type in GOOGLE_CREDENTIALS&lt;/li&gt;
&lt;li&gt;COPY and PASTE all content of the Service Account key(JSON file) into the Value section.&lt;/li&gt;
&lt;li&gt;Don’t forget to tick Sensitive and click Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy8ke98s3mjq2vpfywagc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy8ke98s3mjq2vpfywagc.png" alt="The place you should put your SA key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the reasoning of the above configuration, please refer to Terraform documentation&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjzoo00ts3wer6fn98xm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjzoo00ts3wer6fn98xm.png" alt="GCP credential configuration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/getting_started" rel="noopener noreferrer"&gt;Terraform Registry&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Login to Terraform Cloud
&lt;/h2&gt;

&lt;p&gt;run terraform login and have the token value pasted into terminal&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

terraform login


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Initial your local terraform to terraform cloud
&lt;/h2&gt;

&lt;p&gt;run the following command to get terraform connected to terraform cloud &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

terraform init


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Start Provisioning your infra on GCP using terraform
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

terraform plan
terraform apply
terraform output &lt;span class="c"&gt;# to see your VM ip&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Ansible Configure management
&lt;/h2&gt;

&lt;p&gt;Now we will utilise ansible to configure the remote CICD server&lt;/p&gt;
&lt;h3&gt;
  
  
  Generate ssh key if needed
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# USERNAME should match your current username&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/KEY_FILENAME &lt;span class="nt"&gt;-C&lt;/span&gt; USERNAME &lt;span class="nt"&gt;-b&lt;/span&gt; 2048


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Visit GCE instance page click metadata&amp;gt;&amp;gt; ssh keys&amp;gt;&amp;gt;add ssh key
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubilcxb4tcuzed7c9kwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubilcxb4tcuzed7c9kwp.png" alt="GCE metadata page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;copy your generated .pub key then saved.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create an inventory file in project directory
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;touch &lt;/span&gt;inventory


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;put the following content into inventory file&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[cicd]
x.x.x.x 
# replace above with CICD server IP address
[cicd:vars]
ansible_ssh_private_key_file= /path/to/your/private/ssh/key
[depolyment]
x.x.x.x 
# replace above with depolyment server IP address
[depolyment:vars]
ansible_ssh_private_key_file= /path/to/your/private/ssh/key


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Configure ansible.cfg file
&lt;/h3&gt;

&lt;p&gt;check the location of ansible.cfg by running the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

ansible-config &lt;span class="nt"&gt;--version&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;if you saw the &lt;strong&gt;config file = None&lt;/strong&gt;, then in current directory, run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

ansible-config init &lt;span class="nt"&gt;--disabled&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ansible.cfg


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;modify the ansible.cfg by setting:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;host_key_checking&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;False


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;then saved.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try reaching out CICD and Deployment server via ansible
&lt;/h3&gt;

&lt;p&gt;run the following command to test the ssh connectivity of two hosts.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# -i flag specify your inventory path&lt;/span&gt;
ansible all &lt;span class="nt"&gt;-m&lt;/span&gt; ping &lt;span class="nt"&gt;-i&lt;/span&gt; ./inventory


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;you should see the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflq6j7nhzatm21x6ddyy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflq6j7nhzatm21x6ddyy.png" alt="Ping success"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure CICD server using Ansible
&lt;/h3&gt;

&lt;p&gt;before start configuring, go to &lt;strong&gt;ansible_playbook/ then open&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ansible_deployment.yml&lt;/strong&gt; to modify the project_id, replace it with yours.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy app to server&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;project_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YOUR_GCP_PROJECT_ID&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;cicd_server_init_config.yml&lt;/strong&gt; to modify the service account key and ansible_deployment.yml playbook location(ansible_deployment.yml is in project dir/ansible_playbooks)&lt;/p&gt;

&lt;p&gt;the Path should be in absolute path format, key_dest and playbook_dest are set to jenkins home directory, so you don't need to modify them.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Activate Service account&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cicd&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;key_src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YOUR/LOCAL/ABSOLUTE/PATH/TO/sa_key.json&lt;/span&gt; 
    &lt;span class="na"&gt;key_dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/lib/jenkins/key.json&lt;/span&gt;

&lt;span class="s"&gt;......&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload playbook to CICD server&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cicd&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;playbook_src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YOUR/LOCAL/ABSOLUTE/PATH/TO/ansible_deployment.yml&lt;/span&gt;
    &lt;span class="na"&gt;playbook_dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/lib/jenkins/ansible_deployment.yml&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;the ansible playbook will &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pass your service account key to CICD server&lt;/li&gt;
&lt;li&gt;install Docker, Jenkins, and Ansible&lt;/li&gt;
&lt;li&gt;Configure what’s necessary for running the operations including adding jenkins to docker group and cgroup mounting&lt;/li&gt;
&lt;li&gt;pass deployment playbook to CICD server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;in the project directory, &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="s"&gt;ansible-playbook -i inventory \&lt;/span&gt;
                    &lt;span class="s"&gt;ansible_playbook/cicd_server_init_config.yml&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After completion, you should open your browser via &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc07rnz72rwly2w7t3vfq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc07rnz72rwly2w7t3vfq.png" alt="Jenkins initialisation"&gt;&lt;/a&gt;&lt;br&gt;
PS. Initial ADMIN PWD will can be found either in the file location or the stdout on your terminal&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1dze3dlnao2tri32d40c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1dze3dlnao2tri32d40c.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;DO NOT CLEAN UP UNLESS YOU WANT TO SKIP PART II!&lt;/p&gt;

&lt;p&gt;If you wish to terminate the whole setup, in the project directory run the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

terraform destroy


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;DON'T FORGET TO ENTER YES TO PROCEED!&lt;/p&gt;

&lt;h2&gt;
  
  
  To be continued
&lt;/h2&gt;

&lt;p&gt;In the next article, I will continue building Jenkins CICD pipeline to build, test, package and finally deploy for hosting a website offering algorithm-based fun games written by my good friend, &lt;a href="https://github.com/Gravender/AiGames" rel="noopener noreferrer"&gt;Noah&lt;/a&gt;(big shoutout to you:)). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tommyhenchuanlin/pipeline-example-using-terraform-jenkins-ansible-and-docker-on-google-cloud-part-2-2kgj"&gt;Part 2 article link&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>beginners</category>
      <category>googlecloud</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
