Клиент Python Kubernetes: проблема аутентификации
Мы используем клиент Python kubernetes (4.0.0) в сочетании с движком Google kubernetes (master + nodepools run k8s 1.8.4) для периодического планирования рабочих нагрузок на kubernetes. Упрощенная версия скрипта, который мы используем для создания модуля, прикрепления к журналам и отчета о конечном состоянии модуля, выглядит следующим образом:
config.load_kube_config(persist_config=False)
v1 = client.CoreV1Api()
v1.create_namespaced_pod(body=pod_specs_dict, namespace=args.namespace)
logging_response = v1.read_namespaced_pod_log(
name=pod_name,
namespace=args.namespace,
follow=True,
_preload_content=False
)
for line in logging_response:
line = line.rstrip()
logging.info(line)
status_response = v1.read_namespaced_pod_status(pod_name, namespace=args.namespace)
print("Pod ended in status: {}".format(status_response.status.phase))
Все работает довольно хорошо, однако у нас возникают некоторые проблемы с аутентификацией. Аутентификация происходит по умолчанию gcp
auth-провайдера, для которого я получил начальный токен доступа, запустив kubectl container cluster get-credentials
вручную по планировщику. На некоторых случайных таймфреймах некоторые вызовы API приводят к ответу 401 от сервера API. Я предполагаю, что это происходит всякий раз, когда токен доступа истек, и сценарий пытается получить новый токен доступа. Однако бывает так, что в планировщике одновременно выполняется несколько сценариев, что приводит к получению нового ключа API несколько раз, из которых только один остается действительным. Я опробовал несколько способов решить проблему (используйте persist_config=True
, повторите попытку 401 после перезагрузки конфигурации,...) без какого-либо успеха. Так как я не полностью осознаю, как работает аутентификация gcp и конфиг клиента Python kubernetes (и документации для обоих довольно мало), я немного оставлен в неведении.
Должны ли мы использовать другой метод аутентификации вместо gcp
Auth-провайдер? Это ошибка в клиенте Python kubernetes? Должны ли мы использовать несколько файлов конфигурации?
2 ответа
В конце концов, мы решили эту проблему, используя аутентификацию на основе токенов на предъявителя, вместо того, чтобы полагаться на метод аутентификации gcloud по умолчанию.
Вот шаги, которые я сделал для достижения этой цели.
Сначала создайте учетную запись службы в требуемом пространстве имен, создав файл со следующим содержимым.
apiVersion: v1
kind: ServiceAccount
metadata:
name: <name_of_service_account>
Затем используйте этот файл для создания учетной записи службы
kubectl create -f <path_to_file> --namespace=<namespace_name>
С каждой учетной записью службы связан токен-носитель, который можно использовать для аутентификации. Этот токен на предъявителя автоматически устанавливается как секрет в пространство имен. Чтобы узнать, что это за токен, сначала найдите название секрета (имеет вид <service_account_name>-token-<random_string>
), а затем используйте это имя для доступа к содержанию.
# To search for out service account's token name
kubectl get secrets --namespace=<namespace_name>
# To find the token name
kubectl describe secret/<secret_name>
После этого вы должны узнать IP-адрес сервера API и сертификат Cluster CA кластера kubernetes. Это можно сделать, перейдя на страницу сведений о движке kubernetes в облачной консоли Google. Скопируйте содержимое сертификата в локальный файл.
Теперь вы можете использовать токен-носитель для аутентификации через Python-клиент kubernetes следующим образом:
from kubernetes import client
configuration = client.Configuration()
configuration.api_key["authorization"] = '<bearer_token>'
configuration.api_key_prefix['authorization'] = 'Bearer'
configuration.host = 'https://<ip_of_api_server>'
configuration.ssl_ca_cert = '<path_to_cluster_ca_certificate>'
v1 = client.CoreV1Api(client.ApiClient(configuration))
У меня есть контейнер python, использующий клиент Kubernetes, и я искал способ, чтобы он использовал учетную запись службы при выполнении в кластере, но загружал смонтированную конфигурацию куба при выполнении локально. Мне потребовалось время, чтобы найти
load_incluster_config()
, который будет автоматически настраиваться на основе учетной записи службы контейнера при выполнении в кластере. Теперь я включаю env var при локальном запуске. Это может быть вам полезно:
https://github.com/kubernetes-client/python/blob/master/examples/in_cluster_config.py
Для аутентификации на вашем сервере API вы можете использовать управление доступом на основе ролей (RBAC), которое может определять ряд ролей для управления аутентификацией и доступом к вашему API.
Это основано на предоставлении ролей и ролей кластера различным пользователям или учетным записям служб с помощью привязок. Эти роли включают в себя некоторые правила, которые представляют собой набор разрешений и могут быть определены для работы с пространством имен (ролями) или целым кластером (ролями кластера).
Первый шаг для включения RBAC - запустить сервер API со следующей опцией:
--authorization-mode=RBAC
Вы можете определить конкретные роли с помощью команды kubectl. Например, если вы хотите предоставить роль кластера администратора пользователю (например, Бобу) в пространстве имен (например, acme), вы можете использовать эту команду:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
Вы также можете определить роль кластера, чтобы пользователь (например, root) имел права администратора для всего кластера:
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
Если вы хотите использовать вместо этого служебные учетные записи, вы можете использовать такую команду для предоставления ролей служебной учетной записи:
kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace
Вы можете проверить здесь для получения дополнительной информации о RBAC, включая все возможные роли и роли кластера, которые вы можете предоставить своей учетной записи пользователя или службы.