Kubernetes: kubectl и kubeconfig – обзор файла, добавление кластера, пользователя и контекста

Автор: | 14/04/2020

Аутентификация в Kubernetes может отличаться методами аутентификации, пользователями, правилами кластеров:

  • сам kubectl может использовать различные способы аутентифицаии – сертификаты, логин-пароль
  • сами пользователи могут использовать различные способы – токены, логин-пароль и т.д.
  • и, в конце-концов, мы можем захотеть хранить в настройках доступ к различным кластерам, но иметь возможность манипулировать ими из одного места

Для всего этого служит файл настроек kubectl, в котором описываются механизмы аутентификации и данные подключения к кластерам.

В системе может присутствовать более одного такого файла настроек, а для определения того, какой использовать – kubectl выполнит проверку по:

  1. опции --kubeconfig и пути к файлу
  2. переменной окружения $KUBECONFIG
  3. и файлу по-умолчанию – $HOME/.kube/config

Применён будет первый обнаруженный, т.е. приоритет в списке выше идёт сверху вниз.

Например:

[simterm]

$ kubectl get pods --kubeconfig=/home/setevoy/new-config

[/simterm]

Впрочем, можно передать все нужные опции прямо аргументами к kubectl, не используя файл вообще:

[simterm]

$ kubectl get nodes --server https://eks-api-server.com:6443 --user kube-username --client-certificate user-client.cert --client-key user-client --insecure-skip-tls-verify

[/simterm]

В этом посте рассмотрим из чего файл настроек состоит, как манипулировать данными в нём, и в конце – сгенерируем файл настроек kubectl для своего AWS Elastic Kubernetes Service кластера для двух пользователейй – AWS IAM User и AWS IAM Role.

kubectl config file

Пример файла настроек kubectl:

current-context: federal-context
apiVersion: v1
clusters:
- cluster:
    api-version: v1
    server: http://cluster-1.com:8080
  name: cluster-1
- cluster:
    certificate-authority: path/to/cafile
    server: https://cluster-2.com:4443
  name: cluster-2
- cluster:
    insecure-skip-tls-verify: true
    server: https://cluster-3.com:443
  name: cluster-3
contexts:
- context:
    cluster: cluster-1
    namespace: cluster-1-ns
    user: user-1
  name: federal-context
- context:
    cluster: cluster-2
    namespace: cluster-1-ns
    user: user-2
  name: queen-anne-context
kind: Config
preferences:
  colors: true
users:
- name: user-1
  user:
    token: user-1-token
- name: user-2
  user:
    client-certificate: path/to/client/cert
    client-key: path/to/client/key

Для просмотра содержимого текущего файла настроек используем kubectl config view, а для просмотра только текущего контекста – добавляем --minify:

[simterm]

$ kubectl config view --minify
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://example-cluster.yl4.us-east-2.eks.amazonaws.com
  name: arn:aws:eks:us-east-2:534***385:cluster/bttrm-eks-dev-0
contexts:
- context:
    cluster: arn:aws:eks:us-east-2:534***385:cluster/bttrm-eks-dev-0
    user: arn:aws:eks:us-east-2:534***385:cluster/bttrm-eks-dev-0
  name: arn:aws:eks:us-east-2:534***385:cluster/bttrm-eks-dev-0
current-context: arn:aws:eks:us-east-2:534***385:cluster/bttrm-eks-dev-0
kind: Config
preferences: {}
users:
- name: arn:aws:eks:us-east-2:534***385:cluster/bttrm-eks-dev-0
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - us-east-2
      - eks
      - get-token
      - --cluster-name
      - bttrm-eks-dev-0
      command: aws
      env:
      - name: AWS_PROFILE
        value: arseniy

[/simterm]

Процессы аутентификации и авторизации в AWS Elastic Kubernetes Service и процесс получения токенов см. в Kubernetes: знакомство, часть 4 — аутентификация в AWS EKS, aws-iam-authenticator и AWS IAM.

cluster

clusters:
- cluster:
    certificate-authority: path/to/my/cafile
    server: https://horse.org:4443
  name: horse-cluster
- cluster:
    insecure-skip-tls-verify: true
    server: https://pig.org:443
  name: pig-cluster

Блок cluster содержит информацию об, внезапно, кластере – FQDN API-сервера для подключения, его Certificate Authority сертификат с публичным ключём (в base64), и имя.

Для добавления нового кластера используем kubectl config set-cluster – передаём имя для сервера, как мы его хотим видеть, плюс URL API-сервера:

[simterm]

$ kubectl --kubeconfig=example-kubeconf config set-cluster example-cluster-1 --server=https://example-cluster.yl4.us-east-2.eks.amazonaws.com --insecure-skip-tls-verify=true
Cluster "example-cluster-1" set.

