paint-brush
วิธีเพิ่มประสิทธิภาพ Kubernetes สำหรับภาพ Docker ขนาดใหญ่โดย@kksudo
132 การอ่าน

วิธีเพิ่มประสิทธิภาพ Kubernetes สำหรับภาพ Docker ขนาดใหญ่

โดย Kazakov Kirill10m2024/09/30
Read on Terminal Reader

นานเกินไป; อ่าน

🚀 ผู้เชี่ยวชาญด้าน Kubernetes คุณเบื่อกับการต้องรอเวลาหลายชั่วโมงเพื่อให้โหนดของคุณอุ่นเครื่องหรือไม่ ลองนึกภาพว่าคุณสามารถย่นเวลาให้เหลือเพียงไม่กี่วินาทีดูสิ! บทความที่เปลี่ยนเกมนี้จะเปิดเผยวิธีเร่งกระบวนการปรับใช้ Kubernetes ของคุณ แม้ว่าจะมีอิมเมจขนาดใหญ่ 3GB และพ็อด 1,000 พ็อดก็ตาม ค้นพบสูตรลับที่เปลี่ยนประสิทธิภาพของคลัสเตอร์ของคุณจากช้าเป็นเร็วกว่าเสียง อย่าปล่อยให้การอุ่นเครื่องที่ช้ามาขัดขวางคุณ เรียนรู้วิธีปฏิวัติเวิร์กโฟลว์ Kubernetes ของคุณวันนี้!
featured image - วิธีเพิ่มประสิทธิภาพ Kubernetes สำหรับภาพ Docker ขนาดใหญ่
Kazakov Kirill HackerNoon profile picture
0-item

ภาพรวมสั้นๆ ของปัญหา

วันหนึ่งระหว่างการอัปเดตคลัสเตอร์ k8s ตามแผน เราพบว่า POD เกือบทั้งหมดของเรา (ประมาณ 500 จาก 1,000) ในโหนดใหม่ไม่สามารถเริ่มทำงานได้ และนาทีก็กลายเป็นชั่วโมงอย่างรวดเร็ว เราพยายามค้นหาสาเหตุที่แท้จริง แต่หลังจากผ่านไปสามชั่วโมง PODS ยังคงอยู่ในสถานะ ContainerCreating


Kubernetes ติดอยู่ใน ContainerCreating

โชคดีที่นี่ไม่ใช่สภาพแวดล้อมการผลิตและหน้าต่างการบำรุงรักษาถูกกำหนดไว้ในช่วงสุดสัปดาห์ เรามีเวลาตรวจสอบปัญหาโดยไม่มีแรงกดดันใดๆ

คุณควรเริ่มค้นหาสาเหตุที่แท้จริงจากที่ไหน คุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีแก้ปัญหาที่เราพบหรือไม่ เตรียมตัวให้พร้อมและสนุกไปกับมัน!

รายละเอียดเพิ่มเติมเกี่ยวกับปัญหา

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


บางครั้งกระบวนการ CD อาจใช้เวลานานถึง 3 ชั่วโมงในการดึงภาพออกมา อย่างไรก็ตาม ในครั้งนี้ กระบวนการดังกล่าวเกิดการหยุดชะงัก เนื่องจากปริมาณ PODS ในระหว่างการอัปเกรด EKS (แบบอินไลน์ เมื่อเราแทนที่โหนดทั้งหมดในคลัสเตอร์) สูงเกินไป


  • แอปทั้งหมดของเราอยู่ใน k8s (ตาม EKS ) เพื่อประหยัดต้นทุนสำหรับสภาพแวดล้อม DEV เราจึงใช้อินสแตนซ์จุด

  • เราใช้อิมเมจ AmazonLinux2 สำหรับโหนด

  • เรามี ฟีเจอร์สาขา (FB) จำนวนมากในสภาพแวดล้อมการพัฒนาที่ปรับใช้กับคลัสเตอร์ Kubernetes ของเราอย่างต่อเนื่อง FB แต่ละรายการมีชุดแอปพลิเคชันของตัวเอง และแอปพลิเคชันแต่ละรายการมีชุดการอ้างอิงของตัวเอง (ภายในอิมเมจ)

  • ในโครงการของเรา มีแอปเกือบ 200 แอป และจำนวนนี้ยังคงเพิ่มขึ้นเรื่อยๆ แอปแต่ละตัวจะใช้หนึ่งใน 7 อิมเมจพื้นฐานของ Docker ที่มีขนาดประมาณ 2 GB ขนาดรวมสูงสุดของอิมเมจที่เก็บถาวร (ใน ECR ) อยู่ที่ประมาณ 3 GB

  • รูปภาพทั้งหมดถูกเก็บไว้ใน Amazon Elastic Container Registry (ECR)

  • เราใช้ประเภทปริมาณ gp3 EBS เริ่มต้นสำหรับโหนด


