Triển khai ứng dụng lên VM, Nomad và Kubernetes

Chào mọi người! Tên tôi là Pavel Agaletsky. Tôi làm trưởng nhóm trong một nhóm phát triển hệ thống phân phối Lamoda. Năm 2018, tôi đã phát biểu tại hội nghị HighLoad++ và hôm nay tôi muốn trình bày bản ghi lại báo cáo của mình.

Chủ đề của tôi dành riêng cho kinh nghiệm của công ty chúng tôi trong việc triển khai hệ thống và dịch vụ cho các môi trường khác nhau. Bắt đầu từ thời tiền sử, khi chúng tôi triển khai tất cả hệ thống vào các máy chủ ảo thông thường, kết thúc bằng quá trình chuyển đổi dần dần từ Nomad sang triển khai trong Kubernetes. Tôi sẽ cho bạn biết lý do tại sao chúng tôi làm điều đó và chúng tôi gặp phải những vấn đề gì trong quá trình này.

Triển khai ứng dụng lên VM

Hãy bắt đầu với thực tế là 3 năm trước, tất cả hệ thống và dịch vụ của công ty đều được triển khai trên các máy chủ ảo thông thường. Về mặt kỹ thuật, nó được tổ chức theo cách mà tất cả mã cho hệ thống của chúng tôi được lưu trữ và tập hợp bằng các công cụ lắp ráp tự động, sử dụng jenkins. Bằng cách sử dụng Ansible, nó đã được triển khai từ hệ thống kiểm soát phiên bản của chúng tôi sang các máy chủ ảo. Hơn nữa, mỗi hệ thống mà công ty chúng tôi đã triển khai trên ít nhất 2 máy chủ: một ở phần đầu, cái thứ hai ở phần đuôi. Hai hệ thống này hoàn toàn giống nhau về mọi cài đặt, sức mạnh, cấu hình, v.v. Sự khác biệt duy nhất giữa chúng là phần đầu nhận được lưu lượng truy cập của người dùng, trong khi phần đuôi không bao giờ nhận được lưu lượng truy cập của người dùng.

Nó để làm gì?

Khi triển khai các bản phát hành mới của ứng dụng, chúng tôi muốn đảm bảo quá trình triển khai liền mạch, nghĩa là không gây hậu quả đáng chú ý cho người dùng. Điều này đạt được là do bản phát hành được biên dịch tiếp theo sử dụng Ansible đã được triển khai hoàn thiện. Ở đó, những người tham gia triển khai có thể kiểm tra và đảm bảo rằng mọi thứ đều ổn: tất cả các số liệu, phần và ứng dụng đều hoạt động; các tập lệnh cần thiết được đưa ra. Chỉ sau khi họ tin chắc rằng mọi thứ đều ổn thì giao thông mới được chuyển sang. Nó bắt đầu đi đến máy chủ trước đó là tail. Và cái trước đây là phần đầu vẫn không có lưu lượng truy cập của người dùng, trong khi vẫn có phiên bản trước của ứng dụng của chúng tôi trên đó.

Vì vậy, nó rất liền mạch cho người dùng. Bởi vì việc chuyển đổi diễn ra tức thời, vì nó chỉ đơn giản là chuyển đổi bộ cân bằng. Bạn có thể dễ dàng quay lại phiên bản trước bằng cách chuyển bộ cân bằng trở lại. Chúng tôi cũng có thể xác minh rằng ứng dụng có khả năng hoạt động ngay cả trước khi nó nhận được lưu lượng truy cập của người dùng, điều này khá thuận tiện.

Chúng ta đã thấy những lợi thế gì trong tất cả những điều này?

  1. Trước hết là đủ nó chỉ hoạt động. Mọi người đều hiểu sơ đồ triển khai như vậy hoạt động như thế nào vì hầu hết mọi người đều đã từng triển khai lên các máy chủ ảo thông thường.
  2. thế là đủ đáng tin cậy, vì công nghệ triển khai rất đơn giản và đã được thử nghiệm bởi hàng nghìn công ty. Hàng triệu máy chủ được triển khai theo cách này. Thật khó để phá vỡ một cái gì đó.
  3. Và cuối cùng chúng ta có thể có được triển khai nguyên tử. Quá trình triển khai diễn ra đồng thời cho người dùng mà không có giai đoạn chuyển đổi đáng chú ý giữa phiên bản cũ và phiên bản mới.

