Java ในคลาวด์: บทช่วยสอนการตั้งค่าการรวมอย่างต่อเนื่อง
เผยแพร่แล้ว: 2022-03-11ปีแล้วปีเล่า เราเป็นพยานถึงวิวัฒนาการอย่างรวดเร็วของอุตสาหกรรมไอที เป็นเวลากว่าสองทศวรรษแล้วที่สโลแกนที่ว่า "เขียนครั้งเดียว รันได้ทุกที่" ได้สร้างความคาดหวังในระดับใหม่ให้กับชุมชนการพัฒนาซอฟต์แวร์ และในวันนี้ เรามาถึงแล้ว ด้วยชุดเครื่องมือที่เพิ่มมากขึ้นเรื่อยๆ ซึ่งได้นำการพัฒนา Java โดยรวมโดยเฉพาะ และการพัฒนาซอฟต์แวร์โดยทั่วไป ไปสู่จักรวาลแห่งความเป็นไปได้ใหม่ทั้งหมด
ระเบียบวิธีต่างๆ เช่น Agile, DevOps และการผสานรวมและการปรับใช้อย่างต่อเนื่อง ควบคู่ไปกับวิวัฒนาการของไมโครเซอร์วิส ได้เพิ่มประสิทธิผลของกระบวนการพัฒนาซอฟต์แวร์โดยรวมจนถึงจุดที่รู้สึกยินดีเป็นอย่างยิ่งที่จะได้พัฒนาซอฟต์แวร์มากกว่าที่เคยเป็นมา การใช้ระบบอัตโนมัติและการตั้งค่าชุดเครื่องมือที่ถูกต้องจะทำให้การพัฒนาและการส่งมอบผลิตภัณฑ์ซอฟต์แวร์เป็นไปอย่างง่ายดาย
บทความนี้จะกล่าวถึงจักรวาลใหม่นี้จากมุมมองของนักพัฒนา Java ที่ข้ามเข้าสู่ DevOps และค้นหาเพื่อเพิ่มประสิทธิภาพการพัฒนาผลิตภัณฑ์และการส่งมอบให้สูงสุด
ทุกวันนี้ คำต่างๆ เช่น Spring Boot, Docker, Cloud, Amazon Web Services, Continuous Delivery ถูกนำมาใช้กันอย่างแพร่หลายแต่ไม่ค่อยเข้าใจกันอย่างกว้างขวาง บทความนี้จะใช้เส้นทางที่ง่ายที่สุดในการนำเสนอเทคโนโลยีเหล่านี้ทั้งหมดและอธิบายข้อกำหนดเหล่านี้ และสรุปไว้ในรูปแบบของบทช่วยสอนที่เราจะพัฒนาซอฟต์แวร์ชิ้นเล็กๆ และเตรียมสำหรับการส่งมอบการผลิตโดยใช้เครื่องมือที่กล่าวถึงทั้งหมด
ทำไมต้องใช้เครื่องมือเหล่านี้
ลดความซับซ้อนในการปรับใช้ด้วย Docker
”เขียนครั้งเดียว รันได้ทุกที่” เป็นความก้าวหน้าทางแนวคิดที่ก่อให้เกิดเทคโนโลยี เช่น Java Virtual Machine (JVM) ซึ่งทำให้โค้ดของคุณทำงานได้ทุกที่ และตอนนี้ เรามาถึงแล้ว สองสามทศวรรษต่อมา โดยมีการนำเสนอสิ่งที่เรียกว่า Docker ต่อชุมชนไอที Docker เป็นเครื่องมือกักกันซึ่งคุณสามารถวางซอฟต์แวร์ของคุณและเรียกใช้งานได้อย่างง่ายดาย แทบทุกที่ที่คุณต้องการ
อย่างไรก็ตาม นักพัฒนา Java อาจมองไปที่ Docker และพูดว่า "ทำไมเราถึงต้องการสิ่งนั้น เรามี JVM อยู่แล้ว ซึ่งเป็นที่รู้จักดีว่าเป็นโซลูชันหลักแบบพกพา" แต่มันคือ?
”เขียนครั้งเดียว วิ่งได้ทุกที่” ฟังดูดี และเล่นได้ดี… อย่างน้อยก็เกือบทุกครั้ง จนกว่าคุณจะพบกับผู้จำหน่าย JVM หลายราย Java เวอร์ชันหลายเวอร์ชัน ระบบปฏิบัติการหลายระบบ และการเรียงสับเปลี่ยนและการผสมผสานที่หลากหลายของสิ่งที่กล่าวมาทั้งหมด จากนั้นคุณจะพบว่าตัวเองเปลี่ยนจากกระบวนทัศน์ ”เขียนครั้งเดียว รันได้ทุกที่” ที่สง่างาม ไปเป็นหลุมพราง ”เขียนครั้งเดียว แก้ปัญหา ทุกที่” ที่ได้ผลตรงกันข้าม
และนั่นคือสิ่งที่ Docker เข้ามาเพื่อช่วยกอบกู้โลก
Docker ช่วยลดความยุ่งยากในการพัฒนา ทดสอบ และจัดส่งซอฟต์แวร์ หากคุณมีซอฟต์แวร์ที่ต้องการทดสอบ ให้ใส่ไว้ในคอนเทนเนอร์ Docker จากนั้นซอฟต์แวร์จะทำงานและสามารถติดตั้งได้ไม่ลำบากสำหรับทุกฝ่ายที่เกี่ยวข้อง
เร่งความเร็วการพัฒนาด้วย Spring Boot
น้อยกว่าทศวรรษหลังจากเปิดตัวสโลแกน "วิ่งได้ทุกที่" กรอบงาน Spring ก็ปรากฏขึ้นในที่เกิดเหตุ วันนี้ ระบบนิเวศของ Spring ยังคงเฟื่องฟูและได้ผลิตโปรเจ็กต์ Spring-based อันมีค่ามากมาย ซึ่งบางทีอาจเป็น Spring Boot ที่โดดเด่นที่สุด ตามที่ระบุไว้ในเว็บไซต์ Spring Boot:
Spring Boot ทำให้ง่ายต่อการสร้างแอปพลิเคชันที่ใช้ Spring แบบสแตนด์อโลนระดับโปรดักชันที่คุณเรียกใช้ได้
Spring Boot ช่วยให้คุณสามารถนำแอปพลิเคชันขึ้นและทำงานภายในเวลาไม่กี่นาที นักพัฒนาซอฟต์แวร์สามารถมุ่งเน้นที่การพัฒนาซอฟต์แวร์ จากนั้นจึงได้รับประโยชน์จากเครื่องมือที่กำหนดค่าทั้งหมดสำหรับพวกเขา
ในบทช่วยสอนนี้ เราจะใช้ Spring Boot เพื่อพัฒนาไมโครเซอร์วิสของเรา
การบูรณาการอย่างต่อเนื่อง (CI) กับเจนกินส์
DevOps เป็นการเคลื่อนไหวที่เติบโตอย่างรวดเร็วที่ผสานรวมทีมพัฒนาซอฟต์แวร์และทีมดูแลระบบอย่างแน่นหนา โดยมีเป้าหมายเพื่อให้การพัฒนาซอฟต์แวร์และวงจรชีวิตการส่งมอบเป็นไปอย่างราบรื่น ราบรื่น และให้ประสิทธิผลสูงสุดสำหรับทุกฝ่ายที่เกี่ยวข้อง: นักพัฒนา, sysadmins, ผู้ทดสอบ และท้ายที่สุด , ผู้ใช้ปลายทาง
การบูรณาการอย่างต่อเนื่อง (CI) เป็นหนึ่งในรากฐานที่สำคัญของการปฏิวัติ DevOps แนวคิดก็คือเมื่อใดก็ตามที่นักพัฒนาส่งรหัสไปยังที่เก็บรหัส จะถูกทดสอบโดยอัตโนมัติและจัดแพ็คเกจสำหรับการส่งมอบ (การปรับใช้) สู่การใช้งานจริง
CI จับมือกับ:
- การส่งมอบอย่างต่อเนื่อง – การจัดส่งแพคเกจอัตโนมัติที่เตรียมไว้สำหรับการทดสอบธุรกิจของผู้ใช้ปลายทางพร้อมทริกเกอร์แบบแมนนวลเพื่อปรับใช้การผลิต
- การปรับใช้อย่างต่อเนื่อง – การปรับใช้ผลิตภัณฑ์บรรจุภัณฑ์โดยอัตโนมัติไปยังการผลิตโดยตรง
มีเครื่องมือมากกว่าสองสามตัวที่สามารถใช้สำหรับการนำกระบวนการ CI ไปใช้ หนึ่งในความนิยมมากที่สุดคือ Jenkins ซึ่งเป็นเครื่องมือ CI แบบโอเพ่นซอร์ส ด้วยปลั๊กอินมากกว่าหนึ่งพันตัวและชุมชนขนาดใหญ่ที่อยู่เบื้องหลัง Jenkins เป็นตัวเลือกที่ง่ายเมื่อเริ่มคิดเกี่ยวกับการนำการผสานรวม การส่งมอบ หรือการปรับใช้อย่างต่อเนื่อง
ในบทช่วยสอนของเรา Jenkins จะถูกใช้เพื่อส่งมอบผลิตภัณฑ์ของเราไปยังระบบคลาวด์ โดยเฉพาะอย่างยิ่ง คลาวด์ของ Amazon (AWS)
คลาวด์คอมพิวติ้งด้วย AWS
หากคุณมีประสบการณ์ด้านการดูแลระบบ ลองนึกภาพขจัดความกังวลเกี่ยวกับการดูแลระบบออกจากไหล่ของคุณ คุณมีแอปพลิเคชั่นสองสามตัว คุณมีแนวคิดว่าต้องใช้ทรัพยากรมากน้อยเพียงใด แต่คุณไม่รู้ขนาดฮาร์ดแวร์ที่คุณต้องการอย่างแน่นอน คุณทำการประเมิน ซื้อทรัพยากร และระบบจะไปที่การผลิต หากคุณโชคดี คุณจะพบว่าคุณประเมินค่าสูงไปและมีทรัพยากรมากกว่าที่คุณต้องการ แต่ด้วยกฎของเมอร์ฟี คุณจะพบว่าคุณประเมินความต้องการทรัพยากรต่ำเกินไป และจบลงด้วยการแย่งชิงเพื่อให้ได้หน่วยความจำหรือพลังการประมวลผลเพิ่มขึ้นอีกเล็กน้อยภายใต้แรงกดดันด้านเวลามหาศาล ในทางตรงกันข้าม หากคุณกำลังปรับใช้กับคลาวด์ คุณเพียงแค่วางระบบของคุณออกไปที่นั่นและปรับขนาดตามต้องการ ด้วยความยืดหยุ่นที่ผู้ให้บริการคลาวด์นำเสนอ เมื่อใช้ระบบคลาวด์ คุณไม่จำเป็นต้องกังวลว่าทรัพยากรระบบจะหมด หรือไม่ต้องกังวลว่า 90 เปอร์เซ็นต์ของหน่วยความจำหรือ CPU ของคุณไม่ได้ใช้งาน
แน่นอนว่ามีความท้าทายในการตัดสินใจเลือกผู้ให้บริการ สงครามคลาวด์ยังคงดำเนินอยู่ การปะทะกันของ Microsoft, Amazon และ Google สำหรับอนาคตของการประมวลผล คือตัวอย่างชื่อที่คุณสามารถพบได้ล่าสุดในข่าวเทคโนโลยีโลก สำหรับบล็อกนี้ ฉันได้เลือก Amazon Web Services (AWS) โดยอิงจากความนิยมในปัจจุบันและส่วนแบ่งการตลาดเป็นส่วนใหญ่
ข้อดีอย่างหนึ่งของ AWS คือ Amazon มีบริการมากมายหลังจากที่คุณสมัครใช้งาน:
ในบทช่วยสอนนี้ เราจะใช้บริการของ AWS สองบริการต่อไปนี้: Elastic Compute Cloud EC2 (เจาะจงกว่านั้นคือ Amazon EC2 Container Registry หรือ Amazon ECR) และ Amazon S3 (Simple Storage Services)
อเมซอน ECR
เราจะต้องเก็บอิมเมจ Docker ไว้ที่ไหนสักแห่ง Amazon ECR เป็นบริการรีจิสทรีของ AWS Docker ที่มีการจัดการ ตามที่ระบุไว้ในเว็บไซต์ Amazon ECR:
…ทำให้นักพัฒนาสามารถจัดเก็บ จัดการ และปรับใช้อิมเมจคอนเทนเนอร์ Docker ได้อย่างง่ายดาย Amazon ECR ผสานรวมกับ Amazon EC2 Container Service (ECS) ซึ่งทำให้การพัฒนาของคุณเป็นเวิร์กโฟลว์การผลิตง่ายขึ้น Amazon ECR ขจัดความจำเป็นในการใช้งานที่เก็บคอนเทนเนอร์ของคุณเอง หรือกังวลเกี่ยวกับการปรับขนาดโครงสร้างพื้นฐานพื้นฐาน
อเมซอน S3
ดังที่กล่าวไว้ แอปพลิเคชันที่เราพัฒนาจะเป็นไมโครเซอร์วิส Spring Boot ที่จะอัปโหลดไฟล์ไปยัง Amazon S3 ตามที่ระบุไว้ในเว็บไซต์ Amazon S3:
…มอบพื้นที่จัดเก็บข้อมูลบนคลาวด์ที่ปลอดภัย ทนทาน และปรับขนาดได้สูงสำหรับนักพัฒนาและทีมไอที Amazon S3 เป็นพื้นที่จัดเก็บอ็อบเจ็กต์ที่ใช้งานง่าย พร้อมอินเทอร์เฟซบริการเว็บที่เรียบง่ายเพื่อจัดเก็บและเรียกข้อมูลจำนวนเท่าใดก็ได้จากทุกที่บนเว็บ
แบบฝึกหัด "How To" ที่ใช้งานได้จริง
เป้าหมายคือการเตรียมพร้อมสำหรับการปรับใช้ไมโครเซอร์วิส Spring Boot ซึ่งจะอัปโหลดไฟล์ไปยัง Amazon S3 ขั้นตอนมีดังต่อไปนี้:
- พัฒนาไมโครเซอร์วิส
- กำหนดกระบวนการสร้างที่บริการจะถูกเทียบท่า
- ใช้ Bitbucket เพื่อโฮสต์ที่เก็บโค้ด Git
- รวม Bitbucket กับ Jenkins เพื่อจัดแพ็คเกจแอปพลิเคชันโดยใช้ Gradle
- พุชไปที่ Amazon ECR . ระยะไกล
ต่อไปนี้เป็นบทช่วยสอนสำหรับการตั้งค่าส่วนประกอบที่จำเป็นทั้งหมด:
- แอปพลิเคชันตัวอย่าง Spring Boot – ไมโครเซอร์วิสทำแพ็กเกจและเทียบท่าโดยใช้ Gradle
- การติดตั้ง Jenkins บนเซิร์ฟเวอร์ Ubuntu ใหม่
- การรวม Bitbucket กับ Jenkins ผ่าน webhook
- การกำหนดค่างานของเจนกินส์
- Amazon ECR เพื่อจัดเก็บอิมเมจ Docker ที่มีแอปพลิเคชันของเรา
ข้อกำหนดเบื้องต้น
เพื่อให้สามารถใช้ทรัพยากรระบบคลาวด์ของ AWS ได้ เราต้องลงทะเบียนที่ Amazon ก่อน โดยการลงทะเบียน เราจะได้บัญชีพร้อมสิทธิประโยชน์การใช้งาน Free Tier ทันที เพื่อจุดประสงค์ในการเปิดใช้งานประสบการณ์จริงในช่วง 12 เดือนหลังการลงทะเบียน
ดังที่กล่าวไว้ ในบทช่วยสอนนี้ เราจะใช้ Amazon S3 และ Amazon ECR สำหรับทั้งคู่ เราจะต้องใช้คีย์การเข้าถึงเพื่อเชื่อมต่อกับบริการต่างๆ
หลังจากลงทะเบียนกับ AWS เราจะไปที่บัญชีของเรา ข้อมูลรับรองความปลอดภัย ซึ่งเราเลือก คีย์การเข้าถึง และคลิกที่ "สร้างคีย์การเข้าถึงใหม่" หลังจากคลิกแล้ว คีย์จะถูกสร้างขึ้นพร้อมกับรหัส คุณต้องจัดเก็บข้อมูลนี้ไว้ในที่ปลอดภัย เนื่องจากเราจะใช้ในภายหลังเมื่อกำหนดค่าการรวม AWS Jenkins และพัฒนาการอัปโหลดไฟล์ S3 ของเรา
ข้อกำหนดเบื้องต้นต่อไปคือ เราต้องการบัคเก็ต Amazon S3 (คอนเทนเนอร์ที่เก็บข้อมูล) Spring Boot Service ของเราจะอัปโหลดและดาวน์โหลดไฟล์เข้าและออกจากพื้นที่จัดเก็บ Amazon S3 การสร้างที่เก็บข้อมูลนั้นง่ายพอและเพียงไม่กี่คลิก คำอธิบายโดยละเอียดเกี่ยวกับวิธีการทำนั้นมีอยู่ในเอกสารสร้างบัคเก็ต
เราจะใช้ Bitbucket เพื่อโฮสต์โค้ดของเราและเรียกคำขอไปยัง Jenkins ดังนั้นจึงจำเป็นต้องมีบัญชี Bitbucket เช่นกัน Bitbucket เป็นตัวเลือกที่ยอดเยี่ยมสำหรับนักพัฒนา โดยข้อดีหลักประการหนึ่งคือมีที่เก็บส่วนตัวไม่จำกัดจำนวนที่คุณสามารถสร้างได้
การพัฒนาโปรแกรมประยุกต์
แทนที่จะลงรายละเอียดทั้งหมดของคำอธิบายประกอบของ Spring และวิธีการทำงาน ฉันจะเน้นจากมุมมองของนักพัฒนาอย่างแท้จริง ในส่วนที่ท้าทายยิ่งกว่าของการตั้งค่าทั้งหมด กล่าวคือ การติดตั้งและกำหนดค่า Linux, Jenkins และเครื่องมืออื่นๆ ที่จำเป็นสำหรับ CI ตัวอย่างโค้ดทั้งหมดที่ใช้ในบทช่วยสอนนี้ รวมถึงแอปพลิเคชันไมโครเซอร์วิส Spring Boot มีอยู่ในที่เก็บ Bickbucket สำหรับโปรเจ็กต์
องค์ประกอบของแอปพลิเคชันของเรานั้นเรียบง่าย เรามีจุดเริ่มต้นแอปพลิเคชัน Spring Boot ในไฟล์ StorageWebserviceApplication.java
ของเรา ตรรกะสำหรับการอัปโหลดและดาวน์โหลดไฟล์อยู่ใน StorageService.java
StorageController.java
เป็นตัวควบคุม Rest ซึ่งมีจุดปลาย API ที่ใช้สำหรับการอัปโหลดและดาวน์โหลดไฟล์ นี่คือลำดับชั้นของโครงการ:
เราได้เลือก Gradle เป็นเครื่องมือสร้าง และจะจัดแพคเกจแอปพลิเคชันของเราและเขียนอิมเมจ Docker ต่อไป เราจะพูดถึงไฟล์ Gradle build, ส่วนประกอบบริการ และ Dockerfile
เพื่อให้สามารถใช้ AWS API ได้ เราจำเป็นต้องรวมการพึ่งพาในไฟล์บิลด์ของเราตามที่กำหนดไว้ในเอกสารประกอบของ AWS สำหรับการใช้ Gradle
โดยสรุปแล้ว ส่วนการกำหนดค่าการพึ่งพา AWS ของสคริปต์ Gradle ของเราจะมีลักษณะดังนี้:
buildscript { ... repositories { mavenCentral() } dependencies { ... classpath("io.spring.gradle:dependency-management-plugin:0.5.4.RELEASE") } } .. apply plugin: "io.spring.dependency-management" dependencyManagement { imports { mavenBom ('com.amazonaws:aws-java-sdk-bom:1.10.47') } } dependencies { .. compile ('com.amazonaws:aws-java-sdk-s3') }
ตามที่ระบุไว้ก่อนหน้านี้ เมื่ออัปโหลดไฟล์ไปยัง Amazon S3 เราทำโดยการอัปโหลดไฟล์ไปยังบัคเก็ต S3
ในการเชื่อมต่อกับบัคเก็ต ไคลเอ็นต์ Amazon S3 ของเราต้องมีข้อมูลประจำตัวที่จัดเตรียมไว้ ข้อมูลประจำตัวคือคีย์การเข้าถึงที่เราสร้างไว้ก่อนหน้านี้ เรากำหนด ID คีย์การเข้าถึงและค่าในไฟล์ application.properties
เราได้ตั้งชื่อที่ฝากข้อมูลของเรา toptal-s3-example
ส่วนประกอบบริการหลักของเราตอนนี้มีดังนี้:
@Service public class StorageService { @Value("${aws.accesKeyId}") private String awsAccessKeyId; @Value("${aws.secretKey}") private String awsSecretKey; @Value("${aws.bucketName}") private String awsBucketName; private AWSCredentials credentials; private AmazonS3 s3client;; @PostConstruct public void init(){ credentials = new BasicAWSCredentials(awsAccessKeyId, awsSecretKey); s3client = new AmazonS3Client(credentials); } public void uploadFile(MultipartFile file) throws IOException { File fileForUpload = transformMultipartToFile(file); s3client.putObject(new PutObjectRequest(awsBucketName, file.getOriginalFilename(), fileForUpload)); } public InputStream downloadFile(String amazonFileKey) throws IOException { S3Object fetchFile = s3client.getObject(new GetObjectRequest(awsBucketName, amazonFileKey)); InputStream objectData = fetchFile.getObjectContent(); return objectData; } …
StorageService
อ่านข้อมูลประจำตัวจากไฟล์ application.properties
และใช้เพื่อสร้างอินสแตนซ์อ็อบเจ็กต์ BasicAWSCredentials
และอ็อบเจ็กต์ AmazonS3Client
ในเวลาต่อมา ต่อไปนี้เป็นเรื่องง่ายๆ ในการเรียกใช้ putObject
สำหรับการอัปโหลดไฟล์ และ getObject
สำหรับการดาวน์โหลดไฟล์ บนอ็อบเจ็กต์ไคลเอ็นต์ Amazon S3
เราจะเรียกใช้บริการภายในคอนเทนเนอร์ Docker และระหว่างกระบวนการสร้าง Gradle เราจะสร้างอิมเมจ Docker เราจะทำสิ่งนี้โดยกำหนดค่าไฟล์ build.gradle
เพิ่มเติมดังนี้:
buildscript { ... dependencies { ... classpath('se.transmode.gradle:gradle-docker:1.2') } } ..... apply plugin: 'docker' ... task buildDocker(type: Docker, dependsOn: build) { push = false applicationName = "storageservice" dockerfile = file('src/main/docker/Dockerfile') doFirst { copy { from jar into stageDir } } }
ส่วน Buildscript
และการ apply plugin
นั้นเป็นมาตรฐานที่ค่อนข้างดี นอกจากนี้เรายังได้กำหนดงาน buildDocker
ซึ่งอ่านการกำหนดค่า Docker ที่จัดเก็บไว้ใน src/main/docker/Dockerfile
และคัดลอกไฟล์ JAR ไปยังบิลด์ Docker
Dockerfile มีรายการคำสั่ง Docker แท้ซึ่งเราจะเตรียมอิมเมจของเรา:
FROM frolvlad/alpine-oraclejdk8 ADD storageWebService-0.0.1-SNAPSHOT.jar storageService.jar EXPOSE 8080 CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/storageService.jar"]
ข้อกำหนดเบื้องต้นสำหรับการรันแอปพลิเคชันของเราคือการติดตั้ง Java Virtual Machine (JVM) Docker แสดงรายการรูปภาพที่ติดตั้ง Java และเราจะเลือกรูปภาพที่เล็กที่สุดโดยอิงจาก Alpine Linux ขนาด 5MB ขั้นต่ำ frolvlad/alpine-oraclejdk8
image มีทุกอย่างที่เราต้องการและมีขนาดค่อนข้างเล็ก (เพียง 170 MB)
คำสั่ง FROM
ตั้งค่าอิมเมจที่กล่าวถึงเป็นฐานที่จะสร้างของเราเอง เรา ADD
ไฟล์ JAR ที่สร้างขึ้นไปยังระบบไฟล์คอนเทนเนอร์ภายใต้ชื่อ storageService.jar
ต่อไป เรากำหนดให้คอนเทนเนอร์ Docker ฟังบนพอร์ต 8080
ณ รันไทม์ด้วยคำสั่ง EXPOSE
อย่างไรก็ตาม สิ่งนี้จะไม่เปิดใช้งานการสื่อสารกับ 8080
จากโฮสต์ เมื่ออิมเมจเสร็จสิ้น และเราต้องการเรียกใช้ เราจะต้องเผยแพร่พอร์ตบนคอนเทนเนอร์ด้วยคำสั่งต่อไปนี้ docker run -p 8080:8080 amazonRepository/storageservice
โดยที่ amazonRepository
เป็นที่เก็บที่เราจะกำหนดค่าในภายหลัง กวดวิชา ด้วย CMD
เรากำหนดว่าคำสั่งใดที่จะถูกดำเนินการเมื่อเรารันคอนเทนเนอร์ ค่าในวงเล็บของคำสั่ง CMD
หมายถึงสิ่งต่อไปนี้จะถูกดำเนินการเมื่อเราเรียกใช้คอนเทนเนอร์:
java -Djava.security.egd=file:/dev/./urandom -jar /storageService.jar
จำเป็นต้องใช้ตัวเลือก -Djava.security.egd=file:/dev/./urandom
เพื่อช่วยบรรเทาความล่าช้าของ JVM ในระหว่างการเริ่มต้น หากละเว้น จะทำให้แอปพลิเคชันบูตได้ช้ามาก เนื่องจากกระบวนการสร้างตัวเลขสุ่มที่จำเป็นในระหว่างกระบวนการบูต
สรุปส่วน "การพัฒนาแอปพลิเคชัน" เมื่อทำเช่นนี้ บริการที่เราสร้างขึ้นที่นี่จะเริ่มต้นโดยอัตโนมัติเมื่อเราเรียกใช้คอนเทนเนอร์ Docker ในภายหลัง ดังนั้น มาเริ่มการติดตั้งและกำหนดค่าเครื่องมืออื่นๆ ที่จำเป็นในการตั้งค่ากระบวนการผสานรวมอย่างต่อเนื่องกัน
แอพพลิเคชั่นและการทำงานของระบบ
ก่อนอื่น เราต้องการเซิร์ฟเวอร์ Linux ที่สะอาดเพื่อตั้งค่าเครื่องมือ Jenkins CI โปรดทราบว่าคำแนะนำต่อไปนี้มีไว้สำหรับ Ubuntu 14.04 โดยเฉพาะ โปรดทราบว่าคำแนะนำอาจแตกต่างกันเล็กน้อยสำหรับลีนุกซ์รุ่นอื่นๆ เวอร์ชันของเจนกินส์ที่ใช้คือ 2.7.1 และหน้าจอและคำแนะนำอาจแตกต่างกันเล็กน้อยขึ้นอยู่กับเวอร์ชันของเจนกินส์ที่ใช้
ดังนั้นเราจึงไปที่คอนโซลเซิร์ฟเวอร์ Linux และเริ่มติดตั้งข้อกำหนดเบื้องต้น
ข้อกำหนดเบื้องต้น JDK
เราจำเป็นต้องติดตั้ง JDK ต่อไปนี้เป็นคำแนะนำสำหรับการติดตั้ง JDK8

sudo add-apt-repository ppa:webupd8team/java sudo apt-get install python-software-properties sudo apt-get update sudo apt-get install oracle-java8-installer java -version
ติดตั้ง Docker
เพื่อให้ Jenkins สามารถเรียกใช้งานบิลด์ Docker ได้ เราต้องติดตั้ง docker-engine
ดังนี้:
sudo apt-get install apt-transport-https ca-certificates sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D #create a docker list file sudo vi /etc/apt/sources.list.d/docker.list #add the following entry in the docker.list file (change trusty to #the release you are running on if you are running on different, ie. #xenial, precise...): deb https://apt.dockerproject.org/repo ubuntu-trusty main #save and exit the file sudo apt-get update apt-cache policy docker-engine sudo apt-get install docker-engine
เนื่องจากเราได้ติดตั้งเอ็นจิ้น Docker แล้ว ด้วยคำสั่งต่อไปนี้ เราจะเริ่มอิมเมจ Docker ของ hello-world
เพื่อยืนยันว่า Docker ทำงานอย่างถูกต้อง
sudo docker run hello-world
เอาต์พุตภาพ Hello-world
จะมีลักษณะดังนี้ และด้วยสิ่งนี้ เราสามารถยืนยันได้ว่าเอ็นจิ้นทำงานได้ดี
ติดตั้ง AWS Command Line Interface (CLI)
ต่อไป เราจะติดตั้ง AWS CLI ในภายหลัง ในการกำหนดค่างาน Jenkins เราจะใช้ CLI เพื่อดำเนินการคำสั่งสำหรับการตรวจสอบสิทธิ์ AWS และการพุชอิมเมจ Docker ไปยังรีจิสตรีคอนเทนเนอร์ Amazon EC2
ในการติดตั้ง AWS CLI เราปฏิบัติตามหลักเกณฑ์ที่อธิบายไว้ในรายละเอียดในเอกสารประกอบของ Amazon CLI
จากสองตัวเลือกการติดตั้ง เราจะเลือกการติดตั้งโดยใช้ Pip ซึ่งเป็นระบบจัดการแพ็คเกจที่ใช้สำหรับการติดตั้งและจัดการโปรแกรม Python เราจะติดตั้ง Pip และ AWS CLI โดยเรียกใช้สามคำสั่งต่อไปนี้:
#install Python version 2.7 if it was not already installed during the JDK #prerequisite installation sudo apt-get install python2.7 #install Pip package management for python sudo apt-get install python-pip #install AWS CLI sudo pip install awscli
AWS ECR
ในขั้นสุดท้ายของกระบวนการบิลด์ เราจะพุชอิมเมจ Docker ของเราไปที่รีจิสตรีคอนเทนเนอร์ของ Amazon ในคอนโซลบริการเว็บของ Amazon เราพบ AWS EC2 Container Service
เราเลือกเมนูย่อย Repositories ทางด้านซ้ายและคลิกที่ เริ่มต้น
จากนั้นเราจะนำเสนอด้วยหน้าจอแรกสำหรับการกำหนดค่าที่เก็บที่เราป้อนชื่อที่เก็บและคลิกที่ปุ่ม ขั้นตอนต่อไป
เมื่อคลิกที่ Next Step จะแสดงหน้าจอพร้อมคำแนะนำเกี่ยวกับวิธีการส่งรูปภาพไปยังที่เก็บ
เราจะนำเสนอตัวอย่างวิธีการสร้างและผลักอิมเมจ Docker ไปยังรีจิสตรี แต่เราไม่จำเป็นต้องกังวลเรื่องนี้ในตอนนี้ ด้วยสิ่งนี้ เราได้สร้างที่เก็บ
ติดตั้งและกำหนดค่า Jenkins
ในการติดตั้ง Jenkins เราป้อนคำสั่งต่อไปนี้ในเชลล์:
#Download Jenkins key and pipe it to apt-key tool, apt-key command #add will read from input stream, as defined by „–„. When added #apt will be able to authenticate package to be installed. wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add - #create a sources list for jenkins sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list' #update your local package list sudo apt-get update #install jenkins sudo apt-get install jenkins
เมื่อการติดตั้งเสร็จสิ้น Jenkins จะเริ่มทำงานโดยอัตโนมัติ ตรวจสอบสถานะการบริการด้วยคำสั่งต่อไปนี้:
sudo service jenkins status
Jenkins จะเชื่อมต่อกับที่เก็บ Bitbucket Git และเราจำเป็นต้องติดตั้ง Git เพื่อดำเนินการดังกล่าว
#install Git sudo apt-get install git
เจนกินส์จะเรียกใช้กระบวนการสร้าง Gradle ในระหว่างนั้นจะสร้างอิมเมจ Docker เพื่อให้สามารถทำเช่นนี้ได้ ผู้ใช้ Jenkins จะต้องถูกเพิ่มในกลุ่มผู้ใช้ docker
:
#add Jenkins user to docker user group sudo usermod -aG docker jenkins
ระหว่างกระบวนการสร้าง Jenkins จะพุชอิมเมจ Docker ไปยัง Amazon ECR เพื่อเปิดใช้งานสิ่งนี้ เราต้องกำหนดค่า AWS สำหรับผู้ใช้ Jenkins
อันดับแรก เราต้องเปลี่ยนไปใช้ jenkins
user ในการทำเช่นนั้น เราต้องตั้งรหัสผ่าน
#change Jenkins password sudo passwd jenkins #switch to Jenkins user su – jenkins #configure AWS aws configure
หลังจากป้อนคำสั่ง aws configure
เราจะเริ่มป้อนคีย์การเข้าถึงที่เป็นความลับและ ID คีย์ที่สร้างขึ้น (นี่คือข้อมูลประจำตัวที่เราสร้างขึ้นก่อนหน้านี้ในกระบวนการ) ในกรณีของฉัน ภูมิภาคของบัญชีคือ us-west-2
ดังนั้นฉันจึงป้อนข้อมูลนั้น เรายังตั้งค่ารูปแบบเอาต์พุตเริ่มต้นสำหรับคำสั่ง AWS ให้เป็น JSON
ตอนนี้เราสามารถไปยังการกำหนดค่า Jenkins ผ่านเว็บคอนโซลที่สามารถเข้าถึงได้บนพอร์ต 8080
เมื่อเราเข้าถึง URL เราจะเห็นหน้าจอ เริ่มต้น ต่อไปนี้
ตามที่ระบุไว้บนหน้าจอเราต้องป้อนรหัสผ่าน เมื่อทำสิ่งนี้แล้ว วิซาร์ดการตั้งค่าจะแจ้งให้เราทำดังต่อไปนี้:
- เลือกปลั๊กอินที่จะติดตั้ง - เราจะเลือก ติดตั้งปลั๊กอินที่แนะนำ
- สร้างผู้ดูแลระบบคนแรกโดยป้อนข้อมูลประจำตัวผู้ใช้
เมื่อเสร็จแล้ว ให้คลิก บันทึกและเสร็จสิ้น ด้วยเหตุนี้ เราจึงกำหนดค่าการตั้งค่า Jenkins เสร็จแล้ว
ก่อนที่เราจะเริ่มกำหนดงานบิลด์ เราต้องเพิ่มปลั๊กอินเพิ่มเติมสองสามตัว เราจะไปที่ Manage Jenkins และคลิกที่ Manage plugins ในแท็บ Available อันดับแรก เราจะพบ Bitbucket plugin ทำเครื่องหมายที่ช่อง และคลิก Download and install after restart
จากนั้นคุณจะเห็นบางอย่างเช่นหน้าจอต่อไปนี้
หลังจากติดตั้งปลั๊กอิน เราจะทำซ้ำขั้นตอนสำหรับปลั๊กอินเพิ่มเติมต่อไปนี้ซึ่งจำเป็นสำหรับการตั้งค่างาน:
- ปลั๊กอิน Gradle
- ปลั๊กอินขั้นตอนการสร้างนักเทียบท่า
- ปลั๊กอินสภาพแวดล้อมการสร้างแบบกำหนดเองของ Cloudbees Docker
- ปลั๊กอิน Amazon ECR
ปลั๊กอินขั้นตอนการสร้าง Docker ที่เราใช้จะส่งคำขอไปยัง Docker daemon เพื่อจุดประสงค์นี้ เราจำเป็นต้องเปิดใช้งานซ็อกเก็ต TCP บนพอร์ต 2375 ในการทำเช่นนั้น เราป้อนไฟล์การกำหนดค่า Docker ที่ etc/default/docker
sudo vi /etc/default/docker
ที่นี่เราเพิ่มบรรทัดต่อไปนี้ในการกำหนดค่า:
DOCKER_OPTS='-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock'
เราบันทึกและออกจากไฟล์และรีสตาร์ททั้งบริการ Docker และ Jenkins
sudo service docker restart sudo service jenkins restart
หลังจาก Jenkins รีบูตแล้ว เราไปที่คอนโซล Jenkins และจาก Manage Jenkins เราเลือก Configure System
เราพบส่วนตัว สร้าง Docker และป้อน http://localhost:2375
สำหรับ REST API URL คลิกที่ Apply เพื่อยืนยันการเปลี่ยนแปลง จากนั้นเราคลิก ทดสอบการเชื่อม ต่อเพื่อหวังว่าจะยืนยันว่าทุกอย่างเรียบร้อย
เราบันทึกการกำหนดค่าและดำเนินการกำหนดค่างานของเจนกินส์
การกำหนดค่างาน
เราไปที่หน้าแรกของเจนกินส์และสร้าง รายการใหม่
เราเลือก โครงการ Freestyle และป้อนชื่อโครงการดังที่แสดงบนหน้าจอต่อไปนี้:
เมื่อคลิกที่ OK เราจะเห็นหน้าการกำหนดค่างาน เราต้องการให้โปรเจ็กต์ถูกสร้างขึ้นในแต่ละการกดไปยังที่เก็บ Bitbucket Git ของเรา เพื่อให้บรรลุสิ่งนี้ อันดับแรก เราต้องกำหนดที่เก็บที่เรากำลังเชื่อมต่ออยู่
ขั้นตอนที่ 1: การจัดการซอร์สโค้ด
ภายใต้การจัดการซอร์สโค้ด เราเลือก Git และป้อน URL ของที่เก็บ Bitbucket ของเรา URL มีรูปแบบของ https://bitbucket.org/bitbucketUsername/repositoryName
หลังจากที่เราป้อน URL แล้ว Jenkins จะพยายามทดสอบการเชื่อมต่อโดยอัตโนมัติ เนื่องจากเรายังไม่ได้ป้อนข้อมูลรับรอง ระบบจะแสดงข้อผิดพลาดที่ระบุว่าไม่สามารถเชื่อมต่อได้
เปิดรายการดรอปดาวน์ Add และคลิกที่ Credentials Jenkins provider
เราจะนำเสนอด้วยหน้าจอต่อไปนี้ ซึ่งเราป้อนชื่อผู้ใช้และรหัสผ่านสำหรับบัญชี Bitbucket ของเรา
หลังจากเพิ่มระเบียนข้อมูลประจำตัวใหม่แล้ว เราต้องแน่ใจว่าได้เลือกระเบียนดังกล่าวในรายการข้อมูลประจำตัวแบบเลื่อนลง และการดำเนินการนี้จะเสร็จสิ้นการตั้งค่า การจัดการซอร์สโค้ด
ขั้นตอนที่ 2: สร้างทริกเกอร์
ตรวจสอบ ทริกเกอร์บิลด์จากระยะไกล และกำหนดโทเค็นการตรวจสอบสิทธิ์ อย่าลืมกำหนดโทเค็นแบบสุ่มและปลอดภัย
ขั้นตอนที่ 3: Bitbucket Webhook
Jenkins ได้ให้ URL แก่เราแล้วที่เราจะใช้ใน Bitbucket เราไปที่หน้าที่เก็บ Bitbucket และในเมนูการตั้งค่าให้คลิกที่ Web hooks จากนั้นคลิกที่ Add webhook จะแสดงหน้าจอต่อไปนี้ซึ่งเรากรอกดังนี้:
URL มีโครงสร้างดังนี้: http://JENKINS_URL _HOST:PORT/job/JOB_NAME/build?token=TOKEN
ป้อนค่าด้านบนตามลำดับด้วย Jenkins URL, พอร์ตที่กำลังทำงาน, ชื่อของงานที่คุณสร้าง และโทเค็นที่คุณได้กำหนดไว้ก่อนหน้านี้
หลังจากบันทึก Webhook แล้ว คุณจะได้รับหน้าจอต่อไปนี้ ซึ่งคุณสามารถแก้ไขได้หากจำเป็น หรือดูคำขอที่สร้างขึ้นทุกครั้งที่เรากดรหัสใหม่
ด้วยการกำหนดค่านี้ เว็บฮุคจะถูกทริกเกอร์ในการพุชที่เก็บแต่ละครั้ง โดยไม่คำนึงถึงสาขา ในด้านเจนกินส์ เราสามารถกำหนดได้ว่าการพุชของสาขาใดจะทริกเกอร์บิลด์
เพื่อให้ Bitbucket สามารถพุชรหัสไปยัง Jenkins ได้ เราจำเป็นต้องกำหนดค่าความปลอดภัยทั่วโลกของ Jenkins ใหม่เพื่อให้สามารถเข้าถึงการอ่านแบบไม่ระบุชื่อได้ นอกจากนี้ สำหรับการตั้งค่าของเรา เราต้องปิดใช้งานตัวเลือก Jenkins เริ่มต้น ซึ่งป้องกันการปลอมแปลงคำขอข้ามไซต์ ในการดำเนินการนี้ ให้ไปที่ Manage Jenkins แล้วเลือก Configure global security กาเครื่องหมาย อนุญาตการเข้าถึงแบบอ่านโดยไม่ระบุชื่อ และกาเครื่องหมาย ป้องกันการแสวงหาประโยชน์จากการปลอมแปลงข้ามไซต์ จากนั้นบันทึกการกำหนดค่า
โปรดทราบว่าการดำเนินการนี้ทำขึ้นเพื่อความเรียบง่ายเท่านั้น การตั้งค่าแบบสมบูรณ์เกินความครอบคลุมของบทช่วยสอนนี้ และจะรวมถึงการรักษาความปลอดภัยให้กับเจนกินส์เพิ่มเติมหลังพร็อกซีย้อนกลับ ในการเชื่อมต่อ TLS และการเปิดใช้งานการป้องกัน CSRF
ขั้นตอนที่ 4: Gradle Build
ตอนนี้เราสามารถกลับไปที่งาน Jenkins และกำหนดค่าต่อไปได้ ในส่วนบิลด์ เราเพิ่มขั้นตอนบิลด์: เรียกใช้สคริปต์ gradle
ในแบบฟอร์มนี้ เราป้อนข้อมูลต่อไปนี้:
ตามที่แสดงบนหน้าจอ เราจะใช้ Gradle wrapper ซึ่งเป็นคุณสมบัติ Gradle ที่สะดวกซึ่งไม่ต้องการให้คุณติดตั้ง Gradle บนโฮสต์ ตรวจสอบให้แน่ใจว่าได้ทำเครื่องหมายในช่อง Make gradlew executable
ในงาน เราระบุ build
และ buildDocker
ขั้นตอนที่ 5: ภาพแท็ก Docker
บิลด์ส่วนนี้แท็กอิมเมจ Docker ที่จัดเตรียมไว้ก่อนหน้านี้โดยงาน dockerBuild ของ dockerBuild
สำหรับสิ่งนี้ เราเพิ่มขั้นตอนการสร้างใหม่ให้กับงาน: ดำเนินการคำสั่ง Docker เราเลือกคำสั่ง Tag image และตั้งชื่อรูปภาพ พื้นที่เก็บข้อมูลเป้าหมายที่เราจะพุชรูปภาพ และแท็ก:
ขั้นตอนที่ 6: นักเทียบท่ากดไปที่ Amazon ECR
สุดท้ายนี้ เราต้องกำหนดวิธีการส่งภาพของเราไปยัง Amazon ECR สำหรับสิ่งนี้ เราเพิ่มขั้นตอนการสร้าง เชลล์ Execute ใหม่และตั้งค่าคำสั่งเพื่อรับรองความถูกต้องกับ AWS และพุชอิมเมจไปยัง Amazon ECR:
#region for our account is us-west-2 aws ecr get-login --region us-west-2 | bash #push the previously tagged image docker push 058432294874.dkr.ecr.us-west-2.amazonaws.com/springbootdocker:${BUILD_NUMBER}
ด้วยเหตุนี้ เราจึงเสร็จสิ้นกระบวนการสร้างของเรา หลังจากผลักรหัสใหม่ไปที่ repo งานนี้จะเปิดใช้งาน และเราจะมีการอัปโหลดอิมเมจ Docker ใหม่ไปยังรีจิสทรีของ Docker “โดยอัตโนมัติอย่างน่าอัศจรรย์”
จากนั้นสามารถดึงอิมเมจไปที่ใดก็ได้ที่เราติดตั้ง docker-engine
ไว้ และสามารถเรียกใช้ด้วยคำสั่งต่อไปนี้:
docker run -p 8080:8080 amazonRepository/springbootdocker
คำสั่งนี้จะเริ่มต้นไมโครเซอร์วิส Spring Boot โดยมีปลายทางต่อไปนี้สำหรับการอัปโหลดและดาวน์โหลดไฟล์ของเราไปยังบัคเก็ต S3:
-
http://hostnameURL:8080/api/storage/upload
-
http://hostnameURL:8080/api/storage/download?fileName=xyz
ก้าวต่อไปของ Java และการรวมอย่างต่อเนื่อง
มีหลายสิ่งที่ต้องทำมากขึ้น บทช่วยสอนนี้ครอบคลุมประเด็นมากมาย แต่ฉันคิดว่านี่เป็นเพียงจุดเริ่มต้นสำหรับการเรียนรู้เพิ่มเติม การวาง Jenkins ไว้เบื้องหลังเว็บพร็อกซีเซิร์ฟเวอร์ เช่น Nginx และสร้างการเชื่อมต่อ TLS เป็นเพียงสองตัวอย่างของสิ่งที่สามารถทำได้มากกว่าและน่าจะทำได้
อิมเมจ Docker ของเรามีอยู่ใน Amazon ECR และพร้อมสำหรับการปรับใช้ ตอนนี้เราสามารถนำไปใช้และปรับใช้ได้ด้วยตนเอง อย่างไรก็ตาม ทางออกที่ดีกว่าคือทำให้ระบบอัตโนมัติต่อไป CI เป็นเพียงขั้นตอนแรก และขั้นตอนต่อไปคือ การส่งมอบอย่างต่อเนื่อง ความพร้อมใช้งานสูงเป็นอย่างไร Amazon AWS EC2 มีคุณสมบัติสำหรับการลงทะเบียนคอนเทนเนอร์ในระบบคลาวด์บนสภาพแวดล้อมแบบคลัสเตอร์ซึ่งจำเป็นสำหรับบริการตามการผลิต ตัวอย่างการทำงานที่ดีของการพัฒนากระบวนการจัดส่งแบบต่อเนื่องมีอยู่ในบล็อกโพสต์ของ AWS ต่อไปนี้
บทสรุป
โดยรวมแล้ว เราได้วางกระบวนการพัฒนาซอฟต์แวร์ที่ราบรื่นและสะอาดตา ด้วยการใช้เครื่องมือที่มีอยู่ เราได้สร้างโครงสร้างพื้นฐานที่ช่วยเพิ่มประสิทธิภาพการทำงานของเราให้สูงสุด ตอนนี้ เราไม่ต้องกังวลเกี่ยวกับการกำหนดค่าบริการ Java ซึ่งเป็นบริการเว็บอย่างง่ายที่มีปลายทาง REST เราปล่อยให้แบบแผน Spring Boot ดูแลทุกอย่างและมุ่งเน้นที่ตรรกะของบริการเท่านั้น เราใช้ Jenkins เพื่อสร้างอิมเมจ Docker ใหม่ทุกครั้งที่เราพุชโค้ดของเราไปที่ที่เก็บ Bitbucket Git และในท้ายที่สุด เราได้ตั้งค่าให้คลาวด์รับผิดชอบการจัดเก็บอิมเมจและไฟล์ Docker ของเรา เมื่อเราปรับใช้บริการของเราที่อยู่ภายในอิมเมจ Docker เราจะปราศจากข้อจำกัดใดๆ ของระบบปฏิบัติการ (ตราบใดที่ระบบปฏิบัติการมีการติดตั้ง Docker docker-engine
)