Karena kunci dan rahasia Anda seharusnya hanya itu—rahasia

Halo dan selamat datang 👋👋 Kami melanjutkan perjalanan Singkatnya Kubernetes. Di salah satu blog sebelumnya, kita melihat cara mengonfigurasi aplikasi Kubernetes menggunakan ConfigMapobject. Dalam postingan ini, kita akan menjelajahi Kubernetes Secretsdan bagaimana mereka dapat digunakan untuk menyimpan data konfigurasi sensitif yang perlu ditangani dengan aman (misalnya, kredensial database, kunci API, dll.).

Seperti biasa, ini akan didasarkan pada contoh, dan Anda akan belajar:

  • cara membuat Secrets (CLI, yaml dll) dan
  • berbagai cara menggunakannya di aplikasi Anda (variabel env, volume, dll.)

Kode (dan YAML) tersedia di GitHub.

Bagian ini telah dibagi menjadi dua bagian logis: cara membuat Secrets dan teknik menggunakan Secrets dalam aplikasi Anda.

Prasyarat

Untuk melihat contoh dalam postingan ini, yang Anda perlukan hanyalah cluster Minikube dan alat kubectl CLI untuk mengakses cluster.

Instal Minikube sebagai cluster Kubernetes node tunggal di mesin virtual di komputer Anda. Di Mac, Anda cukup:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 \
  && chmod +x minikube
sudo mv minikube /usr/local/bin

Instal kubectl untuk berinteraksi dengan cluster Minikube. Di Mac, Anda dapat:

curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl

Menciptakan Rahasia

Mari kita lihat teknik yang dapat digunakan untuk membuat Secret.

Gunakan bagian data

Dimungkinkan untuk membuat Secret bersama dengan data konfigurasi yang disimpan sebagai pasangan nilai kunci di bagian data definisi.

apiVersion: v1
kind: Secret
metadata:
  name: service-apikey
data:
  apikey: Zm9vYmFy

Secret berisi data nilai kunci yang mewakili info sensitif, dengan apikey sebagai kunci dan nilainya adalah string yang dikodekan base64.

Untuk membuat Secret ini di Kubernetes:

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/secrets/secret-data.yaml

Untuk mempermudah, file YAML direferensikan langsung dari repo GitHub, tetapi Anda juga dapat mengunduh file tersebut ke mesin lokal Anda dan menggunakannya dengan cara yang sama.

Untuk mengonfirmasi bahwa Secret telah dibuat:

kubectl get secret/service-apikey -o yaml

Anda akan mendapatkan respons YAML yang mirip dengan:

apiVersion: v1
data:
  apikey: Zm9vYmFy
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"apikey":"Zm9vYmFy"},"kind":"Secret","metadata":{"annotations":{},"name":"service-apikey","namespace":"default"}}
  creationTimestamp: "2019-12-17T11:11:27Z"
  name: service-apikey
  namespace: default
  resourceVersion: "113009"
  selfLink: /api/v1/namespaces/default/secrets/service-apikey
  uid: 671b547c-3316-4916-b6dc-be2b551b974e
type: Opaque

Mengambil detail Secret menggunakan kubectl get tidak mengungkapkan isinya.

Perhatikan bahwa apikey: Zm9vYmFy adalah apa yang kami sediakan di manifes YAML. Anda dapat memeriksa formulir teks biasa dengan mendekodekannya:

echo 'Zm9vYmFy' | base64 --decode
//foobar

Gunakan bagian stringData

Atribut data yang digunakan dalam contoh di atas digunakan untuk menyimpan informasi yang dikodekan base64. Jika Anda ingin menyimpan data teks biasa dengan aman, Anda dapat menggunakan bagian stringData. Berikut ini contohnya:

apiVersion: v1
kind: Secret
metadata:
  name: plaintext-secret
stringData:
  foo: bar
  mac: cheese

Nilai untuk foo dan mac diteruskan sebagai teks biasa. Buat Secret ini dan konfirmasikan:

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/secrets/secret-plaintext.yaml
kubectl get secret/plaintext-secret -o yaml

Berikut adalah bagian data dari respons YAML. Data aktual disimpan dalam format berkode base64.

data:
  foo: YmFy

Jika Anda memecahkan kode data, Anda dapat mengonfirmasi bahwa data tersebut cocok dengan masukan teks biasa asli (bar) yang kami sediakan

echo 'YmFy' | base64 --decode
//bar

Perhatikan bahwa bagiandata tidak menerima atribut teks biasa. Mencoba melakukannya akan menghasilkan kesalahan sepertiini:illegal base64 data at input byte 8

Isi file

Anda juga dapat memberikan konten seluruh file sebagai masukan ke bagian stringData. Berikut tampilannya:

apiVersion: v1
kind: Secret
metadata:
  name: secret-in-a-file
stringData:
  app-config.yaml: |-
    hello: world
    john: doe

Buat ini Secret

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/secrets/secret-file.yaml

Secret yang dihasilkan ini akan berisi kunci bernama app-config.yaml dan isinya (nilai) akan menjadi base64 pengkodean data yang disediakan.

