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

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

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

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

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

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

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

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

Например:

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

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

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

В этом посте рассмотрим из чего файл настроек состоит, как манипулировать данными в нём, и в конце — сгенерируем файл настроек 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:

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

Процессы аутентификации и авторизации в 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-сервера:

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.

Проверяем содержимое 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:

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

В --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 — объединяем созданные ранее кластер и пользователя, плюс задаём дефолтный для юзера неймспейс в кластере:

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.

Проверяем:

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:

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

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

  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 '"', что бы убрать кавычки):

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

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

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

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

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

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

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

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

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

Проверяем:

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:

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

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

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

Т.е.:

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

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

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

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

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

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

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
Создание context

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

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

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

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

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

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

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

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

Готово.

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