Nhưng chúng tôi cũng thấy một số thiếu sót trong tất cả những điều này:

  1. Ngoài môi trường sản xuất, môi trường phát triển còn có các môi trường khác. Ví dụ: qa và tiền sản xuất. Vào thời điểm đó chúng tôi có nhiều máy chủ và khoảng 60 dịch vụ. Vì lý do này nó là cần thiết đối với mỗi dịch vụ, hãy duy trì phiên bản mới nhất cho dịch vụ đó máy ảo. Hơn nữa, nếu bạn muốn cập nhật thư viện hoặc cài đặt các phần phụ thuộc mới, bạn cần thực hiện việc này trong mọi môi trường. Bạn cũng cần phải đồng bộ hóa thời gian chuẩn bị triển khai phiên bản mới tiếp theo của ứng dụng với thời gian các nhà phát triển thực hiện các cài đặt môi trường cần thiết. Trong trường hợp này, rất dễ rơi vào tình huống môi trường của chúng ta sẽ có phần khác biệt trong tất cả các môi trường cùng một lúc. Ví dụ: trong môi trường QA sẽ có một số phiên bản của thư viện và trong môi trường sản xuất sẽ có những phiên bản khác nhau, điều này sẽ dẫn đến các vấn đề.
  2. Khó cập nhật các phần phụ thuộc ứng dụng của bạn. Nó không phụ thuộc vào bạn mà phụ thuộc vào đội khác. Cụ thể là từ nhóm devops duy trì máy chủ. Bạn phải giao cho họ nhiệm vụ thích hợp và mô tả điều bạn muốn làm.
  3. Vào thời điểm đó, chúng tôi cũng muốn chia những khối lớn lớn mà chúng tôi có thành các dịch vụ nhỏ riêng biệt, vì chúng tôi hiểu rằng sẽ ngày càng có nhiều khối như vậy. Vào thời điểm đó, chúng tôi đã có hơn 100 máy ảo, đối với mỗi dịch vụ mới, cần phải tạo một máy ảo mới riêng biệt, máy ảo này cũng cần được bảo trì và triển khai. Ngoài ra, bạn không cần một chiếc ô tô mà ít nhất là hai chiếc. Thêm vào tất cả điều này là môi trường QA. Điều này gây ra sự cố và khiến bạn gặp khó khăn hơn trong việc xây dựng và vận hành các hệ thống mới. quá trình phức tạp, tốn kém và kéo dài.

Do đó, chúng tôi quyết định rằng sẽ thuận tiện hơn khi chuyển từ triển khai các máy ảo thông thường sang triển khai các ứng dụng của chúng tôi trong vùng chứa docker. Nếu bạn có docker, bạn cần một hệ thống có thể chạy ứng dụng trong một cụm, vì bạn không thể chỉ nâng một vùng chứa. Thông thường bạn muốn theo dõi xem có bao nhiêu container được nâng lên để chúng tự động nâng lên. Vì lý do này, chúng tôi cần phải chọn một hệ thống điều khiển.

Chúng tôi đã suy nghĩ rất lâu về việc chúng tôi có thể chọn cái nào. Thực tế là vào thời điểm đó, cách triển khai này trên các máy chủ ảo thông thường đã hơi lỗi thời vì chúng không có phiên bản hệ điều hành mới nhất. Tại một số thời điểm, thậm chí còn có FreeBSD, điều này không thuận tiện cho việc hỗ trợ. Chúng tôi hiểu rằng chúng tôi cần chuyển sang docker càng nhanh càng tốt. Các nhà phát triển của chúng tôi đã xem xét trải nghiệm hiện có của họ với các giải pháp khác nhau và chọn một hệ thống như Nomad.

Chuyển sang du mục

Nomad là sản phẩm của HashiCorp. Họ cũng được biết đến với các giải pháp khác:

Triển khai ứng dụng lên VM, Nomad và Kubernetes

"Lãnh sự" là một công cụ để khám phá dịch vụ.

"Địa hình" - một hệ thống quản lý máy chủ cho phép bạn định cấu hình chúng thông qua cấu hình, cái gọi là cơ sở hạ tầng dưới dạng mã.

"Người lang thang" cho phép bạn triển khai các máy ảo cục bộ hoặc trên đám mây thông qua các tệp cấu hình cụ thể.

Nomad vào thời điểm đó dường như là một giải pháp khá đơn giản có thể nhanh chóng chuyển sang mà không cần thay đổi toàn bộ cơ sở hạ tầng. Ngoài ra, nó khá dễ học. Đó là lý do tại sao chúng tôi chọn nó làm hệ thống lọc cho thùng chứa của mình.