ปัญหาที่ต้องเผชิญ

  • ระยะเวลาการเริ่มต้นแบบเย็นที่ขยายออก: การเริ่มพ็อดใหม่ด้วยภาพใหม่นั้นอาจใช้เวลานานกว่า 1 ชั่วโมง โดยเฉพาะอย่างยิ่งเมื่อมีการดึงภาพหลายภาพพร้อมกันบนโหนดเดียว

  • ข้อผิดพลาด ErrImagePull: เกิด ErrImagePull บ่อยครั้ง หรือติดอยู่ในสถานะ ContainerCreating บ่งชี้ถึงปัญหาในการดึงภาพ

  • การใช้ดิสก์สูง: การใช้ดิสก์ยังคงอยู่ที่เกือบ 100% ในระหว่างกระบวนการดึงภาพ ซึ่งเป็นผลมาจากการใช้ดิสก์ I/O จำนวนมากที่จำเป็นสำหรับการคลายการบีบอัด (เช่น “unpigz”)

  • ปัญหาชุด DaemonSet ของระบบ: ชุด DaemonSet ของระบบบางชุด (เช่น aws-node หรือ ebs-csi-node ) ถูกย้ายไปยังสถานะ "ไม่พร้อม" เนื่องจากแรงกดดันของดิสก์ ซึ่งส่งผลกระทบต่อความพร้อมของโหนด

  • ไม่มีแคชรูปภาพบนโหนด: เนื่องจากเราใช้อินสแตนซ์จุด เราจึงไม่สามารถใช้ดิสก์ภายในเครื่องเพื่อแคชรูปภาพได้


ส่งผลให้การปรับใช้บนสาขาฟีเจอร์ต่างๆ หยุดชะงักเป็นจำนวนมาก โดยเฉพาะอย่างยิ่ง เนื่องจาก FB ที่แตกต่างกันมีชุดรูปภาพพื้นฐานที่แตกต่างกัน

หลังจากตรวจสอบอย่างรวดเร็ว เราพบว่าปัญหาหลักคือแรงกดดันของดิสก์บนโหนดโดยกระบวนการ unpigz กระบวนการนี้รับผิดชอบในการคลายการบีบอัดอิมเมจของ Docker เราไม่ได้เปลี่ยนการตั้งค่าเริ่มต้นสำหรับประเภทโวลุ่ม EBS ของ gp3 เนื่องจากไม่เหมาะกับกรณีของเรา


Hotfix สำหรับการกู้คืนคลัสเตอร์

ในขั้นตอนแรกเราตัดสินใจที่จะลดจำนวน POD บนโหนด

  1. เราย้ายโหนดใหม่ไปยังสถานะ “Cordon”
  2. ถอด PODS ที่ติดอยู่ทั้งหมดออกเพื่อลดแรงกดของดิสก์
  3. รัน POD ทีละตัวเพื่ออุ่นเครื่องโหนด
  4. หลังจากนั้นเราจะย้ายโหนดที่อุ่นเครื่องแล้วไปสู่สถานะปกติ (“unCordon”)
  5. ลบโหนดทั้งหมดในสถานะค้างอยู่
  6. PODS ทั้งหมดเริ่มทำงานได้สำเร็จโดยใช้แคชภาพ Docker


การออกแบบ CI/CD ดั้งเดิม

แนวคิดหลักของโซลูชันนี้คือการวอร์มอัปโหนดก่อนที่กระบวนการ CD จะเริ่มต้นโดยใช้ส่วนที่ใหญ่ที่สุดของอิมเมจ Docker (เลเยอร์การพึ่งพา JS) ซึ่งใช้เป็นอิมเมจรูทสำหรับแอปทั้งหมดของเรา เรามีอิมเมจรูทอย่างน้อย 7 ประเภทที่มีการพึ่งพา JS ซึ่งเกี่ยวข้องกับประเภทของแอป ดังนั้น มาวิเคราะห์การออกแบบ CI/CD ดั้งเดิมกัน


