Pada artikel sebelumnya, kita telah membahas tentang ConfigMap yang digunakan untuk menyimpan konfigurasi aplikasi. Namun, bagaimana jika kita perlu menyimpan data sensitif seperti password, token, atau kunci API? Menyimpan data sensitif di ConfigMap bukanlah praktik yang baik karena ConfigMap menyimpan data dalam bentuk plaintext. Di sinilah Secret berperan.
Apa itu Secret?
Secret adalah objek Kubernetes yang digunakan untuk menyimpan dan mengelola informasi sensitif, seperti password, token OAuth, kunci SSH, atau kunci API. Secret mirip dengan ConfigMap, tetapi dirancang khusus untuk menyimpan data rahasia.
Meskipun Secret dan ConfigMap memiliki fungsi yang mirip, ada beberapa perbedaan penting:
- Tujuan: ConfigMap untuk konfigurasi non-sensitif, Secret untuk data sensitif.
- Penyimpanan: Secret disimpan dalam tmpfs (memori) pada node, bukan di disk seperti ConfigMap.
- Encoding: Data dalam Secret di-encode dengan base64, sementara ConfigMap menyimpan data dalam plaintext.
- Ukuran: Secret memiliki batasan ukuran 1MB.
Perlu diingat bahwa meskipun Secret menggunakan encoding base64, ini bukan merupakan enkripsi yang aman. Base64 hanya encoding, bukan enkripsi, dan dapat dengan mudah di-decode. Keamanan Secret bergantung pada fitur tambahan seperti enkripsi data saat disimpan (encryption at rest) yang perlu dikonfigurasi secara terpisah.
Jenis-jenis Secret
Kubernetes menyediakan beberapa jenis Secret yang dapat digunakan sesuai kebutuhan:
1. Opaque (generic)
Jenis Secret default dan paling umum digunakan. Opaque Secret menyimpan data arbitrer dalam format key-value.
2. docker-registry
Secret yang digunakan untuk menyimpan kredensial Docker registry, memungkinkan Pod untuk menarik image dari registry privat.
3. tls
Secret yang menyimpan sertifikat TLS dan kunci privat, biasanya digunakan untuk mengamankan Ingress.
4. bootstrap token
Secret yang digunakan selama proses bootstrap klaster.
5. service account token
Secret yang berisi token untuk autentikasi service account.
Cara Membuat Secret
Ada beberapa cara untuk membuat Secret di Kubernetes:
1. Dari Nilai Literal
Kita dapat membuat Secret langsung dari command line menggunakan nilai literal:
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=s3cr3t
2. Dari File
Jika kita memiliki file yang berisi data sensitif, kita dapat membuat Secret dari file tersebut:
echo -n 'admin' > ./username.txt
echo -n 's3cr3t' > ./password.txt
kubectl create secret generic db-credentials \
--from-file=username=./username.txt \
--from-file=password=./password.txt
3. Dari Definisi YAML
Kita juga dapat membuat Secret menggunakan file YAML. Namun, perlu diingat bahwa nilai dalam Secret harus di-encode dengan base64:
echo -n 'admin' | base64
# Output: YWRtaW4=
echo -n 's3cr3t' | base64
# Output: czNjcjN0
Kemudian, kita dapat membuat file YAML seperti berikut:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4=
password: czNjcjN0
Simpan file di atas sebagai db-secret.yaml dan terapkan ke klaster:
kubectl apply -f db-secret.yaml
Cara Menggunakan Secret
Ada tiga cara utama untuk menggunakan Secret dalam Pod:
1. Sebagai Environment Variable
Kita dapat menggunakan Secret sebagai environment variable dalam container:
apiVersion: v1
kind: Pod
metadata:
name: backend
spec:
containers:
- name: backend
image: myapp:latest
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
2. Sebagai Argumen Command Line
Kita juga dapat menggunakan Secret sebagai argumen command line:
apiVersion: v1
kind: Pod
metadata:
name: backend
spec:
containers:
- name: backend
image: myapp:latest
command: ["./app"]
args: ["--username=$(DB_USERNAME)", "--password=$(DB_PASSWORD)"]
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
3. Sebagai Volume yang Di-mount
Cara ketiga adalah dengan meng-mount Secret sebagai volume:
apiVersion: v1
kind: Pod
metadata:
name: backend
spec:
containers:
- name: backend
image: myapp:latest
volumeMounts:
- name: credentials
mountPath: "/etc/credentials"
readOnly: true
volumes:
- name: credentials
secret:
secretName: db-credentials
Dengan konfigurasi di atas, setiap key dalam Secret akan menjadi file di dalam direktori /etc/credentials. Misalnya, nilai dari username akan tersedia di /etc/credentials/username.
Contoh Lengkap: Aplikasi Database dengan Secret
Mari kita lihat contoh lengkap aplikasi yang menggunakan Secret untuk menyimpan kredensial database:
- Pertama, kita buat Secret untuk kredensial database:
apiVersion: v1
kind: Secret
metadata:
name: mysql-credentials
type: Opaque
data:
username: YWRtaW4= # admin
password: czNjcjN0 # s3cr3t
database: bXlhcHA= # myapp
- Kemudian, kita buat Deployment untuk database MySQL:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-credentials
key: password
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: mysql-credentials
key: database
- Terakhir, kita buat Deployment untuk aplikasi backend yang terhubung ke database:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: myapp:latest
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: "mysql"
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: mysql-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-credentials
key: password
- name: DB_NAME
valueFrom:
secretKeyRef:
name: mysql-credentials
key: database
- Simpan ketiga file YAML di atas dan terapkan ke klaster:
kubectl apply -f mysql-secret.yaml
kubectl apply -f mysql-deployment.yaml
kubectl apply -f backend-deployment.yaml
Memperbarui Secret
Memperbarui Secret mirip dengan memperbarui objek Kubernetes lainnya. Kita dapat menggunakan perintah kubectl edit, kubectl patch, atau membuat ulang Secret dengan kubectl apply.
Namun, perlu diingat bahwa memperbarui Secret tidak secara otomatis memperbarui nilai yang digunakan oleh Pod yang sudah berjalan. Untuk Pod yang menggunakan Secret sebagai environment variable, Pod perlu di-restart agar perubahan diterapkan. Untuk Pod yang menggunakan Secret sebagai volume, perubahan akan diterapkan secara otomatis setelah beberapa saat (tergantung pada sinkronisasi kubelet).
Pertimbangan Keamanan
Meskipun Secret dirancang untuk menyimpan data sensitif, ada beberapa pertimbangan keamanan yang perlu diperhatikan:
-
Base64 bukan enkripsi: Data dalam Secret hanya di-encode dengan base64, bukan dienkripsi. Siapa pun yang memiliki akses ke Secret dapat dengan mudah men-decode nilai tersebut.
-
Enkripsi data saat disimpan (encryption at rest): Secara default, Secret disimpan dalam etcd tanpa enkripsi. Untuk meningkatkan keamanan, aktifkan enkripsi data saat disimpan.
-
RBAC untuk akses Secret: Gunakan Role-Based Access Control (RBAC) untuk membatasi siapa yang dapat mengakses Secret.
-
Pod Security Policies: Gunakan Pod Security Policies untuk membatasi Pod mana yang dapat meng-mount Secret tertentu.
Best Practices
Berikut adalah beberapa praktik terbaik saat bekerja dengan Secret:
-
Jangan menyimpan Secret dalam repositori Git: Hindari menyimpan Secret dalam repositori Git, bahkan jika repositori tersebut privat.
-
Gunakan Secret untuk data sensitif saja: Gunakan ConfigMap untuk konfigurasi non-sensitif dan Secret hanya untuk data sensitif.
-
Batasi akses ke Secret: Gunakan RBAC untuk membatasi siapa yang dapat membaca atau menulis Secret.
-
Aktifkan enkripsi data saat disimpan: Konfigurasikan Kubernetes untuk mengenkripsi Secret saat disimpan di etcd.
-
Rotasi Secret secara berkala: Perbarui Secret secara berkala untuk meningkatkan keamanan.
-
Gunakan solusi manajemen secret eksternal: Untuk kebutuhan keamanan yang lebih tinggi, pertimbangkan untuk menggunakan solusi manajemen secret eksternal seperti HashiCorp Vault atau AWS Secrets Manager.
Kesimpulan
Secret adalah komponen penting dalam Kubernetes yang memungkinkan kita menyimpan dan mengelola data sensitif dengan aman. Meskipun Secret memiliki beberapa keterbatasan keamanan, dengan mengikuti praktik terbaik, kita dapat menggunakannya untuk menyimpan kredensial dan data sensitif lainnya dengan cukup aman.
Pada artikel berikutnya, kita akan membahas tentang DaemonSet - kontroler Pod yang memastikan setiap node dalam klaster menjalankan salinan Pod tertentu. Jangan lupa untuk mencoba contoh-contoh di atas di klaster Minikube Anda!
Cappy Hoding! ๐๐พ