เพราะกุญแจและความลับของคุณควรเป็นความลับนั้น

สวัสดีและยินดีต้อนรับ หยาบคาย เรากำลังเดินทางต่อใน "Kubernetes in a Nutshell" ต่อไป ในบล็อกก่อนหน้านี้ เราเห็นวิธี "กำหนดค่าแอป Kubernetes" โดยใช้ ConfigMapobject ในโพสต์นี้ เราจะสำรวจ Kubernetes Secretsและวิธีที่สามารถใช้เพื่อจัดเก็บข้อมูลการกำหนดค่าที่ละเอียดอ่อนซึ่งจำเป็นต้องได้รับการจัดการอย่างปลอดภัย (เช่น ข้อมูลรับรองฐานข้อมูล คีย์ API ฯลฯ)

ตามปกติ สิ่งนี้จะเป็นการขับเคลื่อนด้วยตัวอย่าง และคุณจะได้เรียนรู้:

  • วิธีสร้าง Secrets (CLI, yaml ฯลฯ) และ
  • วิธีการใช้งานต่างๆ ในแอปของคุณ (ตัวแปร env, วอลุ่ม ฯลฯ)

รหัส (และ YAML) มีให้ใช้งาน บน GitHub

งานชิ้นนี้แบ่งออกเป็นสองส่วนเชิงตรรกะ: วิธีสร้าง Secrets และเทคนิคในการใช้ Secrets ในแอปพลิเคชันของคุณ

ข้อกำหนดเบื้องต้น

หากต้องการดูตัวอย่างในโพสต์นี้ สิ่งที่คุณต้องมีคือคลัสเตอร์ Minikube และเครื่องมือ kubectl CLI เพื่อเข้าถึงคลัสเตอร์

ติดตั้ง "Minikube" เป็นคลัสเตอร์ Kubernetes โหนดเดียวในเครื่องเสมือนบนคอมพิวเตอร์ของคุณ บน Mac คุณสามารถ:

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

ติดตั้ง kubectl เพื่อโต้ตอบกับคลัสเตอร์ Minikube บน Mac คุณสามารถ:

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

การสร้างความลับ

มาดูเทคนิคที่คุณสามารถสร้าง Secret กัน

ใช้ส่วน data

คุณสามารถสร้าง Secret พร้อมกับข้อมูลการกำหนดค่าที่จัดเก็บเป็นคู่คีย์-ค่าในส่วน data ของคำจำกัดความได้

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

Secret ประกอบด้วยข้อมูลคีย์-ค่าที่แสดงถึงข้อมูลที่ละเอียดอ่อน โดยที่ apikey เป็นคีย์ และค่าเป็นสตริงที่เข้ารหัส base64

หากต้องการสร้าง Secret นี้ใน Kubernetes:

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

เพื่อให้ทุกอย่างง่ายขึ้น ไฟล์ YAML จะถูกอ้างอิงโดยตรงจาก GitHub repo แต่คุณยังสามารถดาวน์โหลดไฟล์ลงในเครื่องของคุณและใช้งานในลักษณะเดียวกันได้

เพื่อยืนยันว่า Secret ถูกสร้างขึ้น:

kubectl get secret/service-apikey -o yaml

คุณจะได้รับคำตอบ YAML คล้ายกับ:

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

การดึงรายละเอียด Secret โดยใช้ kubectl get จะไม่เปิดเผยเนื้อหา

โปรดสังเกตว่า apikey: Zm9vYmFy คือสิ่งที่เราระบุไว้ในรายการ YAML คุณสามารถตรวจสอบรูปแบบข้อความธรรมดาได้โดยการถอดรหัส:

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

ใช้ส่วน stringData

คุณลักษณะ data ที่ใช้ในตัวอย่างข้างต้นใช้เพื่อบันทึกข้อมูลที่เข้ารหัส base64 หากคุณต้องการจัดเก็บข้อมูลข้อความธรรมดาอย่างปลอดภัย คุณสามารถใช้ส่วน stringData นี่คือตัวอย่าง:

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

