GoCasts آموزش Go به زبان ساده

بیش از ۱۰۰۰ شرکت‌کننده یادگیری Go و Backend رو از امروز شروع کن
ثبت‌نام دوره + تیم‌سازی

گولنگ برای مهندسان DevOps - چرا Go زبان اول زیرساخت است

اگر DevOps Engineer یا SRE هستید، احتمالاً روزانه با ابزارهایی مثل Docker، Kubernetes، Terraform، Prometheus و Helm کار می‌کنید. یک نکته جالب وجود دارد: همه این ابزارها با Go نوشته شده‌اند.

این تصادفی نیست. Go ویژگی‌هایی دارد که آن را به انتخاب طبیعی برای ابزارهای زیرساختی تبدیل کرده است.

چرا ابزارهای DevOps با Go نوشته شده‌اند؟

۱. باینری مستقل (Single Binary)

Go به یک فایل اجرایی کامپایل می‌شود که هیچ dependency خارجی ندارد:

# کامپایل برای لینوکس
GOOS=linux GOARCH=amd64 go build -o mytool

# این فایل روی هر سرور لینوکسی کار می‌کند
# بدون نیاز به نصب runtime، pip، npm یا هر چیز دیگری
scp mytool server:/usr/local/bin/

مقایسه کنید با Python که نیاز به interpreter، virtualenv و pip دارد، یا Java که JVM می‌خواهد. برای ابزارهایی که روی هزاران سرور deploy می‌شوند، این مزیت حیاتی است.

۲. Cross-Compilation آسان

با Go می‌توانید از یک مک‌بوک، باینری برای تمام پلتفرم‌ها بسازید:

# از macOS برای تمام پلتفرم‌ها build کنید
GOOS=linux   GOARCH=amd64 go build -o mytool-linux
GOOS=darwin  GOARCH=arm64 go build -o mytool-mac
GOOS=windows GOARCH=amd64 go build -o mytool.exe

این قابلیت برای ابزارهای CLI که باید روی محیط‌های مختلف کار کنند، بسیار ارزشمند است.

۳. عملکرد بالا و مصرف منابع پایین

ابزارهای DevOps باید سریع باشند و منابع کمی مصرف کنند:

زبان زمان شروع مصرف حافظه سرعت اجرا
Go میلی‌ثانیه کم بالا
Python صدها میلی‌ثانیه متوسط پایین
Java ثانیه‌ها بالا بالا (پس از warmup)

وقتی یک CLI tool را صدها بار در روز اجرا می‌کنید یا یک controller در Kubernetes هر ثانیه event پردازش می‌کند، این تفاوت‌ها اهمیت پیدا می‌کنند.

۴. همزمانی داخلی

اکثر ابزارهای زیرساختی نیاز به انجام کارهای همزمان دارند:

// بررسی همزمان وضعیت ۱۰۰ سرور
func checkServers(servers []string) []Result {
    results := make(chan Result, len(servers))

    for _, server := range servers {
        go func(s string) {
            status := ping(s)
            results <- Result{Server: s, Status: status}
        }(server)
    }

    var all []Result
    for range servers {
        all = append(all, <-results)
    }
    return all
}

Goroutine‌ها این کار را بسیار ساده می‌کنند. در Python باید با asyncio یا threading دست‌وپنجه نرم کنید.

ابزارهای معروف DevOps نوشته‌شده با Go

ابزار کاربرد شرکت سازنده
Docker Containerization Docker Inc
Kubernetes Container Orchestration Google/CNCF
Terraform Infrastructure as Code HashiCorp
Prometheus Monitoring CNCF
Grafana Agent Metrics Collection Grafana Labs
Helm Package Manager for K8s CNCF
etcd Distributed Key-Value CNCF
Consul Service Discovery HashiCorp
Vault Secrets Management HashiCorp
CockroachDB Distributed Database Cockroach Labs
InfluxDB Time Series Database InfluxData
Traefik Reverse Proxy Traefik Labs
Caddy Web Server Matt Holt
Hugo Static Site Generator -

تقریباً تمام اکوسیستم Cloud-Native با Go ساخته شده است.

