Terraformer - Cơ sở hạ tầng để mã hóa

Terraformer - Cơ sở hạ tầng để mã hóa
Tôi muốn kể cho bạn nghe về công cụ CLI mới mà tôi đã viết để giải quyết một vấn đề cũ.

vấn đề

Terraform từ lâu đã trở thành một tiêu chuẩn trong cộng đồng Devops/Cloud/IT. Điều này rất thuận tiện và hữu ích cho việc xử lý cơ sở hạ tầng dưới dạng mã. Có rất nhiều thú vui trong Terraform cũng như nhiều nĩa, dao và cào sắc bén.
Với Terraform, rất thuận tiện để tạo những thứ mới và sau đó quản lý, thay đổi hoặc xóa chúng. Những người có cơ sở hạ tầng khổng lồ trên đám mây và không được tạo thông qua Terraform nên làm gì? Viết lại và tạo lại toàn bộ đám mây bằng cách nào đó tốn kém và không an toàn.
Tôi đã gặp phải vấn đề này ở 2 công việc, ví dụ đơn giản nhất là khi bạn muốn mọi thứ ở dạng Git ở dạng tệp địa hình, nhưng bạn có hơn 250 nhóm và việc viết chúng bằng tay là rất nhiều.
vấn đề kể từ năm 2014 tại terrafom đã đóng cửa vào năm 2016 với hy vọng sẽ có hàng nhập khẩu.

Nói chung mọi thứ đều như trong hình chỉ từ phải qua trái thôi

Cảnh báo: Tác giả không sống ở Nga nửa đời và viết rất ít bằng tiếng Nga. Cẩn thận với lỗi chính tả.

Giải pháp

1. Có những giải pháp làm sẵn và cũ cho AWS địa hình hóa. Khi tôi cố gắng vận chuyển hơn 250 thùng của mình qua đó, tôi nhận ra rằng mọi thứ ở đó thật tồi tệ. AWS từ lâu đã giới thiệu rất nhiều tùy chọn mới, nhưng địa khai hóa không biết về chúng và nói chung là ruby mẫu có vẻ thưa thớt. Sau 2 giờ chiều tôi đã gửi Yêu cầu kéo để bổ sung thêm nhiều tính năng hơn và nhận ra rằng giải pháp như vậy không phù hợp chút nào.
Cách thức hoạt động của địa khai hóa: nó lấy dữ liệu từ AWS SDK và tạo tf và tfstate thông qua một mẫu.
Có 3 vấn đề ở đây:
1. Sẽ luôn có độ trễ trong quá trình cập nhật
2. tập tin tf đôi khi bị hỏng
3. tfstate được thu thập riêng biệt với tf và không phải lúc nào cũng hội tụ
Nói chung khó có được một kết quả mà `terraform plan` nói là không có thay đổi

2. `terraform import` là một lệnh tích hợp trong terraform. Làm thế nào nó hoạt động?
Bạn viết một tệp TF trống có tên và loại tài nguyên, sau đó chạy `terraform import` và chuyển ID tài nguyên. terraform liên hệ với nhà cung cấp, nhận dữ liệu và tạo tệp tfstate.
Có 3 vấn đề ở đây:
1. Chúng tôi chỉ nhận được một tệp tfstate và tf trống, bạn cần viết thủ công hoặc chuyển đổi nó từ tfstate
2. Mỗi lần chỉ có thể làm việc với một tài nguyên và không hỗ trợ tất cả các tài nguyên. Và tôi nên làm gì lại với hơn 250 thùng?
3. Bạn cần biết ID của tài nguyên - nghĩa là bạn cần bọc nó trong mã lấy danh sách tài nguyên
Nói chung, kết quả là một phần và không có quy mô tốt

Quyết định của tôi