ใน CI/CD pipeline ของเรา เรามี 3 เสาหลัก: ท่อ CI/CD ดั้งเดิม

ท่อ CI/CD ดั้งเดิม:

  1. ในขั้นตอน Init it: เตรียมสภาพแวดล้อม/ตัวแปร กำหนดชุดของอิมเมจที่จะสร้างใหม่ ฯลฯ...

  2. ในขั้นตอน Build : เราสร้างภาพและส่งไปยัง ECR

  3. ในขั้นตอน Deploy : เราจะปรับใช้รูปภาพไปยัง k8s (อัปเดตการปรับใช้ เป็นต้น...)


รายละเอียดเพิ่มเติมเกี่ยวกับการออกแบบ CICD ดั้งเดิม:

  • สาขาคุณลักษณะ (FB) ของเราแยกออกจากสาขา main ในกระบวนการ CI เราจะวิเคราะห์ชุดรูปภาพที่มีการเปลี่ยนแปลงใน FB และสร้างใหม่เสมอ สาขา main จะเสถียรเสมอ เนื่องจากคำจำกัดความควรมีรูปภาพพื้นฐานเวอร์ชันล่าสุดอยู่เสมอ
  • เราสร้างภาพ Docker ของ JS ที่ต้องพึ่งพา (สำหรับแต่ละสภาพแวดล้อม) แยกกันและส่งไปยัง ECR เพื่อนำกลับมาใช้ใหม่เป็นภาพราก (ฐาน) ใน Dockerfile เรามีภาพ Docker ที่ต้องพึ่งพา JS ประมาณ 5–10 ประเภท
  • FB จะถูกปรับใช้กับคลัสเตอร์ k8s ในเนมสเปซที่แยกจากกัน แต่สำหรับโหนดทั่วไปสำหรับ FB FB สามารถมีแอพได้ ~200 แอพ โดยมีขนาดภาพสูงสุด 3 GB
  • เรามีระบบปรับขนาดคลัสเตอร์อัตโนมัติ ซึ่งปรับขนาดโหนดในคลัสเตอร์ตามโหลดหรือ PODS ที่รอดำเนินการด้วย nodeSelector และค่าความคลาดเคลื่อนที่สอดคล้องกัน
  • เราใช้จุดอินสแตนซ์สำหรับโหนด

การดำเนินการตามกระบวนการวอร์มอัพ

มีข้อกำหนดสำหรับกระบวนการอุ่นเครื่อง

บังคับ:

  1. การแก้ไขปัญหา : จัดการและแก้ไขปัญหา ContainerCreating
  2. ปรับปรุงประสิทธิภาพ : ลดเวลาในการเริ่มต้นระบบอย่างมากด้วยการใช้อิมเมจฐานที่อุ่นไว้ล่วงหน้า (การอ้างอิง JS)

ดีใจที่มีการปรับปรุง:

  1. ความยืดหยุ่น : ช่วยให้สามารถเปลี่ยนแปลงประเภทโหนดและอายุการใช้งานได้อย่างง่ายดาย (เช่น SLA ที่สูงหรือระยะเวลาการใช้งานที่ขยายออกไป)
  2. ความโปร่งใส : ให้มาตรวัดที่ชัดเจนเกี่ยวกับการใช้งานและประสิทธิภาพ
  3. ประสิทธิภาพด้านต้นทุน : ประหยัดต้นทุนด้วยการลบ VNG ทันทีหลังจากลบสาขาฟีเจอร์ที่เกี่ยวข้อง
  4. การแยกตัว : แนวทางนี้ทำให้แน่ใจว่าสภาพแวดล้อมอื่น ๆ จะไม่ได้รับผลกระทบ

สารละลาย

หลังจากวิเคราะห์ข้อกำหนดและข้อจำกัดแล้ว เราตัดสินใจที่จะใช้กระบวนการวอร์มอัพที่จะอุ่นโหนดด้วยอิมเมจแคช JS พื้นฐาน กระบวนการนี้จะถูกเรียกใช้ก่อนที่กระบวนการ CD จะเริ่มต้น เพื่อให้แน่ใจว่าโหนดพร้อมสำหรับการใช้งาน FB และเรามีโอกาสสูงสุดที่จะเข้าถึงแคช