کاربردهای عملی Go برای DevOps Engineers

شما نیاز نیست نرم‌افزار سطح Kubernetes بنویسید. این‌ها کاربردهای واقعی و روزمره هستند:

۱. ابزارهای CLI سفارشی

// یک CLI ساده برای مدیریت deployment
package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println("Usage: deploy <environment>")
        os.Exit(1)
    }

    env := os.Args[1]

    // اعتبارسنجی محیط
    validEnvs := map[string]bool{"staging": true, "production": true}
    if !validEnvs[env] {
        fmt.Printf("Invalid environment: %s\n", env)
        os.Exit(1)
    }

    // اجرای kubectl
    cmd := exec.Command("kubectl", "apply", "-f",
        fmt.Sprintf("k8s/%s/", env))
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    if err := cmd.Run(); err != nil {
        fmt.Printf("Deployment failed: %v\n", err)
        os.Exit(1)
    }

    fmt.Printf("Successfully deployed to %s\n", env)
}

این را کامپایل کنید و یک باینری deploy خواهید داشت که بدون هیچ dependency روی هر سیستمی کار می‌کند.

۲. اسکریپت‌های اتوماسیون قابل حمل

// بررسی سلامت سرویس‌ها و ارسال هشدار
package main

import (
    "fmt"
    "net/http"
    "time"
)

type Service struct {
    Name string
    URL  string
}

func checkHealth(svc Service) error {
    client := &http.Client{Timeout: 5 * time.Second}
    resp, err := client.Get(svc.URL)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("status %d", resp.StatusCode)
    }
    return nil
}

func main() {
    services := []Service{
        {Name: "API Gateway", URL: "https://api.example.com/health"},
        {Name: "Auth Service", URL: "https://auth.example.com/health"},
        {Name: "User Service", URL: "https://users.example.com/health"},
    }

    for _, svc := range services {
        if err := checkHealth(svc); err != nil {
            fmt.Printf("[FAIL] %s: %v\n", svc.Name, err)
            // اینجا می‌توانید به Slack/PagerDuty هشدار بفرستید
        } else {
            fmt.Printf("[OK] %s\n", svc.Name)
        }
    }
}

۳. پلاگین‌های kubectl

// kubectl-pods-by-node: نمایش pods به تفکیک node
package main

import (
    "context"
    "fmt"
    "os"
    "path/filepath"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func main() {
    // خواندن kubeconfig
    home, _ := os.UserHomeDir()
    kubeconfig := filepath.Join(home, ".kube", "config")

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // گرفتن لیست pods
    pods, err := clientset.CoreV1().Pods("").List(
        context.Background(),
        metav1.ListOptions{},
    )
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    // گروه‌بندی بر اساس node
    byNode := make(map[string][]string)
    for _, pod := range pods.Items {
        byNode[pod.Spec.NodeName] = append(
            byNode[pod.Spec.NodeName],
            pod.Name,
        )
    }

    // نمایش نتایج
    for node, podList := range byNode {
        fmt.Printf("\n=== %s (%d pods) ===\n", node, len(podList))
        for _, p := range podList {
            fmt.Printf("  - %s\n", p)
        }
    }
}

این فایل را با نام kubectl-pods-by-node در PATH قرار دهید و با kubectl pods-by-node اجرا کنید.

۴. Prometheus Exporter سفارشی

// exporter برای متریک‌های سفارشی اپلیکیشن
package main

import (
    "net/http"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
    requestsTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "myapp_requests_total",
            Help: "Total number of requests",
        },
        []string{"method", "endpoint", "status"},
    )

    requestDuration = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name:    "myapp_request_duration_seconds",
            Help:    "Request duration in seconds",
            Buckets: prometheus.DefBuckets,
        },
        []string{"method", "endpoint"},
    )
)

func init() {
    prometheus.MustRegister(requestsTotal)
    prometheus.MustRegister(requestDuration)
}

func main() {
    // endpoint برای Prometheus
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":9090", nil)
}

۵. Webhook Handler برای CI/CD