Bạn cần những gì để triển khai hệ thống của mình lên Nomad?

  1. Trước hết bạn cần hình ảnh docker ứng dụng của bạn. Bạn cần xây dựng nó và đặt nó vào kho hình ảnh docker. Trong trường hợp của chúng tôi, đây là một tạo tác - một hệ thống cho phép bạn đẩy nhiều loại hiện vật khác nhau vào đó. Nó có thể lưu trữ các kho lưu trữ, hình ảnh docker, gói soạn thảo PHP, gói NPM, v.v.
  2. Cũng cần thiết tập tin cấu hình, điều này sẽ cho Nomad biết bạn muốn triển khai cái gì, ở đâu và với số lượng bao nhiêu.

Khi chúng ta nói về Nomad, nó sử dụng ngôn ngữ HCL làm định dạng tệp thông tin, viết tắt của Ngôn ngữ cấu hình HashiCorp. Đây là tập hợp lớn hơn của Yaml cho phép bạn mô tả dịch vụ của mình theo thuật ngữ Nomad.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Nó cho phép bạn cho biết bạn muốn triển khai bao nhiêu vùng chứa, từ đó hình ảnh nào sẽ chuyển các tham số khác nhau cho chúng trong quá trình triển khai. Do đó, bạn cung cấp tệp này cho Nomad và nó sẽ khởi chạy các vùng chứa vào sản xuất theo tệp đó.

Trong trường hợp của chúng tôi, chúng tôi nhận ra rằng việc chỉ viết các tệp HCL hoàn toàn giống hệt nhau cho mỗi dịch vụ sẽ không thuận tiện lắm vì có rất nhiều dịch vụ và đôi khi bạn muốn cập nhật chúng. Điều xảy ra là một dịch vụ được triển khai không phải trong một trường hợp mà trong nhiều trường hợp khác nhau. Ví dụ: một trong những hệ thống mà chúng tôi đang sản xuất có hơn 100 phiên bản đang được sản xuất. Chúng chạy từ cùng một hình ảnh, nhưng khác nhau về cài đặt cấu hình và tệp cấu hình.

Do đó, chúng tôi quyết định rằng sẽ thuận tiện cho chúng tôi lưu trữ tất cả các tệp cấu hình để triển khai trong một kho lưu trữ chung. Bằng cách này, chúng có thể được nhìn thấy: chúng dễ bảo trì và chúng tôi có thể biết chúng tôi có những hệ thống nào. Nếu cần thiết, bạn cũng có thể dễ dàng cập nhật hoặc thay đổi điều gì đó. Việc thêm một hệ thống mới cũng không khó - bạn chỉ cần tạo một tệp cấu hình bên trong thư mục mới. Bên trong nó là các tệp sau: service.hcl, chứa mô tả về dịch vụ của chúng tôi và một số tệp env cho phép chính dịch vụ này, đang được triển khai trong sản xuất, được định cấu hình.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Tuy nhiên, một số hệ thống của chúng tôi được triển khai trong sản xuất không phải ở một bản mà thành nhiều bản cùng một lúc. Do đó, chúng tôi quyết định rằng sẽ thuận tiện cho chúng tôi khi lưu trữ không phải các cấu hình ở dạng thuần túy mà ở dạng khuôn mẫu của chúng. Và chúng tôi đã chọn Jinja 2. Ở định dạng này, chúng tôi lưu trữ cả cấu hình của chính dịch vụ và các tệp env cần thiết cho dịch vụ đó.

Ngoài ra, chúng tôi đã đặt trong kho lưu trữ một tập lệnh triển khai chung cho tất cả các dự án, cho phép bạn khởi chạy và triển khai dịch vụ của mình vào sản xuất, vào môi trường mong muốn, vào mục tiêu mong muốn. Trong trường hợp khi chúng tôi biến cấu hình HCL của mình thành một mẫu, thì tệp HCL, trước đây là cấu hình Nomad thông thường, trong trường hợp này bắt đầu trông hơi khác một chút.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Nghĩa là, chúng tôi đã thay thế một số biến vị trí cấu hình bằng các phần chèn biến được lấy từ tệp env hoặc các nguồn khác. Ngoài ra, chúng tôi có cơ hội thu thập các tệp HCL một cách linh hoạt, nghĩa là chúng tôi không chỉ có thể sử dụng các phép chèn biến thông thường. Vì jinja hỗ trợ các vòng lặp và điều kiện nên bạn cũng có thể tạo các tệp cấu hình ở đó, các tệp này sẽ thay đổi tùy thuộc vào chính xác nơi bạn triển khai ứng dụng của mình.

