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:

  1. Tujuan: ConfigMap untuk konfigurasi non-sensitif, Secret untuk data sensitif.
  2. Penyimpanan: Secret disimpan dalam tmpfs (memori) pada node, bukan di disk seperti ConfigMap.
  3. Encoding: Data dalam Secret di-encode dengan base64, sementara ConfigMap menyimpan data dalam plaintext.
  4. 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:

  1. 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
  1. 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
  1. 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
  1. 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:

  1. 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.

  2. Enkripsi data saat disimpan (encryption at rest): Secara default, Secret disimpan dalam etcd tanpa enkripsi. Untuk meningkatkan keamanan, aktifkan enkripsi data saat disimpan.

  3. RBAC untuk akses Secret: Gunakan Role-Based Access Control (RBAC) untuk membatasi siapa yang dapat mengakses Secret.

  4. 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:

  1. Jangan menyimpan Secret dalam repositori Git: Hindari menyimpan Secret dalam repositori Git, bahkan jika repositori tersebut privat.

  2. Gunakan Secret untuk data sensitif saja: Gunakan ConfigMap untuk konfigurasi non-sensitif dan Secret hanya untuk data sensitif.

  3. Batasi akses ke Secret: Gunakan RBAC untuk membatasi siapa yang dapat membaca atau menulis Secret.

  4. Aktifkan enkripsi data saat disimpan: Konfigurasikan Kubernetes untuk mengenkripsi Secret saat disimpan di etcd.

  5. Rotasi Secret secara berkala: Perbarui Secret secara berkala untuk meningkatkan keamanan.

  6. 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! ๐Ÿ––๐Ÿพ