Using Ansible on Google Compute Engine behind Identity Aware Proxy

Ansible adalah aplikasi yang biasa saya gunakan untuk membantu proses deployment. Mulai dari instalasi paket dasar, hingga konfigurasi spesifik dapat dilakukan menggunakan aplikasi ini. Syarat utama ansible adalah koneksi ssh, khususnya ketika saya melakukan manajemen pada server linux secara remote. Masalahnya adalah linux server yang saya kelola pada google cloud platform hanya bisa diakses melalui Google IAP (identity Aware Proxy). Hal tersebut membuat perintah dan sintaks dasar ssh yang ada pada modul ansible gagal mengakses linux server tersebut.

Setelah gugling, saya menemukan permasalah yang sama di stackexchange. Jawaban pada tautan tersebut mengatakan bahwa salah satu solusinya adalah membuat sebuah ssh wrapper script yang menjalankan perintah gcloud compute ssh --tunnel-through-iap.

So, lets try it!. Saya membuat beberapa file, yaitu konfigurasi ansible ansible.cfg, inventori file hosts, playbook yaml update.yml, dan ssh wrapper script yang saya simpan di misc/gssh.sh. Jika dilihat struktur direktorinya akan seperti ini:

.
├── ansible.cfg
├── hosts
├── misc
│   └── gssh.sh
└── update.yml

1 directory, 4 files

ansible.cfg adalah konfigurasi file yang akan dibaca bersamaan dengan direktori tempat menjalankan perintah ansible. Jika diperhatikan ada nilai yang mungkin agak aneh bagi kalian, yaitu forks = 1. Dasarnya ansible forks memiliki nilai 5, dan disini saya hanya menggunakan satu. Hal ini saya lakukan karena perintah gcloud tidak dibuat untuk dijalankan secara paralel atau bersamaan, sehingga akan terjadi error jika diset lebih dari satu. Yup, itu berarti setiap perintah pada playbook ansible akan diselesaikan lebih lama. Ya bisa ditinggal ngopi jika perintah yang dijalankan dan target servernya banyak.

# ansible configuration file
# ansible.cfg

[ssh_connection]
pipelining = True
ssh_executable = misc/gssh.sh
ssh_args =
transfer_method = piped

[defaults]
forks = 1
interpreter_python = '/usr/bin/env python3'
gathering = False
strategy = free

Selanjutnya adalah ssh wrapper script yang diletakkan pada misc/gssh.sh. Sederhananya skrip ini menjalankan perintah gcloud compute ssh --tunnel-through-iap dan tambahan argumen lain dari ansible.

#!/bin/bash
# ssh wrapper using gcloud command
# misc/gssh.sh

host="${@: -2: 1}"
cmd="${@: -1: 1}"

socket="/tmp/ansible-ssh-${target_host}-22-iap"

gcloud_args="--tunnel-through-iap \
--project=corp-project-id \
--zone=us-central1-a
--quiet
--no-user-output-enabled
--
-C
-o ControlMaster=auto
-o ControlPersist=20
-o PreferredAuthentications=publickey
-o KbdInteractiveAuthentication=no
-o PasswordAuthentication=no
-o ConnectTimeout=20"

if [ -e "$socket" ]; then
  exec gcloud compute ssh "$host" \
       $gcloud_args \
       -o ControlPath="$socket" \
       "$cmd"
else
  exec gcloud compute ssh "$host" \
       $gcloud_args \
       -o ControlPath="$socket" \
       "$cmd"
fi

Sebuah file inventori ansible yang berisikan nama vm, dan konfigurasi user yang digunakan untuk login.

[gcp:vars]
ansible_user='ubuntu'

[gcp]
n1-elastic-corp
n2-elastic-corp

Terakhir adalah file ansible playbook yang berisi perintah apt update && apt upgrade, serta melakukan reboot jika diperlukan. File tersebut saya simpan pada update.yml

---
- hosts: gcp
  become: yes
  become_user: root
  tasks:
    - name: Update apt repo and cache on all Debian/Ubuntu boxes
      apt:
        update_cache : yes
        force_apt_get : yes
        cache_valid_time : 3600

    - name: Upgrade all packages on servers
      apt:
        upgrade : 'yes'
        force_apt_get : yes

    - name: Check if a reboot is needed on all servers
      register: reboot_required_file
      stat:
        path : /var/run/reboot-required
        get_md5 : no

    - name: Reboot the box if kernel updated
      reboot:
        msg: "Reboot initiated by Ansible for kernel updates"
        connect_timeout: 5
        reboot_timeout: 300
        pre_reboot_delay: 0
        post_reboot_delay: 30
        test_command: uptime
      when: reboot_required_file.stat.exists

Selanjutnya jalankan menggunakan perintah berikut dan lihat hasilnya:

ansible-playbook -i hosts update.yml

No Comments Yet