Tampilan
Kenapa penting
Satu service punya satu application.yml — gampang. Begitu sistemmu tumbuh menjadi 10 service, masing-masing dengan profil dev, staging, dan prod, kamu punya puluhan file konfigurasi yang tersebar di banyak repo. URL broker yang sama ditulis berulang, timeout berbeda tanpa alasan, dan mengubah satu nilai berarti build ulang dan redeploy banyak image. Lebih buruk lagi, password database ikut ter-commit di repo kode. Di tempat kerja, kemampuan mengelola konfigurasi dan secret secara terpusat, ter-versi, dan bisa diaudit adalah syarat dasar sistem terdistribusi yang sehat — dan sering jadi bahan insiden bila diabaikan.
Konsep inti
Masalah konfigurasi di banyak service
Konfigurasi adalah segala hal yang berbeda antar-environment tetapi bukan kode: URL database, alamat broker, timeout, feature flag, batas transaksi. Prinsip twelve-factor menyarankan konfigurasi dipisah dari artefak build, sehingga image yang sama bisa dipromosikan dari staging ke production tanpa build ulang.
Di microservices muncul masalah tambahan:
| Masalah | Akibat |
|---|---|
| Nilai yang sama ditulis berulang | Satu service lupa diubah, perilaku tidak konsisten |
| Konfigurasi ikut di dalam image | Ubah satu timeout = build dan deploy ulang |
| Secret di repo kode | Bocor ke semua orang yang punya akses repo |
| Tidak ada riwayat perubahan | Saat insiden, tidak ada yang tahu siapa mengubah apa |
Solusinya: satu sumber konfigurasi yang dibaca semua service saat start, dengan riwayat perubahan yang jelas.
Spring Cloud Config Server (backend Git)
Spring Cloud Config Server adalah aplikasi Spring Boot kecil yang menyajikan konfigurasi lewat HTTP. Backend paling umum adalah repo Git, sehingga setiap perubahan otomatis punya commit, author, dan bisa di-review lewat pull request.
java
// Potongan — aplikasi Config Server
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}yaml
# application.yml milik Config Server
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://git.example.com/platform/config-repo.git
default-label: main
search-paths: "{application}"Dependency-nya org.springframework.cloud:spring-cloud-config-server. Struktur repo konfigurasi biasanya seperti ini:
text
config-repo/
├── application.yml # dipakai SEMUA service
├── order-service/
│ ├── order-service.yml # khusus order-service
│ └── order-service-prod.yml # order-service di profil prod
└── payment-service/
└── payment-service.ymlConfig Server menggabungkan file berdasarkan nama aplikasi (spring.application.name), profil, dan label (branch/tag Git). Kamu bisa mengintip hasilnya langsung lewat endpoint /{application}/{profile}:
bash
curl http://localhost:8888/order-service/prodRespons JSON-nya berisi daftar propertySources berurutan — yang paling spesifik (order-service-prod.yml) berada di atas dan menang atas application.yml.
Config client: spring.config.import
Di sisi service, tambahkan org.springframework.cloud:spring-cloud-starter-config, lalu deklarasikan sumber konfigurasi lewat spring.config.import:
yaml
# application.yml milik order-service
spring:
application:
name: order-service
profiles:
active: prod
config:
import: "configserver:http://config-server:8888"Saat startup, service memanggil Config Server dengan nama order-service dan profil prod, lalu menambahkan hasilnya ke Environment. Nilai dari Config Server secara default mengalahkan nilai di application.yml lokal, sehingga file lokal cukup berisi default untuk pengembangan.
Bootstrap context sudah lama ditinggalkan
Tutorial lama memakai bootstrap.yml dan spring.cloud.config.uri. Sejak Spring Boot 2.4, cara yang direkomendasikan adalah spring.config.import. Gunakan cara baru untuk proyek Spring Boot 4.
Fail-fast vs optional:
Ada dua pilihan perilaku bila Config Server tidak bisa dihubungi saat start:
| Deklarasi | Config Server mati saat start |
|---|---|
configserver:http://config:8888 | Aplikasi gagal start (fail-fast) |
optional:configserver:http://config:8888 | Aplikasi tetap start memakai konfigurasi lokal |
Di production, fail-fast biasanya lebih aman: lebih baik pod gagal start dan terlihat jelas daripada diam-diam berjalan dengan URL database localhost dari file lokal. optional: cocok untuk laptop developer. Karena Config Server kini jadi dependency startup semua service, jalankan minimal dua replika dan tambahkan retry di client agar gangguan sesaat tidak menggagalkan deploy.
Refresh saat runtime
Konfigurasi yang dibaca saat start tidak otomatis berubah ketika repo Git berubah. Spring Cloud menyediakan endpoint Actuator /actuator/refresh yang mengambil ulang konfigurasi, lalu:
- me-rebind bean
@ConfigurationPropertiesdengan nilai baru; - membuat ulang bean yang ditandai
@RefreshScopesaat dipakai berikutnya.
java
// Potongan — nilai batas transaksi yang bisa diubah tanpa restart
@ConfigurationProperties(prefix = "payment")
public record PaymentProperties(BigDecimal maxAmount, Duration gatewayTimeout) {}yaml
management:
endpoints:
web:
exposure:
include: health,refreshbash
curl -X POST http://order-service:8080/actuator/refreshEndpoint ini hanya me-refresh satu instance. Untuk banyak instance, Spring Cloud Bus menghubungkan semua service lewat broker (RabbitMQ atau Kafka): satu panggilan /actuator/busrefresh disiarkan ke semua instance. Banyak tim memilih cara yang lebih sederhana — rolling restart lewat pipeline deploy — karena hasilnya lebih bisa diprediksi.
Tidak semua hal layak di-refresh
URL database, ukuran connection pool, atau port server tidak berubah dengan aman di tengah jalan. Batasi refresh untuk nilai yang memang dirancang dinamis: feature flag, batas, timeout, pesan teks.
Secret: enkripsi, Vault, dan pemisahan
Konfigurasi biasa boleh dibaca semua developer; secret (password, API key, private key) tidak. Beberapa pilihan:
- Enkripsi di Config Server. Set
encrypt.key(atau keystore) di Config Server, lalu simpan nilai terenkripsi dengan awalan{cipher}. Config Server men-dekripsi sebelum mengirim ke client.
yaml
# payment-service.yml di repo Git — aman di-commit
payment:
gateway:
api-key: "{cipher}AQB3c9f1e0...ringkas..."- HashiCorp Vault. Config Server bisa memakai Vault sebagai backend, atau service membaca Vault langsung dengan Spring Cloud Vault. Vault menambah rotasi secret, lease, dan audit log akses.
- Kubernetes Secret atau secret manager milik cloud, di-mount ke pod sebagai file atau environment variable.
Apa pun pilihannya, aturannya sama: secret tidak pernah ditulis polos di repo, akses dibatasi seminimal mungkin, dan nilai secret tidak pernah dicetak ke log.
Alternatif: ConfigMap dan Secret Kubernetes
Bila semua service berjalan di Kubernetes, kamu bisa melewatkan Config Server dan memakai objek bawaan:
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: order-service-config
data:
application.yml: |
order:
max-items: 50
payment-timeout: 2sConfigMap di-mount sebagai file, lalu Spring Boot membacanya, misalnya dengan spring.config.import=optional:configtree:/etc/config/ atau lewat lokasi file tambahan. Secret Kubernetes bekerja serupa, tetapi ingat: nilainya hanya di-encode base64, bukan dienkripsi. Aktifkan encryption at rest di etcd dan batasi RBAC.
| Aspek | Spring Cloud Config Server | ConfigMap/Secret Kubernetes |
|---|---|---|
| Riwayat/audit | Bawaan dari Git | Perlu GitOps (manifest di Git) |
| Platform | Di mana saja (VM, Kubernetes) | Hanya Kubernetes |
| Komponen ekstra | Config Server harus dioperasikan | Tidak ada |
| Refresh | /actuator/refresh, Bus | Mount file ter-update; env var perlu restart |
Versioning dan audit
Konfigurasi adalah kode yang bisa menjatuhkan production, jadi perlakukan seperti kode: perubahan lewat pull request, di-review, dan di-tag. Label Git memungkinkan service mengunci versi konfigurasi tertentu (spring.cloud.config.label). Saat insiden, git log dan git revert adalah alat rollback tercepat.
Contoh di dunia backend
Platform e-commerce memiliki order-service, payment-service, dan inventory-service. Nilai bersama (alamat Kafka, format log) ditaruh di application.yml level atas; batas pembayaran khusus payment-service; API key gateway pembayaran dienkripsi.
yaml
# config-repo/application.yml — dipakai semua service
spring:
kafka:
bootstrap-servers: kafka-0.kafka:9092,kafka-1.kafka:9092
logging:
level:
root: INFOyaml
# config-repo/payment-service/payment-service-prod.yml
payment:
max-amount: 50000000
gateway-timeout: 3s
gateway:
api-key: "{cipher}AQA9x2kd...ringkas..."java
// Potongan — payment-service membaca batas yang bisa di-refresh
@Service
public class PaymentLimitChecker {
private final PaymentProperties properties;
public PaymentLimitChecker(PaymentProperties properties) {
this.properties = properties;
}
public void check(BigDecimal amount) {
if (amount.compareTo(properties.maxAmount()) > 0) {
throw new IllegalArgumentException(
"Nominal melebihi batas " + properties.maxAmount());
}
}
}PaymentProperties didaftarkan dengan @ConfigurationPropertiesScan di class aplikasi. Ketika tim risiko menurunkan max-amount saat ada indikasi fraud, perubahan cukup berupa satu pull request ke repo konfigurasi, lalu refresh — tanpa build image baru. Riwayat Git mencatat siapa yang mengubah batas itu dan kapan.
Pertanyaan interview
1. Apa bedanya configserver: dan optional:configserver: di spring.config.import?
Tanpa optional:, import bersifat wajib: bila Config Server tidak bisa dihubungi, aplikasi gagal start (fail-fast). Dengan optional:, aplikasi tetap start memakai konfigurasi lokal. Di production fail-fast lebih aman karena mencegah service berjalan dengan konfigurasi yang salah tanpa disadari.
2. Bagaimana konfigurasi bisa berubah tanpa restart, dan apa batasannya?
Panggil /actuator/refresh: Environment diperbarui, bean @ConfigurationProperties di-rebind, dan bean @RefreshScope dibuat ulang. Untuk banyak instance gunakan Spring Cloud Bus. Batasannya: nilai seperti URL database atau ukuran pool tidak aman diubah di tengah jalan, dan bean biasa yang menyuntik @Value tidak ikut berubah.
3. Di mana kamu menyimpan secret di arsitektur microservices?
Bukan di repo kode atau file konfigurasi polos. Pilihannya: nilai {cipher} di Config Server, HashiCorp Vault, atau Kubernetes Secret/secret manager cloud dengan encryption at rest dan RBAC ketat. Idealnya secret punya rotasi dan audit akses, serta tidak pernah tercetak di log.
Jebakan umum
- Memakai
optional:configserver:di production, sehingga service diam-diam jalan dengan konfigurasi lokal saat Config Server bermasalah. - Mengira bean dengan
@Valueikut berubah setelah/actuator/refreshpadahal bean itu tidak@RefreshScope. - Menganggap Kubernetes Secret terenkripsi, padahal nilainya hanya base64.
- Menjalankan Config Server satu replika — ia menjadi single point of failure untuk startup semua service.
- Mengubah konfigurasi production langsung tanpa review, sehingga satu typo timeout menjatuhkan semua service.
- Mengekspos
/actuator/refreshke publik tanpa autentikasi.
Ringkasan
- Konfigurasi terpusat menghilangkan duplikasi, memisahkan konfigurasi dari image, dan memberi riwayat perubahan.
- Spring Cloud Config Server menyajikan konfigurasi dari Git; client membacanya lewat
spring.config.import=configserver:. - Import tanpa
optional:membuat service fail-fast saat Config Server tidak tersedia — biasanya pilihan tepat di production. /actuator/refreshme-rebind@ConfigurationPropertiesdan bean@RefreshScope; Spring Cloud Bus menyiarkan refresh ke banyak instance.- Secret dipisah dari konfigurasi biasa:
{cipher}, Vault, atau Kubernetes Secret dengan encryption at rest dan RBAC. - Di Kubernetes, ConfigMap/Secret adalah alternatif tanpa komponen tambahan; kelola manifest-nya di Git agar tetap ter-audit.