การเปรียบเทียบที่เหมาะสมของ Kubernetes ใช้ แทนที่ และแก้ไข

Kubernetes มีตัวเลือกมากมายสำหรับการอัปเดตทรัพยากร: ใช้ แก้ไข แก้ไข และแทนที่ มีความสับสนว่าแต่ละคนทำอะไรและควรใช้เมื่อใด ลองคิดดูสิ

การเปรียบเทียบที่เหมาะสมของ Kubernetes ใช้ แทนที่ และแก้ไข

ถ้า ค้นหาบน Google มีวลี "kubernetes Apply vs แทนที่" ตั้งอยู่ ตอบกลับ StackOverflowซึ่งไม่ถูกต้อง เมื่อทำการค้นหา "kubernetes Apply vs patch" ลิงก์แรกคือเอกสารประกอบ kubectl patchซึ่งไม่รวมการเปรียบเทียบ apply и patch. บทความนี้จะกล่าวถึงตัวเลือกต่างๆ รวมถึงการใช้งานที่เหมาะสมของแต่ละตัวเลือก

ในช่วงวงจรชีวิตของทรัพยากร Kubernetes (บริการ การนำไปใช้งาน ทางเข้า ฯลฯ) บางครั้งคุณจำเป็นต้องเปลี่ยนแปลง เพิ่ม หรือลบคุณสมบัติบางอย่างของทรัพยากรนี้ เช่น เพิ่มบันทึก เพิ่มหรือลดจำนวนแบบจำลอง

Kubernetes CLI

หากคุณทำงานกับคลัสเตอร์ Kubernetes ผ่าน CLI อยู่แล้ว แสดงว่าคุณคุ้นเคยอยู่แล้ว apply и edit. ทีม apply อ่านข้อกำหนดทรัพยากรจากไฟล์และสร้าง "upsert" ไปยังคลัสเตอร์ Kubernetes เช่น สร้างทรัพยากรหากไม่มีอยู่และอัปเดตหากมีอยู่ ทีม edit อ่านทรัพยากรผ่าน API จากนั้นเขียนข้อกำหนดทรัพยากรลงในไฟล์ในเครื่อง ซึ่งจากนั้นจะเปิดในโปรแกรมแก้ไขข้อความ หลังจากที่คุณแก้ไขและบันทึกไฟล์แล้ว kubectl จะส่งการเปลี่ยนแปลงที่ทำกลับผ่าน API ซึ่งจะนำการเปลี่ยนแปลงเหล่านี้ไปใช้กับทรัพยากรอย่างระมัดระวัง

ไม่ใช่ทุกคนที่รู้คำสั่ง patch и replace. ทีม patch อนุญาตให้คุณเปลี่ยนส่วนหนึ่งของข้อกำหนดคุณสมบัติทรัพยากร โดยระบุเฉพาะส่วนที่เปลี่ยนแปลงในบรรทัดคำสั่ง ทีม replace ทำงานเหมือนกับ editแต่ทุกอย่างจะต้องดำเนินการด้วยตนเอง: คุณต้องดาวน์โหลดเวอร์ชันปัจจุบันของข้อกำหนดทรัพยากร เช่น การใช้ kubectl get -o yamlแก้ไขแล้วจึงใช้งาน replace เพื่ออัปเดตทรัพยากรตามข้อกำหนดที่เปลี่ยนแปลง ทีม replace จะไม่ทำงานหากมีการเปลี่ยนแปลงใดๆ เกิดขึ้นระหว่างการอ่านและการแทนที่ทรัพยากร

Kubernetes API

คุณคงคุ้นเคยกับวิธีการต่างๆ CoreV1().Pods().Update(), replaceNamespacedService หรือ patch_namespaced_deploymentหากคุณทำงานกับคลัสเตอร์ผ่าน ไลบรารีไคลเอ็นต์สำหรับ Kubernetes API โดยใช้ภาษาโปรแกรมบางอย่าง ไลบรารีจัดการวิธีการเหล่านี้ผ่านการร้องขอ HTTP โดยใช้วิธีการ PUT и PATCH... โดยที่ update и replace ใช้ PUTและ patchไม่ว่าจะเล็กน้อยแค่ไหนก็ใช้ PATCH.