Yêu cầu:
1. Khả năng tạo tệp tf và tfstate cho tài nguyên. Ví dụ: tải xuống tất cả các nhóm/nhóm bảo mật/cân bằng tải và `kế hoạch địa hình` trả về rằng không có thay đổi nào
2. Bạn cần 2 đám mây GCP + AWS
3. Giải pháp toàn cầu, dễ dàng cập nhật mọi lúc và không lãng phí thời gian cho từng tài nguyên trong 3 ngày làm việc
4. Biến nó thành Nguồn mở - mọi người đều có cùng một vấn đề

Ngôn ngữ Go là lý do tại sao tôi yêu thích nó và nó có một thư viện để tạo các tệp HCL được sử dụng ở terraform + rất nhiều mã ở terraform có thể hữu ích

Con đường

Lần thử đầu tiên
Tôi bắt đầu với một phiên bản đơn giản. Liên hệ với đám mây thông qua SDK để có tài nguyên được yêu cầu và chuyển đổi nó thành các trường cho địa hình. Nỗ lực này đã chết ngay lập tức đối với nhóm bảo mật vì tôi không thích 1.5 ngày chỉ chuyển đổi nhóm bảo mật (và có rất nhiều tài nguyên). Trong một thời gian dài và sau đó các trường có thể được thay đổi/thêm

Lần thử thứ hai
Dựa trên ý tưởng được mô tả đây. Chỉ cần lấy và chuyển đổi tfstate sang tf. Tất cả dữ liệu đều ở đó và các trường đều giống nhau. Làm cách nào để có được tfstate đầy đủ cho nhiều tài nguyên?? Đây là lúc lệnh `terraform Refresh` ra tay giải cứu. terraform lấy tất cả tài nguyên trong tfstate và bằng ID, lấy dữ liệu trên chúng và ghi mọi thứ vào tfstate. Nghĩa là, tạo một tfstate trống chỉ có tên và ID, chạy `terraform Refresh` và sau đó chúng ta nhận được các tfstate đầy đủ. Hoan hô!
Bây giờ chúng ta hãy thực hiện nội dung khiêu dâm đệ quy bằng cách viết một trình chuyển đổi từ tfstate sang tf. Đối với những người chưa bao giờ đọc tfstate, nó là JSON, nhưng đặc biệt.
Đây là thuộc tính phần quan trọng của nó

 "attributes": {
                            "id": "default/backend-logging-load-deployment",
                            "metadata.#": "1",
                            "metadata.0.annotations.%": "0",
                            "metadata.0.generate_name": "",
                            "metadata.0.generation": "24",
                            "metadata.0.labels.%": "1",
                            "metadata.0.labels.app": "backend-logging",
                            "metadata.0.name": "backend-logging-load-deployment",
                            "metadata.0.namespace": "default",
                            "metadata.0.resource_version": "109317427",
                            "metadata.0.self_link": "/apis/apps/v1/namespaces/default/deployments/backend-logging-load-deployment",
                            "metadata.0.uid": "300ecda1-4138-11e9-9d5d-42010a8400b5",
                            "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",

Có:
1. id - chuỗi
2. siêu dữ liệu - một mảng có kích thước 1 và trong đó là một đối tượng có các trường được mô tả bên dưới
3. spec - hàm băm có kích thước 1 và khóa, giá trị trong đó
Nói tóm lại, một định dạng thú vị, mọi thứ có thể sâu sắc ở nhiều cấp độ

                   "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",
                            "spec.0.selector.0.match_expressions.#": "0",
                            "spec.0.selector.0.match_labels.%": "1",
                            "spec.0.selector.0.match_labels.app": "backend-logging-load",
                            "spec.0.strategy.#": "0",
                            "spec.0.template.#": "1",
                            "spec.0.template.0.metadata.#": "1",
                            "spec.0.template.0.metadata.0.annotations.%": "0",
                            "spec.0.template.0.metadata.0.generate_name": "",
                            "spec.0.template.0.metadata.0.generation": "0",
                            "spec.0.template.0.metadata.0.labels.%": "1",
                            "spec.0.template.0.metadata.0.labels.app": "backend-logging-load",
                            "spec.0.template.0.metadata.0.name": "",
                            "spec.0.template.0.metadata.0.namespace": "",
                            "spec.0.template.0.metadata.0.resource_version": "",
                            "spec.0.template.0.metadata.0.self_link": "",
                            "spec.0.template.0.metadata.0.uid": "",
                            "spec.0.template.0.spec.#": "1",
                            "spec.0.template.0.spec.0.active_deadline_seconds": "0",
                            "spec.0.template.0.spec.0.container.#": "1",
                            "spec.0.template.0.spec.0.container.0.args.#": "3",

Nói chung, nếu ai đó muốn giải quyết vấn đề lập trình cho một cuộc phỏng vấn, chỉ cần yêu cầu họ viết một trình phân tích cú pháp cho nhiệm vụ này :)
Sau nhiều nỗ lực viết một trình phân tích cú pháp mà không có lỗi, tôi đã tìm thấy một phần của nó trong mã terraform và phần quan trọng nhất. Và mọi thứ dường như hoạt động tốt