Ví dụ: bạn muốn triển khai dịch vụ của mình ở giai đoạn tiền sản xuất và sản xuất. Giả sử trong giai đoạn tiền sản xuất, bạn không muốn chạy tập lệnh cron mà chỉ muốn xem dịch vụ trên một miền riêng để đảm bảo nó hoạt động. Đối với bất kỳ ai triển khai dịch vụ, quy trình này trông rất đơn giản và minh bạch. Tất cả những gì bạn cần làm là thực thi tệp triển khai.sh, chỉ định dịch vụ nào bạn muốn triển khai và mục tiêu nào. Ví dụ: bạn muốn triển khai một hệ thống nào đó tới Nga, Belarus hoặc Kazakhstan. Để thực hiện việc này, chỉ cần thay đổi một trong các tham số và bạn sẽ có tệp cấu hình chính xác.

Khi dịch vụ Nomad đã được triển khai cho cụm của bạn, nó trông như thế này.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Đầu tiên, bạn cần một số loại bộ cân bằng bên ngoài, nó sẽ nhận tất cả lưu lượng truy cập của người dùng. Nó sẽ làm việc cùng với Lãnh sự và tìm ra từ đó, trên nút nào, tại địa chỉ IP nào mà một dịch vụ cụ thể được đặt tương ứng với một tên miền cụ thể. Các dịch vụ trong Lãnh sự đến từ chính Nomad. Vì đây là những sản phẩm của cùng một công ty nên chúng khá liên quan với nhau. Chúng ta có thể nói rằng Nomad ngay lập tức có thể đăng ký tất cả các dịch vụ được triển khai bên trong Consul.

Sau khi bộ cân bằng tải giao diện người dùng của bạn biết dịch vụ nào sẽ gửi lưu lượng truy cập đến, nó sẽ chuyển tiếp lưu lượng đó đến vùng chứa thích hợp hoặc nhiều vùng chứa phù hợp với ứng dụng của bạn. Đương nhiên, cũng cần phải nghĩ đến sự an toàn. Mặc dù tất cả các dịch vụ đều chạy trên cùng một máy ảo trong các vùng chứa, nhưng điều này thường yêu cầu ngăn chặn quyền truy cập miễn phí từ bất kỳ dịch vụ nào đến bất kỳ dịch vụ nào khác. Chúng tôi đạt được điều này thông qua phân khúc. Mỗi dịch vụ được khởi chạy trong mạng ảo riêng, trên đó quy định các quy tắc định tuyến và quy tắc cho phép/từ chối quyền truy cập vào các hệ thống và dịch vụ khác. Chúng có thể được đặt cả bên trong cụm này và bên ngoài nó. Ví dụ: nếu bạn muốn ngăn một dịch vụ kết nối với cơ sở dữ liệu cụ thể, điều này có thể được thực hiện thông qua phân đoạn cấp độ mạng. Nghĩa là, thậm chí do nhầm lẫn, bạn không thể vô tình kết nối từ môi trường thử nghiệm với cơ sở dữ liệu sản xuất của mình.

Quá trình chuyển đổi đã tiêu tốn của chúng tôi bao nhiêu về mặt nguồn nhân lực?

Quá trình chuyển đổi toàn bộ công ty sang Nomad mất khoảng 5-6 tháng. Chúng tôi di chuyển theo từng dịch vụ nhưng với tốc độ khá nhanh. Mỗi nhóm phải tạo các thùng chứa riêng cho các dịch vụ.

Chúng tôi đã áp dụng cách tiếp cận sao cho mỗi nhóm chịu trách nhiệm về hình ảnh docker của hệ thống của họ một cách độc lập. DevOps cung cấp cơ sở hạ tầng chung cần thiết cho việc triển khai, tức là hỗ trợ cho chính cụm đó, hỗ trợ cho hệ thống CI, v.v. Và vào thời điểm đó, chúng tôi đã có hơn 60 hệ thống được chuyển đến Nomad, tổng cộng khoảng 2 nghìn container.

Devops chịu trách nhiệm về cơ sở hạ tầng chung của mọi thứ liên quan đến triển khai và máy chủ. Và lần lượt, mỗi nhóm phát triển chịu trách nhiệm triển khai các vùng chứa cho hệ thống cụ thể của mình, vì chính nhóm đó biết những gì họ thường cần trong một vùng chứa cụ thể.

Lý do từ bỏ Nomad

