Artifact Management #
Artifact adalah output dari proses build yang siap di-deploy — Docker image, package Python, binary yang dikompilasi, atau archive tarball. Mengelola artifact dengan baik berarti: artifact bisa ditelusuri ke commit yang membuatnya, tersimpan di tempat yang persisten dan bisa diakses oleh semua environment, versinya immutable (tidak bisa diubah setelah dibuat), dan yang sudah tidak digunakan bersih dari storage. Ansible bisa mengotomasi seluruh lifecycle ini.
Prinsip Artifact yang Baik #
1. Immutable
Setelah artifact bertag v2.1.0 dibuat, isinya tidak pernah berubah.
Jika ada bugfix, buat artifact baru dengan tag v2.1.1.
2. Traceable
Dari artifact, bisa ditelusuri: kode commit mana yang membuatnya,
siapa yang menjalankan build, kapan, dan dari branch mana.
3. Verified
Setiap artifact punya checksum (SHA256) yang bisa diverifikasi
sebelum deployment — memastikan artifact tidak rusak atau dimanipulasi.
4. Lifecycle-Managed
Artifact lama yang tidak diperlukan dibersihkan secara otomatis
untuk menghemat storage.
Docker Image sebagai Artifact #
Docker registry adalah cara paling umum untuk mendistribusikan artifact berbasis container:
# playbooks/build-artifact.yml
---
- name: Build dan push Docker image artifact
hosts: localhost
vars:
registry: registry.company.com
image_name: myapp
version: "{{ version | mandatory }}"
git_sha: "{{ lookup('pipe', 'git rev-parse --short HEAD') }}"
build_date: "{{ ansible_date_time.iso8601 }}"
tasks:
- name: Login ke registry
community.docker.docker_login:
registry_url: "{{ registry }}"
username: "{{ registry_username }}"
password: "{{ vault_registry_password }}"
no_log: true
- name: Build image dengan label untuk traceability
community.docker.docker_image:
name: "{{ registry }}/{{ image_name }}"
tag: "{{ version }}"
source: build
build:
path: "{{ playbook_dir }}/.."
labels:
version: "{{ version }}"
git.sha: "{{ git_sha }}"
build.date: "{{ build_date }}"
build.pipeline: "{{ lookup('env', 'CI_PIPELINE_ID') | default('local') }}"
args:
APP_VERSION: "{{ version }}"
state: present
- name: Push image ke registry
community.docker.docker_image:
name: "{{ registry }}/{{ image_name }}"
tag: "{{ version }}"
push: true
source: local
- name: Generate checksum manifest
command: >
docker inspect
--format="{{ '{{' }}index .RepoDigests 0{{ '}}' }}"
{{ registry }}/{{ image_name }}:{{ version }}
register: image_digest
changed_when: false
- name: Simpan artifact manifest
copy:
content: |
image={{ registry }}/{{ image_name }}:{{ version }}
digest={{ image_digest.stdout }}
version={{ version }}
git_sha={{ git_sha }}
build_date={{ build_date }}
dest: "{{ playbook_dir }}/artifact-manifest.txt"
delegate_to: localhost
Distribusi Artifact ke Managed Node #
# playbooks/distribute-artifact.yml
---
- name: Distribusikan artifact ke managed node
hosts: appservers
vars:
artifact_url: "https://artifacts.company.com/releases/{{ app_name }}/{{ version }}/{{ app_name }}-{{ version }}.tar.gz"
artifact_checksum: "sha256:{{ artifact_sha256 }}"
tasks:
- name: Buat direktori artifact
file:
path: /opt/releases/{{ version }}
state: directory
owner: deployer
mode: '0755'
- name: Download artifact dengan verifikasi checksum
get_url:
url: "{{ artifact_url }}"
dest: "/opt/releases/{{ version }}/app.tar.gz"
checksum: "{{ artifact_checksum }}" # Ansible otomatis verifikasi setelah download
owner: deployer
mode: '0644'
register: artifact_download
- name: Extract artifact
unarchive:
src: "/opt/releases/{{ version }}/app.tar.gz"
dest: "/opt/releases/{{ version }}/"
remote_src: true
when: artifact_download.changed
- name: Atomic symlink switch ke versi baru
file:
src: "/opt/releases/{{ version }}"
dest: /opt/app/current
state: link
force: true # Overwrite symlink yang ada
- name: Bersihkan release lama (simpan 3 terakhir)
shell: |
ls -dt /opt/releases/*/ | tail -n +4 | xargs rm -rf
args:
warn: false
changed_when: false
Pola atomic symlink adalah cara yang elegan untuk deployment tanpa downtime — symlink /opt/app/current di-update atomically setelah semua file sudah di-extract.
Artifact di Object Storage (S3/MinIO) #
Untuk artifact non-container seperti binary atau package:
# Upload artifact ke S3 setelah build
- name: Upload artifact ke S3
amazon.aws.s3_object:
bucket: company-artifacts
object: "releases/{{ app_name }}/{{ version }}/{{ app_name }}-{{ version }}.tar.gz"
src: "/tmp/build/{{ app_name }}-{{ version }}.tar.gz"
mode: put
metadata:
version: "{{ version }}"
git_sha: "{{ git_sha }}"
build_date: "{{ ansible_date_time.iso8601 }}"
region: ap-southeast-1
# Upload checksum file
- name: Upload SHA256 checksum
amazon.aws.s3_object:
bucket: company-artifacts
object: "releases/{{ app_name }}/{{ version }}/{{ app_name }}-{{ version }}.tar.gz.sha256"
content: "{{ artifact_sha256 }} {{ app_name }}-{{ version }}.tar.gz"
mode: put
region: ap-southeast-1
Artifact Lifecycle Management #
Artifact lama yang menumpuk menghabiskan storage yang mahal. Bersihkan secara berkala:
# playbooks/cleanup-artifacts.yml
---
- name: Bersihkan artifact Docker yang sudah tidak dipakai
hosts: localhost
vars:
registry: registry.company.com
image_name: myapp
keep_versions: 10 # Simpan 10 versi terakhir
tasks:
- name: Ambil semua tag image dari registry
uri:
url: "https://{{ registry }}/v2/{{ image_name }}/tags/list"
headers:
Authorization: "Bearer {{ vault_registry_token }}"
return_content: true
register: image_tags
no_log: true
- name: Sortir tag dan ambil yang akan dihapus
set_fact:
tags_to_delete: >-
{{ image_tags.json.tags
| sort
| list
| difference(['latest'])
| list
| reverse
| list
| skip(keep_versions) }}
- name: Hapus tag lama dari registry
uri:
url: "https://{{ registry }}/v2/{{ image_name }}/manifests/{{ item }}"
method: DELETE
headers:
Authorization: "Bearer {{ vault_registry_token }}"
status_code: [202, 404]
loop: "{{ tags_to_delete }}"
loop_control:
label: "Menghapus tag: {{ item }}"
Ringkasan #
- Artifact harus immutable — setelah dibuat dengan tag tertentu, isinya tidak pernah berubah. Bugfix = artifact baru dengan tag baru.
- Tambahkan label/metadata ke artifact saat build: versi, git SHA, tanggal build, pipeline ID — memungkinkan traceability penuh dari artifact ke kode sumber.
- Gunakan
checksum:diget_urluntuk memverifikasi integritas artifact setelah download — mendeteksi download yang rusak atau artifact yang dimanipulasi.- Atomic symlink (
/opt/app/current → /opt/releases/v2.1.0) adalah pola deployment yang elegan — switch versi terjadi secara atomic, rollback semudah mengganti symlink.- Simpan checksum artifact di tempat yang terpisah dari artifact itu sendiri — idealnya di object storage yang berbeda atau signed secara kriptografis.
- Lifecycle management: bersihkan artifact lama secara otomatis — simpan hanya N versi terakhir untuk mengontrol biaya storage.
← Sebelumnya: Rollback Strategy Berikutnya: Notification & Reporting →