Недавно я начал обновлять один из наших инструментов развертывания, чтобы он использовал helm3. Текущий инструмент - это приложение golang, которое, учитывая путь к диаграмме управления и kubeconfig, будет развернуто во всех наших производственных пространствах имен (в этом кластере) одновременно с помощью helm (позже мы напишем об этом отдельный блог).

Как мы сейчас выполняем развертывание в кластере k8s

Нынешний инструмент, который мы используем, использует библиотеки helm2 вроде ... когда Обама еще был президентом. Библиотеки go были не очень удобны в использовании, а документации было довольно мало ... не говоря уже о головной боли размера Шакила О’Нила, которую я получил от попыток заставить библиотеки 4-летней давности с различными зависимостями играть хорошо. Чтобы использовать helm, нам пришлось использовать метод переадресации портов из Kubernetes для привязки локального порта к сервисному порту tiller (44134).

func getHelmClient(kcfg string) *helm.Client {
 config, _ := clientcmd.BuildConfigFromFlags(“”, kcfg)
 client, _ := kubernetes.NewForConfig(config)
// port forward tiller
 tillerTunnel, _ := portforwarder.New(“kube-system”, client, config)
// new helm client
 host := fmt.Sprintf(“127.0.0.1:%d”, tillerTunnel.Local)
 helmClient := helm.NewClient(helm.Host(host))
 return helmClient
}

Переход на Helm3

Я не собираюсь вдаваться в дискуссию «я люблю штурвал, но ненавижу румпель», но, разумеется, переходить к helm3 было большим удовольствием. Появилось множество новых функций, одна из которых - исчезновение Tiller, а helm будет напрямую взаимодействовать с Kubernetes API.

В разгар исследования того, как загрузить kubeconfig из кластера EKS, я наткнулся на эту жемчужину вопроса в StackOverflow. Как и любой хороший разработчик, я скопировал и вставил этот код без всяких сожалений по поводу человеческой жизни.

Суть сообщения в том, что «aws eks update-kubeconfig» - это удобная функция. Общий процесс программного доступа к вашему кластеру EKS заключается в использовании серии библиотек и вызовов API для генерации токена для создания клиентского набора K8s для взаимодействия с вашим кластером. С появлением возможности передавать токен-носитель для аутентификации в helm3 cli я надеялся увидеть, смогу ли я программно усовершенствовать библиотеки go, чтобы они делали то же самое.

Получите токен авторизации k8s

Вот где я копирую / прошиваю ... err написал код для получения клиента kubernetes (и для возврата токена аутентификации)

func NewClientset(cluster *eks.Cluster) (*kubernetes.Clientset, *rest.Config, error) {
 gen, err := token.NewGenerator(true, false)
 if err != nil {
  return nil, nil, err
 }
 opts := &token.GetTokenOptions{
  ClusterID: aws.StringValue(cluster.Name),
 }
 tok, err := gen.GetWithOptions(opts)
 if err != nil {
  return nil, nil, err
 }
 ca, err := base64.StdEncoding.DecodeString(aws.StringValue(cluster.CertificateAuthority.Data))
 if err != nil {
  return nil, nil, err
 }
restConfigs := &rest.Config{
  Host:        aws.StringValue(cluster.Endpoint),
  BearerToken: tok.Token,
  TLSClientConfig: rest.TLSClientConfig{
   CAData: ca,
  },
 }
clientset, err := kubernetes.NewForConfig(restConfigs)
 if err != nil {
  return nil, nil, err
 }
 return clientset, restConfigs, nil
}

Создать собственный ActionConfig

В helm3 pkg/action содержит клиента, который обрабатывает большинство / все действия Helm. Теперь цель состоит в том, чтобы найти способ определить конфигурацию настраиваемого действия (я считаю, что по умолчанию установлено чтение kubeconfig). Используя приведенный ниже код, вы можете установить токен в качестве входных данных с предыдущего шага.

func GetActionConfig(namespace string, config *rest.Config) (*action.Configuration, error) {
 actionConfig := new(action.Configuration)
 var kubeConfig *genericclioptions.ConfigFlags
insecure := true
 kubeConfig = genericclioptions.NewConfigFlags(false)
 kubeConfig.APIServer = &config.Host
 kubeConfig.BearerToken = &config.BearerToken
 kubeConfig.Namespace = &namespace
 kubeConfig.Insecure = &insecure
 if err := actionConfig.Init(kubeConfig, namespace, os.Getenv("HELM_DRIVER"), log.Printf); err != nil {
  return nil, err
 }
 return actionConfig, nil
}

Собираем все вместе

Вот функция для вывода списка ваших релизов в Helm после аутентификации на вашем EKScluster

func main() {
    name := "name-of-your-cluster"
    region := "your-region"
    sess := session.Must(session.NewSession(&aws.Config{
        Region: aws.String(region),
    }))
    eksSvc := eks.New(sess)

    input := &eks.DescribeClusterInput{
        Name: aws.String(name),
    }
    result, err := eksSvc.DescribeCluster(input)
    if err != nil {
        log.Fatalf("Error calling DescribeCluster: %v", err)
    } 
    // pass cluster results to generate token and k8s client
    clientset, cfg, err := newClientset(result.Cluster)
    if err != nil {
        log.Fatalf("Error creating clientset: %v", err)
    }
    // initalize actionconfig
    actionConfig, err := getActionConfig("your-namespace", cfg)
    if err != nil {
        log.Println(err)
    }
    client := action.NewList(actionConfig)
    releases, err := client.Run()
    if err != nil {
        log.Println(err)
    }
    for _, release := range releases {
        log.Println("Release: " + release.Name + " Status: " +     release.Info.Status.String())
    }
}

В целом это был довольно интересный проект, чтобы исследовать и опробовать его. Многие из сложных вопросов задавали и отвечали на них гораздо более умные и талантливые разработчики. Я сопоставляю это, поскольку мне еще не приходилось видеть какую-либо документацию по этому поводу в Интернете. Кроме того, это было бесценно для меня в моем пути разработки с Kubernetes и Helm.