Chúng tôi đã nhận được lợi ích gì khi chuyển sang triển khai bằng Nomad và docker, cùng những thứ khác?

  1. Chúng tôi cung cấp các điều kiện bình đẳng cho mọi môi trường. Trong quá trình phát triển, môi trường QA, tiền sản xuất, sản xuất, các hình ảnh vùng chứa giống nhau được sử dụng, có cùng sự phụ thuộc. Theo đó, bạn hầu như không có khả năng những gì sẽ xuất hiện trong sản xuất không phải là những gì bạn đã thử nghiệm trước đó tại địa phương hoặc trong môi trường thử nghiệm của mình.
  2. Chúng tôi cũng thấy rằng thế là đủ dễ dàng thêm một dịch vụ mới. Từ quan điểm triển khai, mọi hệ thống mới đều được khởi chạy rất đơn giản. Chỉ cần đi tới kho lưu trữ cấu hình, thêm một cấu hình khác cho hệ thống của bạn ở đó và bạn đã hoàn tất. Bạn có thể triển khai hệ thống của mình vào sản xuất mà không cần bất kỳ nỗ lực bổ sung nào từ nhà phát triển.
  3. tất cả tập tin cấu hình trong một kho lưu trữ chung hóa ra là đang được xem xét. Vào thời điểm chúng tôi triển khai hệ thống của mình bằng máy chủ ảo, chúng tôi đã sử dụng Ansible, trong đó các cấu hình nằm trong cùng một kho lưu trữ. Tuy nhiên, đối với hầu hết các nhà phát triển, việc này khó thực hiện hơn một chút. Ở đây, khối lượng cấu hình và mã mà bạn cần thêm để triển khai dịch vụ đã trở nên nhỏ hơn nhiều. Ngoài ra, các nhà phát triển rất dễ dàng sửa hoặc thay đổi nó. Ví dụ: trong trường hợp chuyển đổi sang phiên bản mới của Nomad, họ có thể lấy và cập nhật hàng loạt tất cả các tệp vận hành nằm ở cùng một nơi.

Nhưng chúng tôi cũng gặp phải một số nhược điểm:

Hoá ra là chúng tôi không thể đạt được việc triển khai liền mạch trong trường hợp của Nomad. Khi tung ra các container trong các điều kiện khác nhau, nó có thể đang chạy và Nomad coi đó là một container sẵn sàng tiếp nhận lưu lượng truy cập. Điều này xảy ra trước khi ứng dụng bên trong nó có cơ hội khởi chạy. Vì lý do này, hệ thống bắt đầu xuất hiện 500 lỗi trong một khoảng thời gian ngắn do lưu lượng truy cập bắt đầu đi đến một container chưa sẵn sàng tiếp nhận.

Chúng tôi gặp phải một số bởi các bãi lầy. Lỗi quan trọng nhất là Nomad không xử lý tốt một cụm lớn nếu bạn có nhiều hệ thống và vùng chứa. Khi bạn muốn lấy một trong các máy chủ có trong cụm Nomad ra để bảo trì, khả năng khá cao là cụm đó sẽ hoạt động không tốt và sẽ tan rã. Ví dụ: một số vùng chứa có thể rơi xuống và không nổi lên - điều này sẽ khiến bạn phải trả giá rất đắt về sau nếu tất cả hệ thống sản xuất của bạn nằm trong một cụm do Nomad quản lý.

Vì vậy, chúng tôi quyết định nghĩ xem nên đi đâu tiếp theo. Vào thời điểm đó, chúng tôi nhận thức rõ hơn nhiều về những gì chúng tôi muốn đạt được. Cụ thể: chúng tôi muốn độ tin cậy, nhiều chức năng hơn Nomad cung cấp và một hệ thống hoàn thiện hơn, ổn định hơn.

Về vấn đề này, sự lựa chọn của chúng tôi rơi vào Kubernetes vì ​​đây là nền tảng phổ biến nhất để khởi chạy các cụm. Đặc biệt là kích thước và số lượng container của chúng tôi đủ lớn. Với những mục đích như vậy, Kubernetes dường như là hệ thống phù hợp nhất mà chúng tôi có thể xem xét.

Chuyển sang Kubernetes

Tôi sẽ cho bạn biết một chút về các khái niệm cơ bản của Kubernetes và chúng khác với Nomad như thế nào.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Trước hết, khái niệm cơ bản nhất trong Kubernetes là khái niệm pod. Pod là một nhóm gồm một hoặc nhiều container luôn chạy cùng nhau. Và chúng luôn hoạt động như thể trên một máy ảo. Họ có thể truy cập lẫn nhau thông qua IP 127.0.0.1 trên các cổng khác nhau.

Giả sử rằng bạn có một ứng dụng PHP bao gồm nginx và php-fpm - sơ đồ cổ điển. Rất có thể, bạn sẽ muốn luôn luôn giữ cả hai thùng chứa nginx và php-fpm. Kubernetes cho phép bạn đạt được điều này bằng cách mô tả chúng như một nhóm chung. Đây chính xác là những gì chúng tôi không thể có được với Nomad.