Cố gắng ba
nhà cung cấp terraform là các tệp nhị phân chứa mã có tất cả tài nguyên và logic để làm việc với API đám mây. Mỗi đám mây có nhà cung cấp riêng và bản thân địa hình chỉ gọi họ thông qua giao thức RPC giữa hai quy trình.
Bây giờ tôi quyết định liên hệ trực tiếp với các nhà cung cấp terraform thông qua các cuộc gọi RPC. Nó trở nên tuyệt vời và có thể thay đổi nhà cung cấp địa hình sang nhà cung cấp mới hơn và nhận các tính năng mới mà không cần thay đổi mã. Nó cũng chỉ ra rằng không phải tất cả các trường trong tfstate đều phải ở dạng tf, nhưng làm cách nào bạn có thể tìm ra? Chỉ cần hỏi nhà cung cấp của bạn về điều này. Sau đó, một nội dung khiêu dâm đệ quy khác về việc tập hợp các biểu thức chính quy bắt đầu, tìm kiếm chuyên sâu các trường bên trong tfstate ở mọi cấp độ.

Cuối cùng, chúng tôi đã có được một công cụ CLI hữu ích có cơ sở hạ tầng chung cho tất cả các nhà cung cấp địa hình và bạn có thể dễ dàng thêm một công cụ mới. Ngoài ra, việc thêm tài nguyên cần ít mã hơn. Cộng với tất cả các loại quà tặng như kết nối giữa các tài nguyên. Tất nhiên, có rất nhiều vấn đề khác nhau không thể kể hết được.
Tôi đặt tên cho con vật là Terrafome.

Chung kết

Bằng cách sử dụng Terrafomer, chúng tôi đã tạo ra 500-700 nghìn dòng mã tf + tfstate từ hai đám mây. Chúng tôi có thể lấy những thứ kế thừa và bắt đầu chạm vào chúng chỉ thông qua địa hình, như trong cơ sở hạ tầng tốt nhất dưới dạng ý tưởng mã. Thật kỳ diệu khi bạn lấy một đám mây khổng lồ và nhận nó thông qua một nhóm dưới dạng tệp công nhân địa hình. Và sau đó grep/replace/git, v.v.

Tôi chải nó ra và sắp xếp nó theo thứ tự, được sự cho phép. Được phát hành trên GitHub cho mọi người vào thứ Năm (02.05.19/XNUMX/XNUMX). github.com/GoogleCloudPlatform/terraformer
Đã nhận được 600 sao, 2 yêu cầu kéo để thêm hỗ trợ cho openstack và kubernetes. Phản hồi tốt. Nói chung là dự án có ích cho mọi người
Tôi khuyên tất cả những ai muốn bắt đầu làm việc với Terraform và không viết lại mọi thứ cho việc này.
Tôi sẽ vui lòng đưa ra các yêu cầu, vấn đề, ngôi sao.

Bản trình diễn
Terraformer - Cơ sở hạ tầng để mã hóa

Nguồn: www.habr.com

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