มันเป็นที่น่าสังเกตว่า kubectl ยังทำงานร่วมกับคลัสเตอร์ผ่าน API ได้อีกด้วย กล่าวอีกนัยหนึ่ง kubectlเป็น wrapper ที่อยู่ด้านบนของไลบรารีไคลเอนต์สำหรับภาษา Go ซึ่งส่วนใหญ่ให้ความสามารถในการจัดเตรียมคำสั่งย่อยในรูปแบบที่กะทัดรัดและอ่านง่ายขึ้น นอกเหนือจากความสามารถมาตรฐานของ API ตัวอย่างเช่น ดังที่คุณอาจสังเกตเห็นแล้วว่าวิธีการนี้ apply ไม่ได้กล่าวไว้ข้างต้นในย่อหน้าก่อนหน้า ปัจจุบัน (พฤษภาคม 2020, ประมาณ นักแปล) ตรรกะทั้งหมด kubectl apply, เช่น. การสร้างทรัพยากรที่ไม่มีอยู่จริงและการอัปเดตทรัพยากรที่มีอยู่ ทำงานบนฝั่งโค้ดทั้งหมด kubectl. กำลังพยายามอยู่ เกี่ยวกับการถ่ายโอนลอจิก apply ไปทางด้าน API แต่ก็ยังอยู่ในช่วงเบต้า ฉันจะเขียนรายละเอียดเพิ่มเติมด้านล่าง

แพทช์ตามค่าเริ่มต้น

ใช้ดีที่สุด patchหากคุณต้องการอัปเดตทรัพยากร นี่คือวิธีที่ไลบรารีไคลเอ็นต์ทั้งสองทำงานบน Kubernetes API และ kubectl (ไม่น่าแปลกใจ เนื่องจากเป็น wrapper สำหรับไลบรารีไคลเอ็นต์ ประมาณ นักแปล).

ทำงานอย่างมีกลยุทธ์

ทุกทีม kubectl apply, edit и patch ใช้วิธีการ PATCH ในคำขอ HTTP เพื่ออัปเดตทรัพยากรที่มีอยู่ หากคุณเจาะลึกการใช้งานคำสั่งโดยละเอียดมากขึ้น คำสั่งทั้งหมดก็ใช้วิธีการนั้น การผสานรวมเชิงกลยุทธ์ เพื่ออัพเดตทรัพยากรแม้ว่าคำสั่ง patch อาจใช้วิธีการอื่น (เพิ่มเติมด้านล่างนี้) วิธีการแก้ไขแบบผสานเชิงกลยุทธ์พยายามที่จะ "ทำให้ถูกต้อง" โดยการผสานข้อกำหนดที่ให้มาเข้ากับข้อกำหนดที่มีอยู่ โดยเฉพาะอย่างยิ่ง พยายามรวมทั้งอ็อบเจ็กต์และอาร์เรย์ ซึ่งหมายความว่าการเปลี่ยนแปลงมีแนวโน้มที่จะเป็นการบวก เช่น การรันคำสั่ง patch ด้วยตัวแปรสภาพแวดล้อมใหม่ในข้อกำหนดเฉพาะของคอนเทนเนอร์พ็อด จะทำให้ตัวแปรสภาพแวดล้อมนั้นถูกเพิ่มลงในตัวแปรสภาพแวดล้อมที่มีอยู่แทนที่จะเขียนทับ หากต้องการลบโดยใช้วิธีนี้ คุณต้องบังคับให้ค่าพารามิเตอร์เป็นโมฆะในข้อกำหนดที่ให้ไว้ ของทีมไหน. kubectl ควรใช้สำหรับการอัพเดตหรือไม่?