ค่าสำหรับ foo และ mac ถูกส่งผ่านเป็นข้อความธรรมดา สร้าง Secret นี้และยืนยัน:

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

นี่คือส่วน data ของการตอบกลับ YAML ข้อมูลจริงจะถูกจัดเก็บในรูปแบบที่เข้ารหัส base64

data:
  foo: YmFy

หากคุณถอดรหัสข้อมูล คุณสามารถยืนยันได้ว่าข้อมูลตรงกับอินพุตข้อความธรรมดาต้นฉบับ (bar) ที่เราให้ไว้

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

โปรดทราบว่าส่วนdata ไม่ยอมรับแอตทริบิวต์ข้อความธรรมดา การพยายามทำเช่นนั้นจะส่งผลให้เกิดข้อผิดพลาดคล้ายกับสิ่งนี้:illegal base64 data at input byte 8

เนื้อหาไฟล์

คุณสามารถระบุเนื้อหาของไฟล์ทั้งหมดเป็นอินพุตในส่วน stringData ได้เช่นกัน นี่คือสิ่งที่อาจมีลักษณะเช่นนี้:

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

สร้างสิ่งนี้ Secret

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

ผลลัพธ์ Secret นี้จะมีคีย์ชื่อ app-config.yaml และเนื้อหา (ค่า) ของคีย์นั้นจะเป็นการเข้ารหัส base64 ของข้อมูลที่ให้ไว้

ตามปกติ คุณจะยืนยันสิ่งนี้ใน Kubernetes รวมถึงถอดรหัสเนื้อหาด้วย

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

หมายเหตุ: เมื่อคุณใช้เทคนิคนี้ แอปพลิเคชันของคุณมีหน้าที่แยกวิเคราะห์ข้อมูลที่แสดงถึงการกำหนดค่า Secret ในกรณีนี้ เป็นคู่คีย์-ค่าที่คั่นด้วยการขึ้นบรรทัดใหม่ แต่อาจเป็นอย่างอื่นก็ได้

ใช้ kubectl

คุณสามารถใช้คำสั่ง kubectl create secret เพื่อสร้างวัตถุ Secret

ใช้ --from-literal

คุณสามารถใช้ข้อมูลข้อความธรรมดาเพื่อสร้าง Secret โดยใช้ CLI (ซึ่งจะถูกจัดเก็บในรูปแบบที่เข้ารหัส base64 ใน Kubernetes):

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

การใช้ --from-file

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

ซึ่งจะสร้างความลับ (topsecret) ด้วย

  • คีย์ที่มีชื่อเดียวกันกับไฟล์ เช่น api_keys.txt ในกรณีนี้
  • และค่าเป็นเนื้อหาของไฟล์

จากไฟล์ในไดเร็กทอรี

คุณสามารถชี้ไปที่ไดเร็กทอรีและไฟล์ทั้งหมดภายในจะถูกนำมาใช้เพื่อสร้าง Secret

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

คุณจะจบลงด้วยการ

  • หลายคีย์ซึ่งจะเหมือนกันกับชื่อไฟล์แต่ละไฟล์
  • ค่าจะเป็นเนื้อหาของไฟล์ที่เกี่ยวข้อง

การใช้ความลับ

เพื่อให้ข้อมูลลับมีประโยชน์ เราต้องแน่ใจว่าข้อมูลเหล่านั้นพร้อมใช้งานในแอปพลิเคชันของเรา (เช่น พ็อด) เรามาสำรวจวิธีที่เราสามารถทำได้กันดีกว่า

ตัวแปรสภาพแวดล้อม

คุณสามารถใช้ข้อมูล Secret เป็นตัวแปรสภาพแวดล้อมใน Pod (เช่นเดียวกับ ConfigMap) นี่คือตัวอย่าง:

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

