Введение в разработку плагинов Kubernetes
Kubernetes, мощный инструмент оркестровки контейнеров, является не только мощным, но и расширяемым. Один из самых интересных способов расширить его возможности — это разработка пользовательских плагинов с использованием Go. В этой статье мы погрузимся в мир разработки плагинов для Kubernetes, проведя вас через процесс с сочетанием теории, практики и долей юмора.
Почему Go?
Прежде чем мы начнём, давайте разберёмся с вопросом: почему именно Go? Go, или Golang, — это язык программирования, который выбирают многие разработчики Kubernetes. Это связано с тем, что сам Kubernetes написан на этом языке. Это делает экосистему невероятно согласованной, а официальные клиентские библиотеки — одними из наиболее поддерживаемых.
Настройка среды разработки
Предварительные условия
Чтобы начать разработку плагинов Kubernetes, вам понадобится несколько вещей:
- Настроенная среда Kubernetes. Если у вас нет многоузлового кластера, такие инструменты, как minikube или microk8s, помогут вам настроить локальную среду.
- Базовые знания Go. Если вы новичок в Go, пришло время познакомиться с ним поближе; это простой и мощный язык.
- Рабочая директория модулей Go. Она необходима для управления зависимостями в ваших проектах Go.
Установка Client-Go
Библиотека client-go — ваш ключ к взаимодействию с API Kubernetes. Вот как её можно установить:
mkdir k8sjobs
cd k8sjobs && go mod init github.com/k8sjobs
go get k8s.io/client-go@latest
Это настроит ваш модуль Go и установит библиотеку client-go. Вы можете проверить установку, проверив файл go.mod:
module github.com/k8sjobs
go 1.15
require k8s.io/client-go v0.20.2 // indirect
Разработка вашего первого плагина Kubernetes
Пошаговое руководство
1. Создайте свой проект Go
Начните с создания нового проекта Go. Вот пример того, как можно структурировать ваш проект:
.
├── LICENSE
├── README.adoc
├── cmd
│ └── main.go
├── go.mod
└── go.sum
2. Напишите код плагина
Давайте создадим простой плагин, который отображает версию сервера Kubernetes. Вот каким может быть ваш файл main.go:
package main
import (
"github.com/bmuschko/kubectl-server-version/cmd"
"k8s.io/cli-runtime/pkg/genericclioptions"
"os"
)
var version = "undefined"
func main() {
serverVersionCmd := cmd.NewServerVersionCommand(genericclioptions.IOStreams{
In: os.Stdin,
Out: os.Stdout,
ErrOut: os.Stderr,
})
if err := serverVersionCmd.Execute(); err != nil {
os.Exit(1)
}
}
Этот код настраивает новую команду, используя библиотеку Cobra, и выполняет её, обрабатывая возможные ошибки.
3. Соберите и установите плагин
Чтобы ваш плагин был обнаружен kubectl, вам нужно собрать его и разместить в системном PATH. Вот как это сделать:
go build -o kubectl-server_version main.go
sudo mv kubectl-server_version /usr/local/bin/
На macOS двоичный файл перемещается в /usr/local/bin/
. Убедитесь, что этот каталог находится в вашем системном PATH.
Сделайте плагин обнаруживаемым
Имя вашего плагина должно начинаться с префикса kubectl-, а любые тире в имени команды должны быть заменены символами подчёркивания. Например, kubectl-server-version становится kubectl-server_version при сборке двоичного файла.
Создание заданий Kubernetes с помощью Client-Go
Иногда вам может потребоваться создавать задания Kubernetes программно. Вот как вы можете сделать это с помощью библиотеки client-go.
Пример кода
Вот пример инструмента командной строки, который создаёт задание Kubernetes:
package main
import (
"context"
"flag"
"log"
"os"
"path/filepath"
"strings"
batchv1 "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubernetes "k8s.io/client-go/kubernetes"
clientcmd "k8s.io/client-go/tools/clientcmd"
)
func connectToK8s() *kubernetes.Clientset {
home, exists := os.LookupEnv("HOME")
if !exists {
home = "/root"
}
configPath := filepath.Join(home, ".kube", "config")
config, err := clientcmd.BuildConfigFromFlags("", configPath)
if err != nil {
log.Fatalf("Failed to build config: %v", err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
return clientset
}
func main() {
jobName := flag.String("job-name", "", "Name of the job")
containerName := flag.String("container-name", "", "Name of the container")
entrypoint := flag.String("entrypoint", "", "Entrypoint of the container")
flag.Parse()
if *jobName == "" || *containerName == "" || *entrypoint == "" {
log.Fatal("All flags must be provided")
}
clientset := connectToK8s()
job := &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: *jobName,
},
Spec: batchv1.JobSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: *containerName,
Image: "busybox",
Command: []string{*entrypoint},
},
},
},
},
},
}
_, err := clientset.BatchV1().Jobs("default").Create(context.TODO(), job, metav1.CreateOptions{})
if err != nil {
log.Fatalf("Failed to create job: %v", err)
}
log.Println("Job created successfully")
}
Этот код подключается к кластеру Kubernetes и создаёт новое задание на основе предоставленных флагов.
Отладка служб Kubernetes из GoLand
Если вы используете GoLand для разработки, вы также можете отлаживать свои службы Kubernetes прямо из IDE.
Шаги для отладки
Подготовьте файлы YAML: убедитесь, что у вас есть необходимые файлы YAML для развёртывания. Например, файлы db.yaml и web.yaml, которые определяют ваши сервисы и развёртывания.
Соберите и разверните: соберите свой контейнер Docker и разверните его в Kubernetes, используя зелёную стрелку в редакторе GoLand.
Внесите изменения для отладки: внесите необходимые изменения в файл web.yaml для включения отладки. Обычно это включает корректировку файла Dockerfile и сборку с конфигурацией отладки.
Запустите отладчик: используйте Run | Debug … | Kubernetes Service для запуска конфигурации удалённой отладки Go. Это позволит вам отлаживать службу, как если бы она работала локально.
Заключение
Разработка плагинов Kubernetes с использованием Go — мощный способ расширить возможности вашего кластера Kubernetes. От создания пользовательских инструментов kubectl до программного управления ресурсами Kubernetes библиотека client-go предоставляет широкий набор инструментов.