หากคุณสร้างและจัดการทรัพยากรของคุณโดยใช้ kubectl applyเมื่ออัปเดตจะเป็นการดีกว่าถ้าใช้เสมอ kubectl applyถึง kubectl สามารถจัดการการกำหนดค่าและติดตามการเปลี่ยนแปลงที่ร้องขอจากแอปพลิเคชันไปยังแอปพลิเคชันได้อย่างถูกต้อง ข้อดีใช้เสมอ apply คือการติดตามข้อกำหนดที่ใช้ก่อนหน้านี้ ทำให้สามารถทราบเมื่อคุณสมบัติข้อกำหนดและองค์ประกอบอาร์เรย์ถูกลบออกอย่างชัดเจน นี้ช่วยให้คุณสามารถใช้ apply เพื่อลบคุณสมบัติและองค์ประกอบอาร์เรย์ ในขณะที่การผสานเชิงกลยุทธ์ตามปกติจะไม่ทำงาน ทีม edit и patch อย่าอัพเดตบันทึกย่อนั้น kubectl apply ใช้เพื่อติดตามการเปลี่ยนแปลง ดังนั้นการเปลี่ยนแปลงใด ๆ ที่ถูกติดตามและทำผ่าน Kubernetes API แต่ทำผ่านคำสั่ง edit и patchมองไม่เห็นคำสั่งต่อมา applyนั่นคือ apply จะไม่ลบออกแม้ว่าจะไม่ปรากฏในข้อกำหนดอินพุตก็ตาม apply (เอกสารบอกว่า edit и patch อัปเดตบันทึกย่อที่ใช้ applyแต่ในทางปฏิบัติ - ไม่)

ถ้าไม่ใช้คำสั่ง apply,สามารถใช้เป็น editและ patchโดยเลือกคำสั่งที่เหมาะสมกับการเปลี่ยนแปลงที่เกิดขึ้นมากที่สุด เมื่อเพิ่มและเปลี่ยนแปลงคุณสมบัติ BOM ทั้งสองวิธีจะใกล้เคียงกัน เมื่อลบคุณสมบัติข้อกำหนดหรือองค์ประกอบอาร์เรย์ edit ทำตัวเหมือนการเปิดตัวครั้งเดียว applyรวมถึงการติดตามว่าข้อกำหนดนั้นเป็นอย่างไรก่อนและหลังการแก้ไข เพื่อให้คุณสามารถลบคุณสมบัติและองค์ประกอบอาร์เรย์ออกจากทรัพยากรได้อย่างชัดเจน คุณต้องตั้งค่าคุณสมบัติเป็นโมฆะอย่างชัดเจนในข้อกำหนดสำหรับ patchเพื่อลบออกจากทรัพยากร การลบองค์ประกอบอาร์เรย์โดยใช้การแพตช์ผสานเชิงกลยุทธ์นั้นซับซ้อนกว่าเนื่องจากต้องใช้คำสั่งผสาน ดูวิธีการอัปเกรดอื่นๆ ด้านล่างเพื่อดูทางเลือกที่มีประสิทธิภาพมากขึ้น

เพื่อใช้วิธีการอัพเดตในไลบรารีไคลเอนต์ที่ทำงานคล้ายกับคำสั่งด้านบน kubectlควรตั้งค่าไว้ในคำขอ content-type в application/strategic-merge-patch+json. หากคุณต้องการลบคุณสมบัติในข้อกำหนด คุณต้องตั้งค่าคุณสมบัติให้เป็น null อย่างชัดเจนในลักษณะเดียวกัน kubectl patch. หากคุณต้องการลบองค์ประกอบอาร์เรย์ คุณควรรวมคำสั่งการผสานไว้ในข้อกำหนดการอัปเดต หรือใช้แนวทางอื่นในการอัปเดต

แนวทางอื่นๆ ในการอัปเดต