[/simterm]

Проверяем содержимое example-kubeconf:

apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://example-cluster.yl4.us-east-2.eks.amazonaws.com
  name: example-cluster-1
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []

user

Блог user определяет собственно пользователя для аутентифицикации.

Тут же указываются доступные пользвателю методы аутентифицикации, которые могут быть:

  • client-certificate
  • client-key
  • token
  • username/password

Добавляем пользователя, используя kubectl config set-credentials:

[simterm]

$ kubectl --kubeconfig=example-kubeconf config set-credentials example-user-1 --token=SOMETOKEN
User "example-user-1" set.

[/simterm]

В --token пока передаём любую дичь – чуть позже, в Добавление user, посмотрим, как добавить аутентификацию через сертификат.

Проверяем конфиг:

apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://example-cluster.yl4.us-east-2.eks.amazonaws.com
  name: example-cluster-1
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: example-user-1
  user:
    token: SOMETOKEN

Появился блок users – окей.

context

В блоке context задаётся блок (в виде типа данных dictionary), в котором объединяются cluster, user и опционально namespace.

Добавляем новый контекст с помощью  kubectl config set-conext – объединяем созданные ранее кластер и пользователя, плюс задаём дефолтный для юзера неймспейс в кластере:

[simterm]

$ kubectl --kubeconfig=example-kubeconf config set-context example-context-1 --cluster=example-cluster-1 --namespace=cluster-1-ns --user=example-user-1
Context "example-context-1" created.

[/simterm]

Проверяем:

apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://example-cluster.yl4.us-east-2.eks.amazonaws.com
  name: example-cluster-1
contexts:
- context:
    cluster: example-cluster-1
    namespace: cluster-1-ns
    user: example-user-1
  name: example-context-1
current-context: ""
kind: Config
preferences: {}
users:
- name: example-user-1
  user:
    token: SOMETOKEN

current-context

Описывает текущий контекст, он же контекст по-умолчанию, который будет использоваться при вызове kubectl без указания контекста.

Используем kubectl config use-context:

[simterm]

$ kubectl --kubeconfig=example-kubeconf config use-context example-context-1
Switched to context "example-context-1".

[/simterm]

Соберём все шаги вместе – настроим второй кластер:

  1. создаём пользователя:
    kubectl --kubeconfig=example-kubeconf-2 config set-credentials example-user-2 --username=user --password=pass
  2. добавляем новый API-сервер нужного кластера:
    kubectl --kubeconfig=example-kubeconf-2 config set-cluster example-cluster-2 --server=http://1.1.1.1:80
  3. объединяем кластер и пользователя в контекст:
    kubectl --kubeconfig=example-kubeconf-2 config set-context example-context-2 --cluster=example-cluster-2 --user=example-user-2
  4. переключаемся на этот контекст:
    kubectl --kubeconfig=example-kubeconf-2 config use-context example-context-2
  5. меняем namespace по-умолчанию в этом кластере для этого пользователя:
    kubectl --kubeconfig=example-kubeconf-2 config set contexts.example-context-2.namespace in-cluster-namespace-name

Результат:

apiVersion: v1
clusters:
- cluster:
    server: http://1.1.1.1:8080
  name: example-cluster-2
contexts:
- context:
    cluster: example-cluster-2
    namespace: in-cluster-namespace-name
    user: example-user-2
  name: example-context-2
current-context: example-context-2
kind: Config
preferences: {}
users:
- name: example-user-2
  user:
    password: pass
    username: user

AWS IAM User и Elastic Kubernetes Service

А теперь создадим новый файл конфига с настройками для конкретного кластера – но для двух различных пользователей.

У нас используется AWS IAM, потому для аутентификации используем IAM пользователей и IAM роли, см. схемы тут – AWS Elastic Kubernetes Service: RBAC-авторизация через AWS IAM и RBAC группы.

Выполним:

  • добавим существующий кластер
  • добавим пользователя с аутентификацией через токен
  • объединим пользователя и кластер в контекст

aws eks describe-cluster и создание kubeconfig

Для настройки нам потребуются:

  • URL API-сервера кластера
  • его сертификат
  • имя кластера
Добавление cluster

Получаем их с помощью aws eks describe-cluster, сохраним в переменную $host (| tr -d '"', что бы убрать кавычки):

[simterm]

$ host=$(aws --profile arseniy eks describe-cluster --name bttrm-eks-dev-0 --query cluster.endpoint | tr -d '"')
$ echo $host
https://example-cluster.yl4.us-east-2.eks.amazonaws.com

[/simterm]

Аналогично для сертификата:

[simterm]