การปรับปรุงนี้เราแบ่งออกเป็นขั้นตอนใหญ่ๆ ดังนี้:

  1. สร้าง ชุดโหนด (Virtual Node Group) ต่อแต่ละ FB

  2. เพิ่ม รูปภาพพื้นฐานลงในสคริปต์ cloud-init สำหรับโหนดใหม่

  3. เพิ่ม ขั้นตอนก่อนการปรับใช้เพื่อรัน DaemonSet พร้อมกับส่วน initContainers เพื่อดาวน์โหลดภาพ Docker ที่จำเป็นไปยังโหนดก่อนที่กระบวนการ CD จะเริ่มต้น


CI/CD Pipeline ที่อัปเดตจะมีลักษณะดังนี้: CI/CD ไปป์ไลน์ที่อัปเดต


CI/CD Pipeline ที่อัปเดต:

  1. ขั้นตอน การเริ่มต้น
    1.1.(ขั้นตอนใหม่) การเริ่มใช้งาน : หากเป็นการเริ่มต้น FB ครั้งแรก ให้สร้างชุดส่วนบุคคลใหม่ของอินสแตนซ์โหนด (ในเงื่อนไขของเราคือ Virtual Node Group หรือ VNG) และดาวน์โหลดอิมเมจพื้นฐานของ JS ทั้งหมด (5–10 อิมเมจ) จากสาขาหลัก การดำเนินการนี้ถือว่ายุติธรรม เพราะเราได้แยก FB ออกจากสาขาหลัก จุดสำคัญคือ นี่ไม่ใช่การดำเนินการบล็อก
  2. ขั้นตอน การสร้าง
  3. ขั้น ตอนก่อนการปรับใช้ ดาวน์โหลดอิมเมจฐาน JS ที่สดใหม่พร้อมแท็ก FB เฉพาะจาก ECR
    3.1.(ขั้นตอนใหม่) จุดสำคัญ : เป็นการดำเนินการบล็อค เนื่องจากเราควรลดแรงกดดันของดิสก์ ทีละรายการ เราจะดาวน์โหลดอิมเมจพื้นฐานสำหรับแต่ละโหนดที่เกี่ยวข้อง
    อย่างไรก็ตาม ขอขอบคุณสำหรับขั้นตอน “ การปรับใช้ init” เรามีภาพ Docker พื้นฐานจากสาขาหลักแล้ว ซึ่งทำให้มีโอกาสสูงที่จะเข้าถึงแคชในการเริ่มต้นครั้งแรก
  4. **การใช้งาน
    **ไม่มีการเปลี่ยนแปลงในขั้นตอนนี้ แต่ด้วยขั้นตอนก่อนหน้านี้ เรามีเลเยอร์ภาพ Docker ขนาดใหญ่ทั้งหมดบนโหนดที่จำเป็นแล้ว

ขั้นตอนการใช้งาน Init

สร้างชุดโหนดใหม่สำหรับแต่ละ FB ผ่านการเรียก API (ไปยังระบบปรับขนาดอัตโนมัติของบุคคลที่สาม) จากไปป์ไลน์ CI ของเรา


ปัญหาที่ได้รับการแก้ไข:

  1. การแยก : FB แต่ละอันมีชุดโหนดของตัวเอง เพื่อให้แน่ใจว่าสภาพแวดล้อมจะไม่ได้รับผลกระทบจาก FB อื่นๆ

  2. ความยืดหยุ่น : เราสามารถเปลี่ยนประเภทโหนดและอายุการใช้งานได้อย่างง่ายดาย

  3. ประสิทธิภาพด้านต้นทุน : เราสามารถลบโหนดได้ทันทีหลังจากลบ FB

  4. ความโปร่งใส : เราสามารถติดตามการใช้งานและประสิทธิภาพของโหนดได้อย่างง่ายดาย (แต่ละโหนดมีแท็กที่เกี่ยวข้องกับ FB)

  5. การใช้งาน Spot Instance อย่างมีประสิทธิผล : Spot Instance เริ่มต้นด้วยอิมเมจพื้นฐานที่กำหนดไว้แล้ว ซึ่งหมายความว่า หลังจากที่โหนด Spot เริ่มทำงาน ก็มีอิมเมจพื้นฐานอยู่บนโหนดแล้ว (จากสาขาหลัก)