Khái niệm thứ hai là triển khai. Thực tế là bản thân cái kén là một thứ phù du, nó bắt đầu và biến mất. Bạn muốn loại bỏ tất cả các vùng chứa trước đó rồi khởi chạy các phiên bản mới cùng một lúc hay bạn muốn triển khai chúng dần dần? Đây là quá trình mà khái niệm triển khai chịu trách nhiệm. Nó mô tả cách bạn triển khai nhóm của mình, số lượng và cách cập nhật chúng.

Khái niệm thứ ba là dịch vụ. Dịch vụ của bạn thực chất là hệ thống của bạn, hệ thống này nhận một số lưu lượng truy cập và sau đó chuyển tiếp nó đến một hoặc nhiều nhóm tương ứng với dịch vụ của bạn. Nghĩa là, nó cho phép bạn nói rằng tất cả lưu lượng truy cập đến dịch vụ đó và dịch vụ đó có tên như vậy phải được gửi đến các nhóm cụ thể này. Và đồng thời nó cung cấp cho bạn khả năng cân bằng lưu lượng. Nghĩa là, bạn có thể khởi chạy hai nhóm ứng dụng của mình và tất cả lưu lượng truy cập đến sẽ được cân bằng đồng đều giữa các nhóm liên quan đến dịch vụ này.

Và khái niệm cơ bản thứ tư là Sự đi vào. Đây là một dịch vụ chạy trên cụm Kubernetes. Nó hoạt động như một bộ cân bằng tải bên ngoài đảm nhận tất cả các yêu cầu. Bằng cách sử dụng API Kubernetes, Ingress có thể xác định nơi sẽ gửi những yêu cầu này. Hơn nữa, anh ấy thực hiện việc này rất linh hoạt. Bạn có thể nói rằng tất cả các yêu cầu tới máy chủ này và URL tương tự đều được gửi đến dịch vụ này. Và những yêu cầu đến máy chủ này và tới một URL khác sẽ được gửi đến một dịch vụ khác.

Điều thú vị nhất theo quan điểm của người phát triển ứng dụng là bạn có thể tự mình quản lý tất cả. Bằng cách đặt cấu hình Ingress, bạn có thể gửi tất cả lưu lượng truy cập đến API đó và API đó tới các vùng chứa riêng biệt được viết, chẳng hạn như trong Go. Nhưng lưu lượng truy cập này đến cùng một tên miền nhưng đến một URL khác, phải được gửi đến các vùng chứa được viết bằng PHP, nơi có nhiều logic nhưng chúng không nhanh lắm.

Nếu so sánh tất cả các khái niệm này với Nomad, chúng ta có thể nói rằng ba khái niệm đầu tiên đều là Dịch vụ. Và khái niệm cuối cùng không có trong chính Nomad. Chúng tôi đã sử dụng bộ cân bằng bên ngoài vì nó: nó có thể là haproxy, nginx, nginx+, v.v. Trong trường hợp hình lập phương, bạn không cần phải giới thiệu riêng khái niệm bổ sung này. Tuy nhiên, nếu bạn nhìn vào Ingress trong nội bộ, thì đó là nginx, haproxy hoặc traefik, nhưng được tích hợp sẵn trong Kubernetes.

Trên thực tế, tất cả các khái niệm tôi mô tả đều là tài nguyên tồn tại trong cụm Kubernetes. Để mô tả chúng trong khối, định dạng yaml được sử dụng, định dạng này dễ đọc và quen thuộc hơn các tệp HCL trong trường hợp của Nomad. Nhưng về mặt cấu trúc, chúng mô tả điều tương tự trong trường hợp pod chẳng hạn. Họ nói - Tôi muốn triển khai các nhóm như vậy và các nhóm như vậy ở đó, với những hình ảnh như vậy và như vậy, với số lượng như vậy.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Ngoài ra, chúng tôi nhận ra rằng chúng tôi không muốn tạo từng tài nguyên riêng lẻ bằng tay: triển khai, dịch vụ, Ingress, v.v. Thay vào đó, chúng tôi muốn mô tả từng hệ thống của mình theo thuật ngữ Kubernetes trong quá trình triển khai để không phải tạo lại thủ công tất cả các phần phụ thuộc tài nguyên cần thiết theo đúng thứ tự. Helm được chọn là hệ thống cho phép chúng tôi thực hiện điều này.

Các khái niệm cơ bản trong Helm