เราใช้คีย์ apikey จาก Secret service-apikey และตรวจสอบให้แน่ใจว่าค่าของคีย์นั้นพร้อมใช้งานเป็นตัวแปรสภาพแวดล้อม API_KEY ภายใน Pod

สร้าง Pod (สมมติว่าคุณมี Secret ที่สร้างจากตัวอย่างก่อนหน้านี้) และยืนยัน

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

รอให้ Pod เปลี่ยนเป็นสถานะ Running จากนั้นยืนยันว่าได้แทรกตัวแปรสภาพแวดล้อมลงใน Pod แล้ว

kubectl exec pod1 -- env | grep API_KEY

คุณควรได้รับการตอบกลับนี้ — API_KEY=foobar

แทนที่จะอ้างอิงถึงแต่ละรายการใน Secret คุณสามารถใช้ envFrom เพื่อใช้รายการทั้งหมดเป็นตัวแปรสภาพแวดล้อมใน Pod ได้อย่างสะดวก นี่คือวิธีที่คุณอาจใช้สิ่งนี้:

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

เรากำลังหมายถึง plaintext-secret Secretusing envFrom.secretRef หากต้องการสร้าง Pod นี้:

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

รอให้ Pod เปลี่ยนเป็นสถานะ Running จากนั้นยืนยันการมีอยู่ของตัวแปรสภาพแวดล้อม

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

นี่เป็นการยืนยันว่าทั้ง foo และ mac ถูกเพิ่มเป็นตัวแปรสภาพแวดล้อมใน the Pod พร้อมกับค่าที่ถอดรหัสแล้ว เช่น bar และ cheese ตามลำดับ

ปริมาณ

คุณสามารถต่อเชื่อม Secrets เป็น Volume ภายใน Pod ได้ ตัวอย่างเช่น:

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

ปริมาณ apikey-config-volume หมายถึง service-apikey Secret หากต้องการสร้าง Pod นี้:

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

รอให้ Pod เปลี่ยนเป็นสถานะ Running จากนั้นดำเนินการคำสั่งต่อไปนี้:

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

นี่เป็นการยืนยันว่าคีย์ apikey ในความลับ service-apikey ถูกเมาท์เป็นไฟล์ (ชื่อ apikey) ในไดเร็กทอรี /secret (ตามที่ระบุใน Pod) เนื้อหาของไฟล์ไม่มีอะไรนอกจากค่าลับ เช่น foobar ในกรณีนี้

การใช้ imagePullSecrets

มีวิธีใช้ Secrets เพื่อให้แอปพลิเคชัน Pod ของคุณสามารถใช้เพื่อตรวจสอบสิทธิ์และดึงอิมเมจ Docker จากรีจิสทรี Docker ส่วนตัว

จริงๆ แล้ว Secrets มีสามประเภท:

  • generic - ใช้เพื่อจัดเก็บคู่คีย์-ค่า ดังที่เราได้เห็นในตัวอย่างแล้ว
  • tls - เก็บข้อมูลคู่คีย์ public.private เป็น Secrets
  • docker-registry - ข้อมูลรับรองสำหรับการรับรองความถูกต้องของรีจิสทรี Docker

วิธีการใช้เทคนิคนี้ง่ายมาก:

  • ใช้ประเภท docker-registry Secret เพื่อจัดเก็บข้อมูลรับรองรีจิสทรี Docker ส่วนตัวใน Kubernetes
  • จากนั้น imagePullSecrets (ในพ็อด) เพื่ออ้างอิง Secret ที่มีข้อมูลรับรองรีจิสทรีนักเทียบท่า

ตัวอย่างจะช่วยได้เสมอ:

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

ดูว่า imagePullSecrets.name อ้างถึง Secret ที่เรียกว่า docker-repo-secret อย่างไร มาสร้างมันกันเถอะ

แต่ก่อนหน้านั้น โปรดตรวจสอบให้แน่ใจว่าคุณมีรีจิสทรี Docker ส่วนตัว ฉันใช้ DockerHub แต่คุณสามารถเลือกอันอื่นได้