ดาวน์โหลดภาพฐาน JS ทั้งหมดจากสาขาหลักไปยังโหนดใหม่ ผ่านสคริปต์ cloud-init


ในขณะที่กำลังดาวน์โหลดรูปภาพในพื้นหลัง กระบวนการ CD สามารถสร้างรูปภาพใหม่ต่อไปได้โดยไม่มีปัญหาใดๆ นอกจากนี้ โหนดถัดไป (ซึ่งจะสร้างขึ้นโดยระบบปรับขนาดอัตโนมัติ) จากกลุ่มนี้จะถูกสร้างขึ้นโดยใช้ข้อมูล cloud-init ที่อัปเดตแล้ว ซึ่งมีคำแนะนำในการดาวน์โหลดรูปภาพก่อนเริ่มต้นอยู่แล้ว


ปัญหาที่ได้รับการแก้ไข:

  1. การแก้ไขปัญหา : แรงกดดันของดิสก์หายไปแล้ว เนื่องจากเราอัปเดตสคริปต์ cloud-init โดยเพิ่มการดาวน์โหลดอิมเมจฐานจากสาขาหลัก วิธีนี้ช่วยให้เราเข้าถึงแคชได้เมื่อเริ่มต้น FB ครั้งแรก

  2. การใช้งานอินสแตนซ์จุดอย่างมีประสิทธิภาพ : อินสแตนซ์จุดจะเริ่มต้นด้วยข้อมูลการเริ่มต้น cloud-init ที่อัปเดต ซึ่งหมายความว่า หลังจากโหนดจุดเริ่มทำงานแล้ว จะมีอิมเมจพื้นฐานบนโหนด (จากสาขาหลัก) อยู่แล้ว

  3. ประสิทธิภาพการทำงานที่ได้รับการปรับปรุง : กระบวนการ CD สามารถสร้างภาพใหม่ต่อไปได้โดยไม่มีปัญหาใดๆ


การดำเนินการนี้เพิ่มเวลา ~17 วินาที (การเรียก API) ให้กับไปป์ไลน์ CI/CD ของเรา

การดำเนินการนี้จะสมเหตุสมผลเฉพาะในครั้งแรกที่เราเริ่ม FB เท่านั้น ในครั้งถัดไป เราจะปรับใช้แอปของเรากับโหนดที่มีอยู่แล้ว ซึ่งมีอิมเมจพื้นฐานที่เราได้ส่งมอบไปแล้วในการปรับใช้ครั้งก่อน

ขั้นตอนก่อนการใช้งาน

เราจำเป็นต้องทำขั้นตอนนี้เนื่องจากรูปภาพ FB แตกต่างจากรูปภาพสาขาหลัก เราจำเป็นต้องดาวน์โหลดรูปภาพฐาน FB ไปยังโหนดก่อนที่กระบวนการ CD จะเริ่มต้น ซึ่งจะช่วยลดเวลาในการเริ่มต้นระบบแบบเย็นที่ยาวนานและการใช้ดิสก์สูงที่อาจเกิดขึ้นได้เมื่อดึงรูปภาพขนาดใหญ่หลายภาพพร้อมกัน


วัตถุประสงค์ของขั้นตอนก่อนการปรับใช้

  1. ป้องกันแรงกดดันของดิสก์ : ดาวน์โหลดรูปภาพขนาดใหญ่ที่สุดของ Docker ตามลำดับ หลังจากขั้นตอน init-deploy แล้ว เราก็มีรูปภาพพื้นฐานบนโหนดแล้ว ซึ่งหมายความว่าเรามีโอกาสสูงที่จะเกิดแคชที่ได้รับผลกระทบ

  2. ปรับปรุงประสิทธิภาพการใช้งาน : ช่วยให้แน่ใจว่าโหนดได้รับการอุ่นเครื่องล่วงหน้าด้วยอิมเมจ Docker ที่จำเป็น ซึ่งจะนำไปสู่เวลาในการเริ่มต้น POD ที่เร็วขึ้น (เกือบจะทันที)

  3. เพิ่มเสถียรภาพ : ลดโอกาสที่จะพบข้อผิดพลาด ErrImagePull / ContainerCreating และตรวจสอบให้แน่ใจว่าชุดเดมอนของระบบยังคงอยู่ในสถานะ "พร้อม"


ในขั้นตอนนี้ เราจะเพิ่มเวลาให้กับกระบวนการซีดี 10–15 นาที