Mũ bảo hiểm là quản lý gói dành cho Kubernetes. Nó rất giống với cách hoạt động của trình quản lý gói trong ngôn ngữ lập trình. Chúng cho phép bạn lưu trữ một dịch vụ bao gồm, chẳng hạn như triển khai nginx, triển khai php-fpm, cấu hình cho Ingress, configmaps (đây là một thực thể cho phép bạn đặt env và các tham số khác cho hệ thống của bạn) ở dạng như vậy- gọi là biểu đồ. Đồng thời Helm chạy trên Kubernetes. Nghĩa là, đây không phải là một loại hệ thống đứng ngoài cuộc mà chỉ là một dịch vụ khác được triển khai bên trong khối. Bạn tương tác với nó thông qua API của nó thông qua lệnh console. Sự tiện lợi và hay ho của nó là ngay cả khi helm bị hỏng hoặc bạn loại bỏ nó khỏi cụm, các dịch vụ của bạn sẽ không biến mất, vì helm về cơ bản chỉ dùng để khởi động hệ thống. Bản thân Kubernetes sau đó chịu trách nhiệm về hiệu suất và trạng thái của dịch vụ.

Chúng tôi cũng nhận ra rằng sự tạo khuôn mẫu, điều mà trước đây chúng tôi buộc phải tự thực hiện bằng cách đưa jinja vào cấu hình của mình, là một trong những tính năng chính của helm. Tất cả các cấu hình mà bạn tạo cho hệ thống của mình đều được lưu trữ trong helm dưới dạng mẫu, hơi giống với jinja, nhưng trên thực tế, sử dụng khuôn mẫu của ngôn ngữ Go, trong đó helm được viết, như Kubernetes.

Helm bổ sung thêm một số khái niệm cho chúng ta.

Biểu đồ - đây là mô tả về dịch vụ của bạn. Trong các trình quản lý gói khác, nó sẽ được gọi là gói, gói hoặc cái gì đó tương tự. Ở đây nó được gọi là biểu đồ.

Các giá trị là các biến bạn muốn sử dụng để xây dựng cấu hình của mình từ các mẫu.

Phát hành. Mỗi lần một dịch vụ được triển khai bằng helm sẽ nhận được phiên bản phát hành gia tăng. Helm nhớ cấu hình dịch vụ trong bản phát hành trước, bản phát hành trước đó, v.v. Do đó, nếu bạn cần khôi phục, chỉ cần chạy lệnh gọi lại helm, trỏ nó đến phiên bản phát hành trước đó. Ngay cả khi cấu hình tương ứng trong kho lưu trữ của bạn không có sẵn tại thời điểm khôi phục, helm vẫn sẽ nhớ cấu hình đó là gì và sẽ khôi phục hệ thống của bạn về trạng thái như trong bản phát hành trước.

Trong trường hợp chúng ta sử dụng helm, các cấu hình thông thường cho Kubernetes cũng biến thành các mẫu trong đó có thể sử dụng các biến, hàm và áp dụng các câu lệnh điều kiện. Bằng cách này, bạn có thể thu thập cấu hình dịch vụ của mình tùy thuộc vào môi trường.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Trong thực tế, chúng tôi quyết định làm mọi thứ hơi khác so với những gì chúng tôi đã làm với Nomad. Nếu trong Nomad cả cấu hình triển khai và n-biến cần thiết để triển khai dịch vụ của chúng tôi đều được lưu trữ trong một kho lưu trữ thì ở đây chúng tôi quyết định chia chúng thành hai kho lưu trữ riêng biệt. Kho lưu trữ “triển khai” chỉ lưu trữ n biến cần thiết cho việc triển khai và kho lưu trữ “trợ giúp” lưu trữ cấu hình hoặc biểu đồ.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Điều này đã cho chúng ta điều gì?

Mặc dù thực tế là chúng tôi không lưu trữ bất kỳ dữ liệu thực sự nhạy cảm nào trong tệp cấu hình. Ví dụ: mật khẩu vào cơ sở dữ liệu. Chúng được lưu trữ dưới dạng bí mật trong Kubernetes, tuy nhiên, vẫn có một số thứ ở đó mà chúng tôi không muốn cấp cho mọi người quyền truy cập. Do đó, quyền truy cập vào kho lưu trữ “triển khai” bị hạn chế hơn và kho lưu trữ “trợ giúp” chỉ chứa mô tả về dịch vụ. Vì lý do này, nhiều người có thể truy cập nó một cách an toàn.

Vì chúng tôi không chỉ có môi trường sản xuất mà còn có các môi trường khác, nhờ sự tách biệt này, chúng tôi có thể sử dụng lại sơ đồ chỉ đạo của mình để triển khai các dịch vụ không chỉ cho sản xuất mà còn cho môi trường QA chẳng hạn. Thậm chí để triển khai chúng cục bộ bằng cách sử dụng minikube - đây là thứ để chạy Kubernetes cục bộ.