Kubernetes รองรับวิธีอัปเดตอีกสองวิธี: JSON ผสานแพตช์ и แพตช์ JSON. วิธีการแพตช์ผสาน JSON ใช้ข้อกำหนด Kubernetes บางส่วนเป็นอินพุต และรองรับการผสานออบเจ็กต์ที่คล้ายกับวิธีการแพตช์ผสานเชิงกลยุทธ์ ข้อแตกต่างระหว่างทั้งสองคือรองรับเฉพาะการแทนที่อาร์เรย์ ซึ่งรวมถึงอาร์เรย์คอนเทนเนอร์ในข้อกำหนดเฉพาะของพ็อดด้วย ซึ่งหมายความว่าเมื่อใช้แพตช์ผสาน JSON คุณจะต้องระบุข้อกำหนดที่ครบถ้วนสำหรับคอนเทนเนอร์ทั้งหมด ในกรณีที่คุณสมบัติของคอนเทนเนอร์มีการเปลี่ยนแปลง ดังนั้นวิธีนี้จึงมีประโยชน์ในการลบองค์ประกอบออกจากอาร์เรย์ใน BOM บนบรรทัดคำสั่ง คุณสามารถเลือกแพตช์ผสาน JSON ได้โดยใช้ kubectl patch --type=merge. เมื่อทำงานกับ Kubernetes API คุณควรใช้วิธีการร้องขอ PATCH และการติดตั้ง content-type в application/merge-patch+json.

วิธีการแพตช์ JSON แทนที่จะระบุข้อกำหนดเฉพาะบางส่วนของทรัพยากร จะใช้การให้การเปลี่ยนแปลงที่คุณต้องการทำกับทรัพยากรในรูปแบบอาร์เรย์ ซึ่งแต่ละองค์ประกอบของอาร์เรย์จะแสดงคำอธิบายของการเปลี่ยนแปลงที่เกิดขึ้นกับทรัพยากร แนวทางนี้เป็นวิธีที่ยืดหยุ่นและมีประสิทธิภาพมากกว่าในการแสดงการเปลี่ยนแปลงที่กำลังดำเนินการ แต่ต้องเสียค่าใช้จ่ายในการแสดงรายการการเปลี่ยนแปลงที่ทำในรูปแบบแยกต่างหากที่ไม่ใช่ Kubernetes แทนที่จะส่งข้อกำหนดเฉพาะทรัพยากรบางส่วน ใน kubectl คุณสามารถเลือกแพตช์ JSON ได้โดยใช้ kubectl patch --type=json. เมื่อใช้ Kubernetes API วิธีการนี้จะใช้ได้กับวิธีการร้องขอ PATCH และการติดตั้ง content-type в application/json-patch+json.

เราต้องการความมั่นใจ - ใช้การแทนที่

ในบางกรณี คุณต้องแน่ใจว่าไม่มีการเปลี่ยนแปลงใดๆ กับทรัพยากรระหว่างเวลาที่อ่านทรัพยากรและเมื่อมีการอัปเดต กล่าวอีกนัยหนึ่ง คุณควรตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงทั้งหมดจะเป็นไปตามนั้น อะตอม. ในกรณีนี้ เพื่ออัปเดตทรัพยากรที่คุณควรใช้ replace. ตัวอย่างเช่น หากคุณมี ConfigMap ที่มีตัวนับที่อัปเดตจากหลายแหล่ง คุณควรแน่ใจว่าทั้งสองแหล่งไม่อัปเดตตัวนับพร้อมกัน ส่งผลให้การอัปเดตสูญหาย เพื่อสาธิต ลองจินตนาการถึงลำดับเหตุการณ์โดยใช้แนวทางนี้ patch:

  • A และ B รับสถานะปัจจุบันของทรัพยากรจาก API
  • แต่ละรายการจะอัปเดตข้อกำหนดในเครื่องโดยเพิ่มตัวนับทีละรายการและเพิ่ม "A" หรือ "B" ตามลำดับในบันทึกย่อ "อัปเดตโดย"
  • และจะอัปเดตทรัพยากรเร็วขึ้นเล็กน้อย
  • B อัพเดตทรัพยากร