รายละเอียดขั้นตอนก่อนการใช้งาน:

  • ในซีดี เราสร้าง DaemonSet ด้วยส่วน initContainers
  • ส่วน initContainers จะถูกดำเนินการก่อนที่คอนเทนเนอร์หลักจะเริ่มต้น เพื่อให้แน่ใจว่ามีการดาวน์โหลดรูปภาพที่จำเป็นก่อนที่คอนเทนเนอร์หลักจะเริ่มต้น
  • ในซีดี เราจะตรวจสอบสถานะของ daemonSet อย่างต่อเนื่อง หาก daemonSet อยู่ในสถานะ "พร้อม" เราจะดำเนินการปรับใช้ มิฉะนั้น เราจะรอให้ daemonSet พร้อม

การเปรียบเทียบ

การเปรียบเทียบขั้นตอนเดิมและขั้นตอนที่อัปเดตกับกระบวนการอุ่นล่วงหน้า

ขั้นตอน

ขั้นตอนการใช้งาน Init

ขั้นตอนก่อนการใช้งาน

การใช้งาน

เวลารวม

ต่าง

โดยไม่ต้องอุ่นเครื่อง

0

0

11นาที 21วินาที

11นาที 21วินาที

0

ด้วยการอุ่นเครื่องล่วงหน้า

8 วินาที

58 วินาที

25 วินาที

1นาที 31วินาที

-9นาที50วินาที


สิ่งสำคัญคือเวลา "Deploy" เปลี่ยนไป (จากคำสั่ง Apply แรกไปจนถึงสถานะ Running ของพ็อด) จาก 11 นาที 21 วินาที เป็น 25 วินาที เวลารวมเปลี่ยนจาก 11 นาที 21 วินาที เป็น 1 นาที 31 วินาที

ประเด็นสำคัญคือ หากไม่มีอิมเมจฐานจากสาขาหลัก เวลา "ปรับใช้" จะเท่ากับเวลาเดิมหรืออาจมากกว่าเล็กน้อย แต่ถึงอย่างไร เราก็ได้แก้ไขปัญหาความดันดิสก์และเวลาเริ่มต้นระบบแบบเย็นแล้ว


บทสรุป เวลาการดึง

ปัญหาหลัก ContainerCreating ได้รับการแก้ไขด้วยกระบวนการวอร์มอัพ ผลที่ได้คือ เราลดเวลาการเริ่มระบบแบบเย็นของ POD ได้อย่างมาก
แรงกดดันของดิสก์หายไปแล้ว เนื่องจากเรามีอิมเมจพื้นฐานบนโหนดแล้ว daemonSet ของระบบอยู่ในสถานะ "พร้อม" และ "มีสุขภาพดี" (เนื่องจากไม่มีแรงกดดันของดิสก์) และเราไม่พบข้อผิดพลาด ErrImagePull ใดๆ ที่เกี่ยวข้องกับปัญหานี้


วิธีแก้ปัญหาและลิงค์ที่เป็นไปได้


ป.ล.: ฉันอยากจะแสดงความชื่นชมต่อทีมงานด้านเทคนิคที่ยอดเยี่ยมของ Justt ( https://www.linkedin.com/company/justt-ai ) สำหรับการทำงานอย่างไม่รู้จักเหน็ดเหนื่อยและแนวทางที่สร้างสรรค์อย่างแท้จริงในการแก้ไขปัญหาต่างๆ ที่พวกเขาเผชิญ โดยเฉพาะอย่างยิ่ง ขอแสดงความชื่นชมต่อ Ronny Sharaby หัวหน้าที่ยอดเยี่ยมซึ่งรับผิดชอบต่องานอันยอดเยี่ยมที่ทีมงานกำลังทำอยู่ ฉันตั้งตารอที่จะเห็นตัวอย่างที่ยอดเยี่ยมมากขึ้นเรื่อยๆ ว่าความคิดสร้างสรรค์ของคุณส่งผลต่อผลิตภัณฑ์ของ Justt อย่างไร


L O A D I N G
. . . comments & more!

About Author

Kazakov Kirill HackerNoon profile picture
Kazakov Kirill@kksudo
DevOps with love. Certified Kubernetes Administrator. I also enjoy riding a motorcycle.

แขวนแท็ก

บทความนี้ถูกนำเสนอใน...