Bên trong mỗi kho lưu trữ, chúng tôi chia thành các thư mục riêng biệt cho từng dịch vụ. Nghĩa là, bên trong mỗi thư mục đều có các mẫu liên quan đến biểu đồ tương ứng và mô tả các tài nguyên cần triển khai để chạy hệ thống của chúng ta. Chúng tôi chỉ để lại env trong kho “triển khai”. Trong trường hợp này, chúng tôi đã không sử dụng khuôn mẫu bằng jinja, vì bản thân helm cung cấp khuôn mẫu ngay lập tức - đây là một trong những chức năng chính của nó.

Chúng tôi đã để lại một tập lệnh triển khai - triển khai.sh, giúp đơn giản hóa và tiêu chuẩn hóa quá trình khởi chạy triển khai bằng cách sử dụng helm. Vì vậy, đối với bất kỳ ai muốn triển khai, giao diện triển khai trông giống hệt như khi triển khai qua Nomad. Cùng một triển khai.sh, tên dịch vụ của bạn và nơi bạn muốn triển khai dịch vụ đó. Điều này khiến bánh lái khởi động bên trong. Đến lượt nó, nó thu thập các cấu hình từ các mẫu, chèn các tệp giá trị cần thiết vào chúng, sau đó triển khai chúng, khởi chạy chúng vào Kubernetes.

Những phát hiện

Dịch vụ Kubernetes có vẻ phức tạp hơn Nomad.

Triển khai ứng dụng lên VM, Nomad và Kubernetes

Ở đây lưu lượng truy cập đi đến Ingress. Đây chỉ là bộ điều khiển phía trước, tiếp nhận tất cả các yêu cầu và sau đó gửi chúng đến các dịch vụ tương ứng với dữ liệu yêu cầu. Nó xác định chúng dựa trên các cấu hình nằm trong phần mô tả ứng dụng của bạn do nhà phát triển tự thiết lập. Dịch vụ gửi yêu cầu đến các nhóm của nó, tức là các vùng chứa cụ thể, cân bằng lưu lượng đến giữa tất cả các vùng chứa thuộc dịch vụ này. Và tất nhiên, chúng ta không nên quên rằng chúng ta không nên đi đâu xa khỏi vấn đề bảo mật ở cấp độ mạng. Do đó, phân đoạn hoạt động trong cụm Kubernetes, dựa trên việc gắn thẻ. Tất cả các dịch vụ đều có một số thẻ nhất định mà quyền truy cập của dịch vụ vào một số tài nguyên bên ngoài/nội bộ nhất định bên trong hoặc bên ngoài cụm được liên kết.

Khi thực hiện quá trình chuyển đổi, chúng tôi thấy rằng Kubernetes có tất cả các khả năng của Nomad mà trước đây chúng tôi đã sử dụng và cũng đã bổ sung thêm rất nhiều tính năng mới. Nó có thể được mở rộng thông qua các plugin và trên thực tế là thông qua các loại tài nguyên tùy chỉnh. Nghĩa là, bạn không chỉ có cơ hội sử dụng thứ gì đó đi kèm với Kubernetes mà còn có cơ hội tạo tài nguyên và dịch vụ của riêng bạn để đọc tài nguyên của bạn. Điều này cung cấp cho bạn các tùy chọn bổ sung để mở rộng hệ thống của mình mà không cần phải cài đặt lại Kubernetes cũng như không cần sửa đổi.

Một ví dụ về việc sử dụng như vậy là Prometheus, chạy bên trong cụm Kubernetes của chúng tôi. Để nó bắt đầu thu thập số liệu từ một dịch vụ cụ thể, chúng tôi cần thêm một loại tài nguyên bổ sung, cái gọi là trình giám sát dịch vụ, vào mô tả dịch vụ. Prometheus, do có thể đọc loại tài nguyên tùy chỉnh khi khởi chạy trong Kubernetes, nên sẽ tự động bắt đầu thu thập số liệu từ hệ thống mới. Nó khá thuận tiện.

Lần triển khai đầu tiên chúng tôi thực hiện cho Kubernetes là vào tháng 2018 năm 3000. Và trong thời gian này chúng tôi chưa bao giờ gặp phải bất kỳ vấn đề nào với nó. Nó hoạt động khá ổn định mà không có lỗi đáng kể. Ngoài ra, chúng tôi có thể mở rộng nó hơn nữa. Ngày nay, chúng tôi có đủ khả năng mà nó có và chúng tôi thực sự thích tốc độ phát triển của Kubernetes. Hiện tại, có hơn XNUMX container trong Kubernetes. Cụm chiếm một số Nút. Đồng thời, nó có thể sử dụng được, ổn định và rất dễ kiểm soát.

Nguồn: www.habr.com

Thêm một lời nhận xét