نشر Swift على Kubernetes: دليل أساسي للمطورين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا Swift وKubernetes؟

Swift ليس فقط لغة لتطبيقات iOS وmacOS. بفضل مشروع Swift on Server وأطر العمل مثل Vapor وSwiftNIO، يمكن لمطوري Swift إنشاء تطبيقات خادم عالية الأداء. ومع ذلك، لكي يعمل هذا التطبيق بشكل مستقر وقابل للتوسع، يتطلب بنية تحتية حديثة.

Kubernetes (K8s) هو المعيار الفعلي لتنسيق الحاويات. في هذا الدليل، سنوضح كيفية تعبئة تطبيق Swift في صورة Docker، وكتابة ملفات تعريف Kubernetes، ونشره في مجموعة. ستتعلم كيفية استخدام SwiftNIO لإنشاء خادم HTTP خفيف الوزن وتكوينه للعمل في السحابة.



1. تحضير تطبيق Swift للحاوية

1.1. إنشاء مشروع باستخدام SwiftNIO

للتوضيح، سنكتب خادم HTTP بسيط باستخدام SwiftNIO. سيتجنب هذا الاعتماديات غير الضرورية ويظهر كيفية عمل الشبكات على مستوى منخفض. افتح الطرفية وأنشئ مشروعًا جديدًا:

mkdir SwiftK8sDemocd SwiftK8sDemoswift package init --type executable

أضف اعتمادية SwiftNIO في Package.swift:

// swift-tools-version:5.7import PackageDescription

let package = Package( name: "SwiftK8sDemo", dependencies: [ .package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0") ], targets: [ .executableTarget( name: "SwiftK8sDemo", dependencies: [ .product(name: "NIO", package: "swift-nio"), .product(name: "NIOHTTP1", package: "swift-nio") ] ) ])


1.2. كود الخادم مع فحص الصحة

لننشئ خادمًا بسيطًا يستجيب لطلبات GET ويحتوي على نقطة نهاية لفحص الصحة (/health). هذا ضروري لـ Kubernetes liveness probe. استبدل محتوى Sources/SwiftK8sDemo/main.swift:

import NIOimport NIOHTTP1

final class HTTPHandler: ChannelInboundHandler { typealias InboundIn = HTTPServerRequestPart typealias OutboundOut = HTTPServerResponsePart

func channelRead(context: ChannelHandlerContext, data: NIOAny) { let req = unwrapInboundIn(data) switch req { case .head(let header): let response: String let status: HTTPResponseStatus if header.uri == "/health" { response = "{\\"status\\":\\"ok\\"}" status = .ok } else { response = "Hello from Swift on K8s!" status = .ok } var buffer = context.channel.allocator.buffer(capacity: response.utf8.count) buffer.writeString(response) let head = HTTPResponseHead(version: .init(major: 1, minor: 1), status: status) context.write(wrapOutboundOut(.head(head)), promise: nil) context.write(wrapOutboundOut(.body(.byteBuffer(buffer))), promise: nil) context.writeAndFlush(wrapOutboundOut(.end(nil)), promise: nil) default: break } }}

let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)defer { try! group.syncShutdownGracefully() }

let bootstrap = ServerBootstrap(group: group) .serverChannelOption(ChannelOptions.backlog, value: 256) .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) .childChannelInitializer { channel in channel.pipeline.configureHTTPServerPipeline().flatMap { channel.pipeline.addHandler(HTTPHandler()) } }

let host = ProcessInfo.processInfo.environment["HOST"] ?? "0.0.0.0"let port = Int(ProcessInfo.processInfo.environment["PORT"] ?? "8080") ?? 8080

print("Server starting on \\(host):\\(port)")try bootstrap.bind(host: host, port: port).wai

المدونات

توصيات الكتب