เป็นผลให้การอัปเดต A หายไป การดำเนินการครั้งสุดท้าย patch ชนะ ตัวนับจะเพิ่มขึ้นทีละหนึ่งแทนที่จะเป็นสอง และค่าของบันทึกย่อ "อัปเดตโดย" จะลงท้ายด้วย "B" และไม่มี "A" ลองเปรียบเทียบข้างต้นกับสิ่งที่เกิดขึ้นเมื่อการอัปเดตเสร็จสิ้นโดยใช้แนวทางนี้ replace:

  • A และ B รับสถานะปัจจุบันของทรัพยากรจาก API
  • แต่ละรายการจะอัปเดตข้อกำหนดในเครื่องโดยเพิ่มตัวนับทีละรายการและเพิ่ม "A" หรือ "B" ตามลำดับในบันทึกย่อ "อัปเดตโดย"
  • และจะอัปเดตทรัพยากรเร็วขึ้นเล็กน้อย
  • B พยายามอัปเดตทรัพยากร แต่การอัปเดตถูกปฏิเสธโดย API เนื่องจากเวอร์ชันของทรัพยากรอยู่ในข้อกำหนด replace ไม่ตรงกับเวอร์ชันปัจจุบันของทรัพยากรใน Kubernetes เนื่องจากเวอร์ชันของทรัพยากรเพิ่มขึ้นตามการดำเนินการแทนที่ของ A

ในกรณีข้างต้น B จะต้องดึงทรัพยากรอีกครั้ง ทำการเปลี่ยนแปลงสถานะใหม่ และลองอีกครั้ง replace. สิ่งนี้จะทำให้ตัวนับเพิ่มขึ้นทีละสองและบันทึกย่อ "อัปเดตโดย" จะรวม "AB" ที่ท้าย

ตัวอย่างข้างต้นบอกเป็นนัยว่าเมื่อดำเนินการ replace ทรัพยากรทั้งหมดถูกแทนที่โดยสมบูรณ์ ข้อมูลจำเพาะที่ใช้สำหรับ replaceจะต้องไม่เป็นบางส่วนหรือเป็นบางส่วนเหมือนใน applyแต่ครบถ้วนรวมถึงการต่อเติมด้วย resourceVersion ลงในข้อมูลเมตาของข้อกำหนด หากคุณไม่ได้เปิดใช้งาน resourceVersion หรือเวอร์ชันที่คุณระบุไม่ใช่เวอร์ชันปัจจุบัน เวอร์ชันทดแทนจะถูกปฏิเสธ ดังนั้นแนวทางการใช้ที่ดีที่สุดคือ replace – อ่านทรัพยากร อัปเดต และแทนที่ทันที โดยใช้ kubectlอาจมีลักษณะดังนี้:

$ kubectl get deployment my-deployment -o json 
    | jq '.spec.template.spec.containers[0].env[1].value = "new value"' 
    | kubectl replace -f -

เป็นที่น่าสังเกตว่าคำสั่งสองคำสั่งต่อไปนี้ซึ่งดำเนินการตามลำดับจะดำเนินการได้สำเร็จตั้งแต่นั้นมา deployment.yaml ไม่มีทรัพย์สิน .metadata.resourceVersion

$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml

สิ่งนี้ดูเหมือนจะขัดแย้งกับสิ่งที่กล่าวไว้ข้างต้นนั่นคือ "เพิ่ม resourceVersion ลงในข้อกำหนดเมตาดาต้า" พูดแบบนั้นผิดไหม ไม่ใช่ ไม่ใช่ เพราะถ้า kubectl สังเกตว่าคุณไม่ได้ระบุ resourceVersionมันจะอ่านจากทรัพยากรและเพิ่มลงในข้อกำหนดที่คุณระบุ จากนั้นจึงดำเนินการเท่านั้น replace. เนื่องจากสิ่งนี้อาจเป็นอันตรายได้หากคุณอาศัยอะตอมมิกซิตี เวทมนตร์จึงทำงานที่ด้านข้างทั้งหมด kubectlคุณไม่ควรเชื่อถือเมื่อใช้ไลบรารีไคลเอ็นต์ที่ทำงานร่วมกับ API ในกรณีนี้ คุณจะต้องอ่านข้อกำหนดทรัพยากรปัจจุบัน อัปเดต จากนั้นจึงดำเนินการ PUT ขอ.

คุณไม่สามารถทำการแพตช์ได้ - เราจะทำการแทนที่

