Errors
Kubernetes

Kubernetes: kubectl create using inline options in bash script instead of yaml file

Ты ~~написал~~ наваял идеальный yaml-манифест для Tiller. Положил его в репу, настроил джобу в Jenkins, которая должна просто выполнить `kubectl create -f`. Но

Ты написал наваял идеальный yaml-манифест для Tiller. Положил его в репу, настроил джобу в Jenkins, которая должна просто выполнить kubectl create -f. Но потом тебя осеняет: а что если сделать всё одной строчкой в скрипте? Без лишних файлов, просто чистый bash, который можно впихнуть в пайплайн и забыть.

Сначала кажется, что это ересь. Всё вокруг твердит о декларативности, о том, что yaml — это свято. Но иногда хочется императивно, быстро и прямо в консоли. Особенно когда нужно протестить что-то или собрать ресурс на лету.

От манифеста к команде

Вот тот самый tiller-sa-crb.yaml. Два ресурса в одном файле: ServiceAccount и ClusterRoleBinding. Классика для Helm 2.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
   name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: tiller
  namespace: kube-system

А вот команда, которая его применяет: kubectl create -f tiller-sa-crb.yaml. Скучно. Предсказуемо. Негибко.

Допустим, тебе нужно в Jenkins-джобе динамически подставлять namespace или имя аккаунта. Лезть в шаблонизацию yaml? Можно. Но есть путь короче.

Bash-ализация кубернетеса

kubectl create умеет многое прямо из командной строки. Зачем файл, если можно так:

#!/bin/bash
#create SA account in one line in namespace kube-system
kubectl create serviceaccount tiller -n kube-system

#create cluster role binding in one line using above serviceaccount and in kube-system namespace
kubectl create clusterrolebinding crb-cluster-admin-test2 --clusterrole=cluster-admin --serviceaccount=kube-system:tiller

Вот и весь скрипт. tiller-sa-crb.sh. Кидаешь его в артефакты, и джоба дёргает его без лишних телодвижений.

Первая команда создаёт ServiceAccount. Всё как в yaml, но флагами: имя, namespace.

Вторая — ClusterRoleBinding. Обрати внимание на флаг --serviceaccount. Тут важен синтаксис: <namespace>:<serviceaccount_name>. Если перепутаешь, binding будет ссылаться в пустоту.

Имя binding (crb-cluster-admin-test2) можно сделать любым. В yaml оно было tiller, но это не обязательно. Главное, чтобы roleRef и subjects сошлись.

Почему это работает (и когда не стоит)

Kubernetes API в итоге получает те же самые структуры данных, что и из yaml-файла. kubectl create просто собирает их из аргументов командной строки и шёт на сервер.

Это отлично подходит для простых ресурсов с парой-тройкой полей. Для чего-то сложного, с кучей аннотаций, меток или вложенных структур — лучше остаться при yaml. Иначе скрипт превратится в нечитаемую портянку с --annotation, --label и --from-literal.

Плюс такого подхода — скорость и прозрачность. Видишь всё сразу в одной строке. Минус — потеря декларативности. Этот ресурс теперь живёт только в твоей команде. Чтобы понять, что было развёрнуто, придётся лезть в историю bash или логи Jenkins.

Итог

Если нужно быстро, для одноразового действия или простого CI-шага — инлайн-команды kubectl create это валидный выход. Запустил скрипт — получил ресурс.

Для production-среды, где важны контроль версий, ревью изменений и ясность — оставайся с yaml. Или иди дальше, к Helm или Kustomize.

Но теперь ты знаешь, что если увидишь в логах джобы загадочный kubectl create serviceaccount..., это не обязательно ошибка. Это кто-то, как и ты, решил срезать угол.