// دریافت webhook از GitHub و اجرای عملیات
package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
    "os/exec"
)

type PushEvent struct {
    Ref        string `json:"ref"`
    Repository struct {
        Name     string `json:"name"`
        CloneURL string `json:"clone_url"`
    } `json:"repository"`
}

func verifySignature(payload []byte, signature string, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(payload)
    expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(signature))
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    payload, _ := io.ReadAll(r.Body)

    // اعتبارسنجی signature
    signature := r.Header.Get("X-Hub-Signature-256")
    if !verifySignature(payload, signature, os.Getenv("WEBHOOK_SECRET")) {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }

    var event PushEvent
    json.Unmarshal(payload, &event)

    // فقط برای main branch
    if event.Ref == "refs/heads/main" {
        go func() {
            cmd := exec.Command("./deploy.sh", event.Repository.Name)
            cmd.Run()
        }()
    }

    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, "OK")
}

func main() {
    http.HandleFunc("/webhook", webhookHandler)
    http.ListenAndServe(":8080", nil)
}

چه موقع Go و چه موقع Python/Bash؟

سناریو توصیه دلیل
اسکریپت یکبار مصرف Bash سریع‌تر نوشته می‌شود
اسکریپت ساده (<50 خط) Bash/Python overhead کمتر
ابزار CLI قابل توزیع Go باینری مستقل
ابزار با همزمانی Go goroutines
پلاگین Kubernetes Go client-go رسمی
اسکریپت پردازش داده Python کتابخانه‌های غنی
Ansible/Terraform modules بستگی دارد از زبان رسمی استفاده کنید

قاعده کلی:

اگر ابزار قرار است روی سیستم‌های مختلف توزیع شود یا توسط دیگران استفاده شود، Go انتخاب بهتری است.

اگر اسکریپت فقط برای خودتان و یکبار مصرف است، Bash یا Python کافی است.

مسیر یادگیری Go برای DevOps Engineers

شما نیاز ندارید یک برنامه‌نویس حرفه‌ای شوید. این مسیر را پیشنهاد می‌کنیم:

مرحله ۱: یادگیری پایه‌های Go

  1. نصب Go
  2. انواع داده
  3. توابع
  4. ساختارهای کنترلی

مرحله ۲: مفاهیم کلیدی

  1. Pointers - برای کار با کتابخانه‌های Go ضروری
  2. Goroutines - همزمانی در Go
  3. Channels - ارتباط بین goroutines

مرحله ۳: کاربردهای عملی

  1. ساخت REST API - درک HTTP در Go
  2. Docker با Go - containerize کردن برنامه‌ها
  3. ساخت CLI با Cobra - ابزارهای خط فرمان

مرحله ۴: تخصص DevOps

  1. Prometheus Exporter با Go
  2. اتوماسیون زیرساخت با Go

نمونه پروژه‌های تمرینی

پروژه مهارت‌های یادگیری سختی
Health Checker CLI HTTP client, CLI basics آسان
Log Parser File I/O, regex آسان
Multi-server ping Goroutines, channels متوسط
Prometheus Exporter Metrics, HTTP server متوسط
kubectl Plugin Kubernetes API پیشرفته
Simple Operator Controller pattern پیشرفته

جمع‌بندی

برای DevOps Engineers، یادگیری Go یک مهارت ارزشمند است زیرا:

  1. ابزارهایی که استفاده می‌کنید با Go نوشته شده‌اند
  2. می‌توانید این ابزارها را سفارشی کنید (پلاگین، exporter، operator)
  3. ابزارهای داخلی بهتری می‌سازید (CLI tools قابل توزیع)
  4. درک بهتری از ابزارها پیدا می‌کنید (کد منبع را بخوانید)

نیازی نیست یک backend developer شوید. با یادگیری پایه‌های Go و تمرین روی پروژه‌های DevOps-محور، می‌توانید ابزارهای قدرتمندی بسازید.


مقالات مرتبط

منابع

بیش از ۱۰۰۰ شرکت‌کننده یادگیری Go و Backend رو از امروز شروع کن
ثبت‌نام دوره + تیم‌سازی