Seperti biasa, Anda mengonfirmasi hal ini di Kubernetes dan juga mendekode isinya.

kubectl get secret/secret-in-a-file -o yaml
echo '<"data" content in yaml response> | base64 --decode

Catatan: Saat Anda menggunakan teknik ini, aplikasi Anda bertanggung jawab untuk menguraikan data yang mewakili konfigurasi Secret. Dalam hal ini, pasangan kunci-nilai yang dipisahkan baris baru, namun bisa juga yang lainnya.

Menggunakan kubectl

Anda dapat menggunakan perintah kubectl create secret untuk membuat objek Secret

Menggunakan --from-literal

Anda dapat menggunakan data teks biasa untuk membuat Secret menggunakan CLI (ini akan disimpan dalam format berkode base64 di Kubernetes):

kubectl create secret generic redis-credentials --from-literal=user=poweruser --from-literal=password='f0ob@r'

Menggunakan --from-file

kubectl create secret generic topsecret --from-file=api_keys.txt

Ini akan membuat rahasia (topsecret) dengan

  • kunci dengan nama file yang sama yaitu api_keys.txt dalam kasus ini
  • dan, nilai sebagai isi file

Dari file dalam direktori

Anda cukup menunjuk ke direktori dan semua file di dalamnya akan digunakan untuk membuat file Secret.

kubectl create secret generic topsecrets --from-file=/home/credentials/

Anda akan berakhir dengan

  • beberapa kunci yang akan sama dengan nama file individual
  • nilainya akan menjadi isi file masing-masing

Menggunakan Rahasia

Agar Rahasia dapat berguna, kita perlu memastikan bahwa Rahasia tersedia untuk aplikasi kita (yaitu Pod). Mari kita jelajahi cara-cara yang dapat kita lakukan untuk melakukan hal ini

Variabel lingkungan

Anda dapat menggunakan data Secret sebagai variabel lingkungan di Pod (seperti ConfigMap). Berikut ini contohnya:

apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
    - name: nginx
      image: nginx
      env:
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: service-apikey
              key: apikey

Kami menggunakan kunci apikey dari Secret service-apikey dan memastikan nilainya tersedia sebagai variabel lingkungan API_KEY di dalam Pod.

Buat Pod (dengan asumsi Anda telah membuat Secret dari contoh sebelumnya) dan konfirmasi.

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/secrets/pod-secret-env.yaml
kubectl get pods -w

Tunggu hingga Pod bertransisi ke status Running. Kemudian, konfirmasikan bahwa variabel lingkungan telah dimasukkan ke dalam Pod.

kubectl exec pod1 -- env | grep API_KEY

Anda seharusnya mendapatkan tanggapan ini — API_KEY=foobar.

Daripada merujuk ke entri individual di Secret, Anda dapat menggunakan envFrom untuk dengan mudah menggunakan semua entri sebagai variabel lingkungan di Pod. Inilah cara Anda menggunakannya:

apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  containers:
    - name: nginx
      image: nginx
      envFrom:
        - secretRef:
            name: plaintext-secret

Kami mengacu pada plaintext-secret Secretmenggunakan envFrom.secretRef. Untuk membuat Pod ini:

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/secrets/pod-secret-envFrom.yaml
kubectl get pods -w

Tunggu hingga Pod bertransisi ke status Running lalu konfirmasikan keberadaan variabel lingkungan.

kubectl exec pod2 -- env | grep foo
//foo=bar
kubectl exec pod2 -- env | grep mac
//mac=cheese

Hal ini mengonfirmasi bahwa foo dan mac telah ditambahkan sebagai variabel lingkungan ke dalam the Pod bersama dengan nilai yang didekodekan yaitu masing-masing bar dan cheese

Volume

Anda dapat memasang Secrets sebagai Volume dalam Pod. Misalnya:

apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - name: apikey-config-volume
          mountPath: /secret
          readOnly: true
  volumes:
    - name: apikey-config-volume
      secret:
        secretName: service-apikey

Volume apikey-config-volume mengacu pada service-apikey Secret. Untuk membuat Pod ini:

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/secrets/pod-secret-volume.yaml
kubectl get pods -w

Tunggu hingga Pod bertransisi ke status Running. Kemudian jalankan perintah berikut:

kubectl exec pod3 -- cat /secret/apikey
//foobar

Ini mengonfirmasi bahwa kunci apikey secara rahasia service-apikey telah dipasang sebagai file (dengan nama apikey) di direktori /secret (khusus di Pod). Isi file tidak lain adalah nilai rahasia yaitu foobar dalam kasus ini.

Menggunakan imagePullSecrets

Ada cara untuk menggunakan Secrets sehingga Pod aplikasi Anda dapat menggunakannya untuk mengautentikasi dan menarik image Docker dari registry Docker privat.

Sebenarnya ada tiga jenis Secrets:

  • generic - digunakan untuk menyimpan pasangan nilai kunci, seperti yang telah kita lihat pada contoh sejauh ini
  • tls - menyimpan info pasangan kunci publik.pribadi sebagai Secrets
  • docker-registry - kredensial untuk mengautentikasi ke registri Docker.