บางครั้งคุณจำเป็นต้องทำการเปลี่ยนแปลงบางอย่างที่ API ไม่สามารถจัดการได้ ในกรณีเหล่านี้ คุณสามารถบังคับให้เปลี่ยนทรัพยากรได้โดยการลบและสร้างใหม่ นี้จะเสร็จสิ้นโดยใช้ kubectl replace --force. การรันคำสั่งจะลบรีซอร์สทันที จากนั้นสร้างใหม่จากข้อกำหนดที่ให้มา ไม่มีตัวจัดการ "บังคับแทนที่" ใน API และเพื่อที่จะดำเนินการดังกล่าวผ่าน API คุณจะต้องดำเนินการสองอย่าง ขั้นแรกคุณต้องลบทรัพยากรโดยการตั้งค่า gracePeriodSeconds ถึงศูนย์ (0) และ propagationPolicy ใน "พื้นหลัง" จากนั้นสร้างทรัพยากรนี้ใหม่ตามข้อกำหนดที่ต้องการ

คำเตือน: วิธีการนี้อาจเป็นอันตรายและอาจนำไปสู่สภาวะที่ไม่ได้กำหนดไว้

สมัครบนฝั่งเซิร์ฟเวอร์

ตามที่กล่าวไว้ข้างต้น นักพัฒนา Kubernetes กำลังทำงานเพื่อนำตรรกะไปใช้ apply ของ kubectl ใน Kubernetes API ลอจิก apply มีอยู่ใน Kubernetes 1.18 ผ่าน kubectl apply --server-side หรือผ่าน API โดยใช้วิธี PATCH с content-type application/apply-patch+YAML.

หมายเหตุ: JSON ก็เป็น YAML ที่ถูกต้องเช่นกัน ดังนั้นคุณจึงสามารถส่งข้อกำหนดเป็น JSON ได้แม้ว่าจะเป็นเช่นนั้นก็ตาม content-type จะ application/apply-patch+yaml.

นอกจากตรรกะนั้นแล้ว kubectl เปิดให้ทุกคนใช้งานได้ผ่าน API apply ทางฝั่งเซิร์ฟเวอร์ ติดตามผู้ที่รับผิดชอบฟิลด์ในข้อกำหนด จึงทำให้สามารถเข้าถึงหลายรายการได้อย่างปลอดภัยสำหรับการแก้ไขที่ปราศจากข้อขัดแย้ง กล่าวอีกนัยหนึ่งถ้า apply ทางฝั่งเซิร์ฟเวอร์จะแพร่หลายมากขึ้น อินเทอร์เฟซการจัดการทรัพยากรที่ปลอดภัยสากลจะปรากฏขึ้นสำหรับไคลเอนต์ที่แตกต่างกัน เช่น kubectl, Pulumi หรือ Terraform, GitOps รวมถึงสคริปต์ที่เขียนเองโดยใช้ไลบรารีไคลเอนต์

ผลของการ

ฉันหวังว่าภาพรวมสั้นๆ ของวิธีต่างๆ ในการอัปเดตทรัพยากรในคลัสเตอร์จะเป็นประโยชน์กับคุณ เป็นเรื่องดีที่รู้ว่าไม่เพียงแต่ใช้เทียบกับการแทนที่เท่านั้น แต่ยังสามารถอัปเดตทรัพยากรโดยใช้ใช้ แก้ไข แก้ไข หรือแทนที่ได้ โดยหลักการแล้วแต่ละวิธีมีพื้นที่การใช้งานของตัวเอง สำหรับการเปลี่ยนแปลงแบบอะตอมมิก ควรแทนที่ มิฉะนั้น คุณควรใช้แพตช์ผสานเชิงกลยุทธ์ผ่านการใช้ อย่างน้อยที่สุด ฉันคาดหวังให้คุณเข้าใจว่าคุณไม่สามารถเชื่อถือ Google หรือ StackOerflow เมื่อค้นหา "kubernetes Apply vs แทนที่" อย่างน้อยก็จนกว่าบทความนี้จะแทนที่คำตอบปัจจุบัน

การเปรียบเทียบที่เหมาะสมของ Kubernetes ใช้ แทนที่ และแก้ไข

ที่มา: will.com

เพิ่มความคิดเห็น