เริ่มต้นด้วยการสร้าง Secret (ด้วยชื่อ docker-repo-secret) ซึ่งมีข้อมูลประจำตัวนักเทียบท่าของคุณโดยใช้ 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

สำหรับนักเทียบท่าฮับ:

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/ คือเซิร์ฟเวอร์รีจิสทรี Docker Hub

เพื่อทดสอบสิ่งต่างๆ เราจะใช้รูปภาพ busybox และ tagit

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

… และ push มัน

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

เมื่อ repo ส่วนตัวพร้อมแล้ว คุณสามารถสร้าง Podซึ่งจะดึงอิมเมจจาก repo ส่วนตัวโดยใช้ข้อมูลรับรองรีจิสทรีที่มอบให้ผ่านทาง Secret

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

รอให้ Pod ย้ายไปที่สถานะ Running

หากคุณเห็นข้อผิดพลาด ErrImagePull แสดงว่าอาจมีปัญหาในการตรวจสอบสิทธิ์รีจิสทรี Docker หากต้องการดูรายละเอียด ให้ใช้: kubectl describe pod/pod4

เพื่อยืนยันว่าพ็อดทำงานได้ดี: kubectl logs -f pod4

เนื่องจากอิมเมจ busybox ไม่ได้ทำอะไรด้วยตัวเองจริงๆ เราจึงดำเนินการ: while true; do date; sleep 5;done (ตามที่ระบุไว้ในข้อมูลจำเพาะ Pod) ด้วยเหตุนี้ คุณควรเห็นบันทึก (พิมพ์ทุกๆ 5 วินาที)

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

ทั้งหมดดี! ความหมายก็คือ Pod สามารถดึงรูปภาพของคุณจาก repo Docker ส่วนตัวโดยใช้ข้อมูลรับรอง Docker ซึ่งถูกฉีดเข้าไปใน Pod โดยใช้ imagePullSecrets ซึ่งตัวมันเองอ้างอิง Secret

ดีแล้วที่รู้

ต่อไปนี้เป็นรายการ (โดยสังเขป) ที่คุณควรคำนึงถึงเมื่อใช้ Secrets:

  • จะต้องสร้าง Secret ก่อน Pod ใดๆ ที่ต้องการใช้
  • Secrets ใช้ได้ภายใน namespace กล่าวคือ สามารถใช้ได้โดย Pods ใน namespace เดียวกันเท่านั้น
  • Pod จะไม่เริ่มทำงานหากมีการอ้างอิงถึงคีย์ที่ไม่มีอยู่ใน Secret (โดยใช้ secretKeyRef)
  • 1MiB คือขีดจำกัดขนาดสำหรับบุคคล Secrets

เพียงเท่านี้สำหรับซีรีส์ Kubernetes in a Nutshell ฉบับนี้ คอยติดตามข้อมูลเพิ่มเติม!

หากคุณสนใจที่จะเรียนรู้ Kubernetes และคอนเทนเนอร์โดยใช้ "Azure" เพียง "สร้างบัญชีฟรี" แล้วเริ่มต้นได้เลย จุดเริ่มต้นที่ดีคือการใช้ “การเริ่มต้นอย่างรวดเร็ว บทช่วยสอน และตัวอย่างโค้ด” ในเอกสารประกอบเพื่อทำความคุ้นเคยกับบริการ ฉันขอแนะนำให้ลองดู "เส้นทางการเรียนรู้ Kubernetes" 50 วัน ผู้ใช้ขั้นสูงอาจต้องการดู "แนวทางปฏิบัติที่ดีที่สุดของ Kubernetes" หรือดู "วิดีโอ" บางส่วนสำหรับการสาธิต คุณลักษณะเด่น และเซสชันด้านเทคนิค

ฉันหวังว่าคุณจะสนุกและเรียนรู้บางอย่างจากบทความนี้ 🙌