Cara penggunaan teknik ini sangat sederhana:

  • Gunakan tipe docker-registry Secret untuk menyimpan kredensial registri Docker pribadi di Kubernetes.
  • Dan kemudian, imagePullSecrets (dalam sebuah Pod) untuk mereferensikan Secret yang berisi kredensial registri Docker.

Sebuah contoh selalu membantu:

apiVersion: v1
kind: Pod
metadata:
  name: pod4
spec:
  containers:
    - name: privateapp
      image: abhirockzz/test-private-repo:latest
      command: ["/bin/sh"]
      args: ["-c", "while true; do date; sleep 5;done"]
  imagePullSecrets:
    - name: docker-repo-secret

Lihat bagaimana imagePullSecrets.name mengacu pada Secret yang disebut docker-repo-secret. Mari kita ciptakan.

Namun sebelum itu, pastikan Anda memiliki registri Docker pribadi. Saya menggunakan DockerHub, tetapi Anda dapat memilih yang lain.

Mulailah dengan membuat Secret (dengan nama docker-repo-secret) yang berisi kredensial Docker Anda menggunakan kubectl create secret docker-registrycommand.

kubectl create secret docker-registry docker-repo-secret --docker-server=DOCKER_REG_SERVER --docker-username=DOCKER_REG_USERNAME --docker-password=DOCKER_REG_PASSWORD --docker-email=DOCKER_REG_EMAIL

Untuk Hub Docker:

kubectl create secret docker-registry docker-repo-secret --docker-server=https://index.docker.io/v1/ --docker-username=foobarbaz --docker-password=t0ps3cr3t [email protected]
kubectl get secret/docker-repo-secret -o yaml

https://index.docker.io/v1/ adalah server registri Docker Hub

Untuk mengujinya, kita akan menggunakan gambar busybox dan tagit

docker pull busybox
docker tag busybox [DOCKER_REG]/[DOCKER_PRIVATE_REPO]:[IMAGE_TAG]
e.g. 
docker tag busybox abhirockzz/test-private-repo:latest

… dan push itu

docker push [DOCKER_REG]/[DOCKER_PRIVATE_REPO]:[IMAGE_TAG]
e.g. 
docker push abhirockzz/test-private-repo:latest

Setelah repo pribadi siap, Anda dapat membuat Podyang akan menarik gambar dari repo pribadi menggunakan kredensial registri yang diberikan melalui Secret

kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/secrets/pod-secret-docker.yaml
kubectl get pods -w

Tunggu hingga Pod berpindah ke status Running.

Jika Anda melihat kesalahan ErrImagePull, ini menunjukkan bahwa mungkin ada masalah dalam mengautentikasi registri Docker. Untuk mendapatkan detailnya, gunakan: kubectl describe pod/pod4

Untuk mengonfirmasi bahwa pod berfungsi dengan baik: kubectl logs -f pod4

Karena gambar busybox tidak melakukan apa pun dengan sendirinya, kami mengeksekusi: while true; do date; sleep 5;done (seperti yang disediakan dalam spesifikasi Pod). Hasilnya, Anda akan melihat log (dicetak setiap 5 detik).

Tue Dec 17 14:17:34 UTC 2019
Tue Dec 17 14:17:39 UTC 2019
Tue Dec 17 14:17:44 UTC 2019
Tue Dec 17 14:18:49 UTC 2019

Semuanya bagus! Artinya, Pod dapat menarik image Anda dari repo Docker pribadi menggunakan kredensial Docker yang dimasukkan ke Pod menggunakan imagePullSecrets, yang mereferensikan Secret

Senang mendengarnya

Berikut adalah daftar (tidak lengkap) hal-hal yang harus Anda ingat saat menggunakan Secrets:

  • Secret harus dibuat sebelum Pod mana pun yang ingin menggunakannya.
  • Secrets berlaku dalam namespace yaitu hanya dapat digunakan oleh Pods di namespace yang sama
  • Pod tidak akan dimulai jika ada referensi ke kunci yang tidak ada di Secret (menggunakan secretKeyRef)
  • 1MiB adalah batas ukuran untuk individu Secrets

Sekian untuk edisi seri Kubernetes in a Nutshell kali ini. Nantikan selengkapnya!

Jika Anda tertarik mempelajari Kubernetes dan Container menggunakan “Azure”, cukup “buat akun gratis” dan mulai. Titik awal yang baik adalah dengan menggunakan mulai cepat, tutorial, dan contoh kode dalam dokumentasi untuk membiasakan diri Anda dengan layanan ini. Saya juga sangat merekomendasikan untuk memeriksa Jalur Pembelajaran Kubernetes 50 hari. Pengguna tingkat lanjut mungkin ingin merujuk ke “praktik terbaik Kubernetes” atau menonton beberapa “video” untuk demo, fitur unggulan, dan sesi teknis.

Saya sangat berharap Anda menikmati dan mempelajari sesuatu dari artikel ini. 🙌