$ cert=$(aws --profile arseniy eks describe-cluster --name bttrm-eks-dev-0 --query cluster.certificateAuthority.data | tr -d '"')

[/simterm]

Создаём файл настроек, добавляем туда блок cluster.

Так как нет опции --certificate-authority-data – делаем грязным хаком (хотя на Github вопрос поднимался ещё в 2018 году – #61572): вместо set-cluster используем просто set, а дальше передадим нужные параметры.

Сначала добавляем сам сервер:

[simterm]

$ kubectl --kubeconfig=newconfig config set-cluster bttrm-eks-dev-0 --server=$host
Cluster "bttrm-eks-dev-0" set.

[/simterm]

А теперь через set – добавляем тело сертификата:

[simterm]

$ kubectl --kubeconfig=newconfig config set clusters.bttrm-eks-dev-0.certificate-authority-data $cert
Property "clusters.bttrm-eks-dev-0.certificate-authority-data" set.

[/simterm]

Проверяем:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0***Qo=
    server: https://example-cluster.yl4.us-east-2.eks.amazonaws.com
  name: bttrm-eks-dev-0
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []
Добавление user

Теперь добавим пользователей.

У меня в AWS CLI настроен профиль arseniy – это рутовый юзер, кроме него есть пользователь iam-bttrm-web-user-1-kubectl, у которого доступы ограничены двумя неймспейсами, и который обращается к EKS, используя AWS IAM Role (см. AWS Elastic Kubernetes Service: RBAC-авторизация через AWS IAM и RBAC группы).

Добавим двух пользователей в конфиг.

Тут используем токен, который можно получить с помощью aws-iam-authenticator, см. Kubernetes: знакомство, часть 4 — аутентификация в AWS EKS, aws-iam-authenticator и AWS IAM:

[simterm]

$ aws-iam-authenticator token -i bttrm-eks-dev-0

[/simterm]

Либо можем посмотреть – как выполняется получение токена сейчас (настроено через aws eks update-kubeconfig):

[simterm]

$ kubectl config view --minify
...
users:
- name: arn:aws:eks:us-east-2:534***385:cluster/bttrm-eks-dev-0
  user:
    exec:
      args:
      - --region
      - us-east-2
      - eks
      - get-token
      - --cluster-name
      - bttrm-eks-dev-0
      command: aws
      env:
      - name: AWS_PROFILE
        value: arseniy

[/simterm]

Т.е.:

[simterm]

$ aws --profile us-east-2 --profile arseniy eks get-token --cluster-name bttrm-eks-dev-0

[/simterm]

Теперь получаем сам токен, сохраняем в переменную $token:

[simterm]

$ token=$(aws --profile us-east-2 --profile arseniy eks get-token --cluster-name bttrm-eks-dev-0 | jq .status.token | tr -d '"')

[/simterm]

Добавляем пользователя arseny-dev-0 в конфиг:

[simterm]

$ kubectl --kubeconfig=newconfig config set-credentials arseny-dev-0 --token=$token 
User "arseny-dev-0" set.

[/simterm]

Проверяем конфиг:

[simterm]

$ cat newconfig 
apiVersion: v1
clusters:
- cluster:
    certificate-authority: LS0***LQo=
    server: https://example-cluster.yl4.us-east-2.eks.amazonaws.com
  name: bttrm-eks-dev-0
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: arseny-dev-0
  user:
    token: k8s-aws-v1.aHR***DE0

[/simterm]

Создание context

И собираем кластер и пользователя в контекст с именем arseny@dev-0:

[simterm]

$ kubectl --kubeconfig=newconfig config set-context arseny@dev-0 --cluster=bttrm-eks-dev-0 --user=arseny-dev-0
Context "arseny@dev-0" created.

[/simterm]

Проверяем конфиг:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: LS0***LQo=
    server: https://example-cluster.yl4.us-east-2.eks.amazonaws.com
  name: bttrm-eks-dev-0
contexts:
- context:
    cluster: bttrm-eks-dev-0
    user: arseny-dev-0
  name: arseny@dev-0
current-context: ""
kind: Config
preferences: {}
users:
- name: arseny-dev-0
  user:
    token: k8s-aws-v1.aHR***DE0

Задаём этот контекст дефолтным:

[simterm]

$ kubectl --kubeconfig=newconfig config use-context arseny@dev-0
Switched to context "arseny@dev-0".

[/simterm]

И пробуем подключиться к кластеру:

[simterm]

$ kubectl --kubeconfig=newconfig get pod
NAME                                  READY   STATUS    RESTARTS   AGE
reloader-reloader-55448df76c-znst5    1/1     Running   0          4d4h
testing-deployment-7b6964f774-cvhmw   1/1     Running   3          3d22h

[/simterm]

Готово.

Ссылки по теме