Многие пользователи Яндекс облака применяют сервис Managed Service for Kubernetes. При этом учетные записи сотрудников организаций хранятся на контроллерах домена Windows. Удобно и правильно логиниться в Kubernetes учетными записями из Windows-домена, оптимизируя ресурсы DevOps и сисадминов. Но без специального инструмента сделать это нельзя.
Меня зовут Дмитрий Глушков, я системный инженер эксплуатации в Lamoda Tech. Мои поиски удобного решения задачи привели к программе Pinniped. Она поможет использовать учетные записи Windows AD для предоставления и контроля доступа сотрудников в Kubernetes. Разберемся, как ее установить и использовать.
Что такое Pinniped
Pinniped (Пиннипед) – это программа, которая позволяет логиниться в Kubernetes-кластеры, в которых у вас нет доступа к их мастер-нодам (пользуясь программой kubectl и специальным файлом-шаблоном кубконфига). Вы можете использовать учетки от разных провайдеров учетных записей (identity providers), например, MS Windows Active Directory. Это подходящее решение, например, в Яндекс облаке для их управляемых куб-кластеров.
Pinniped состоит из двух частей – супервизора и консьержа. Супервизор нужен, чтобы можно было залогиниться с учеткой из Active Directory, а консьерж принимает все запросы в куб-апи и проверяет, что они корректно авторизованы супервизором, и если да, то проксирует их в куб-апи. Обе части – это просто поды в кубе.
Чтобы получить работающую систему, необходимо:
-
подготовить необходимые ресурсы;
-
установить и настроить Pinniped;
-
настроить права в куб-кластере;
-
создать файл шаблона кубконфига;
-
научить пользователей работать с Pinniped.
Звучить объемно, но выполнимо. Поехали!
1. Подготовка к установке
Предполагается, что у вас есть следующие ресурсы, и вы можете ими управлять:
-
аккаунт в Яндекс облаке, в котором есть работающий managed куберкластер;
-
контроллер домена Windows, к которому есть сетевой доступ из Яндекс облака;
-
tls-certificate, который вы можете создать;
-
DNS-запись, которую вы можете создать, и которая будет работать у вас в сети и показывать на IP-адрес в Яндекс облаке.
2. Установка
Просто создаем в нашем куб-кластере объекты из ямл-файлов от создателей Pinniped:
kubectl apply -f https://get.pinniped.dev/v0.32.0/install-pinniped-supervisor.yaml
kubectl apply -f https://get.pinniped.dev/v0.32.0/install-pinniped-concierge-crds.yaml
kubectl apply -f https://get.pinniped.dev/v0.32.0/install-pinniped-concierge-resources.yaml
2.1 Load balancer для консьержа
После выполнения этих трех команд в куб-кластере в неймспейсе pinniped-concierge
появится сервис с именем pinniped-concierge-impersonation-proxy-load-balancer
. Мы будем использовать этот сервис как лоад-балансер, который будет принимать запросы для Pinniped-консьержа. Чтобы этот сервис стал работать как лоад-балансер в Яндекс облаке, надо в его конфиге добавить две аннотации:
yandex.cloud/load-balancer-type: internal
yandex.cloud/subnet-id: id-подсети
Тут internal
– это тип лоад-балансера NLB в ЯО, такой как в документации Яндекс облака, а id-подсети
– это подсетка в Яндекс облаке, в которой будет создан лоад-балансер, как только мы добавим эти две аннотации и сохраним конфиг. Покажу только важную для нас сейчас часть конфигурации, неважные строки пропущены. Вот что должно получиться в итоге:
apiVersion: v1 kind: Service metadata: annotations: . . . yandex.cloud/load-balancer-type: internal yandex.cloud/subnet-id: id-подсети labels: app: pinniped-concierge name: pinniped-concierge-impersonation-proxy-load-balancer namespace: pinniped-concierge . . . spec: . . .
Как только облако создаст лоад-балансер, у него появится IP-адрес, и можно проверить, что он работает. Вот ожидаемый ответ:
% curl -k https://ip-addr-of-load-balancer-of-concierge { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "forbidden: User \"system:anonymous\" cannot get path \"/\": decision made by impersonation-proxy.concierge.pinniped.dev", "reason": "Forbidden", "details": {}, "code": 403 }
2.2 Load balancer для супервизора
Делаем сервис+NLB для супервизора в той же подсетке, что и у консьержа:
apiVersion: v1 kind: Service metadata: annotations: yandex.cloud/load-balancer-type: internal yandex.cloud/subnet-id: id-подсети-из-пункта-2.1 name: pinniped-supervisor-loadbalancer namespace: pinniped-supervisor spec: ports: - targetPort: 8443 port: 443 protocol: TCP selector: app: pinniped-supervisor type: LoadBalancer
Как только облако создаст лоад-балансер для супервизора, у него появится IP-адрес. Надо сделать DNS-запись, указывающую на этот IP-адрес:
pinniped-supervisor.ваш_домен.да → ip-адрес лоад-балансера супервизора.
2.3 Куб-секрет с TLS-сертификатом супервизора
Супервизор обязательно требует использовать TLS-защищенное подключение к нему, поэтому создадим куб-секрет, и положим туда сертификат и приватный ключ. TL-сертификат надо создать, он должен удостоверять url pinniped-supervisor.ваш_домен.да.
apiVersion: v1 data: tls.crt: LS0tLS1CRUdJTiBDRVJUS... tls.key: LS0tLS1CRUdJTiBQUkl... kind: Secret metadata: name: supervisor-lb-tls-cert namespace: pinniped-supervisor type: kubernetes.io/tls
2.4 FederationDomain
Создаем объект, который нужен для указания url, на котором будет работать Cупервизор, и тут же указываем секрет с TLS-сертификатом для этого url.
apiVersion: config.supervisor.pinniped.dev/v1alpha1 kind: FederationDomain metadata: name: my-fd namespace: pinniped-supervisor spec: issuer: https://pinniped-supervisor.ваш_домен.да tls: secretName: supervisor-lb-tls-cert
После этого шага выполнение запроса типа:
% curl https://pinniped-supervisor.ваш_домен.да
должно показывать, что TLS-сертификат правильный.
2.5 Секрет для подключения в домену Active Directory
Создаем секрет для подключения в домену AD. Пароль обязательно должен быть в кавычках. В домене Windows надо создать учетку, которая может читать учетные записи и группы, и использовать её.
apiVersion: v1 kind: Secret metadata: name: active-directory-bind-credentials namespace: pinniped-supervisor type: kubernetes.io/basic-auth stringData: # The dn (distinguished name) of your Active Directory bind account. username: CN=s-pinniped,OU=Service Accounts,DC=office,DC=ru # The password of your Active Directory bind account. password: "ТУТПАРОЛЬОТУЧЁТКИ..."
2.6 ActiveDirectoryIdentityProvider
Продолжаем: делаем ActiveDirectoryIdentityProvider. В этом, например, LDAP-фильтр проверяет, что учетка юзера есть в AD группе admins и/или в AD группе developers. В поле certificateAuthorityData надо записать сертификат контроллера домена, только открытую часть. Используйте подсказку по фильтрам LDAP.
apiVersion: idp.supervisor.pinniped.dev/v1alpha1 kind: ActiveDirectoryIdentityProvider metadata: name: ad-idp namespace: pinniped-supervisor spec: host: ad-dc1.office.ru userSearch: base: "OU=Users,OU=Offices,DC=office,DC=ru" filter: "&(objectClass=person)(userPrincipalName={})(|(memberOf=CN=admins,OU=Groups,DC=office,DC=ru)(memberOf=CN=developers,OU=Groups,DC=office,DC=ru))" attributes: username: "sAMAccountName" groupSearch: base: "ou=Groups,DC=office,DC=ru" filter: "&(objectClass=group)(member={})" tls: certificateAuthorityData: LS0t... bind: secretName: active-directory-bind-credentials
2.7 JWTAuthenticator
Идем дальше. В issuer пишем url лоад-балансера супервизора. В audience не принципиально, что будет написано, но нужно, чтобы для разных куб-кластеров это значение было разным. В certificateAuthorityData кладем сертификат от супервизора, только открытую часть.
apiVersion: authentication.concierge.pinniped.dev/v1alpha1 kind: JWTAuthenticator metadata: name: jwt-auth spec: issuer: https://pinniped-supervisor.ваш_домен.да audience: from-pinniped tls: certificateAuthorityData: LS0t...
Установка закончена.
3. Конфигурация Kubernetes
Допустим, мы хотим, чтобы после успешного логина сотрудник мог в кубере успешно выполнять команды типа k get pods, k logs и подобные им – в некоторых заранее разрешенных неймспейсах.
-
Для этого создадим в нашем кубе ClusterRole, и будем её назначать (bind) на неймспейсы и группы AD.
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: pinniped-view rules: - apiGroups: [""] resources: ["pods", "configmaps"] verbs: ["get", "list"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list"] - apiGroups: [""] resources: ["pods/log"] verbs: ["get"]
2. Для каждого неймспейса, доступ в который мы хотим разрешить, делаем RoleBinding, который будет связывать кластер-роль с неймспейсом и с AD-группой, например, для неймспейса, который называется «util» и группы AD developers.
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pinniped-view-util-developers namespace: util subjects: - kind: Group name: developers@office.ru apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: pinniped-view apiGroup: rbac.authorization.k8s.io
Чтобы наши пользователи могли логиниться в кубер-кластер, им надо предоставить файл – шаблон кубконфига, который будет направлять логин в Pinniped.
Чтобы сделать этот файл, на свой комп ставим Pinneped-CLI. Логинимся в целевой куб-кластер как обычно, например:
kubectl config use-context ваш_кластер
Затем выполняем команду:
pinniped get kubeconfig > kubeconfig-template.yml
Теперь в kubeconfig-template.yml файле у нас есть шаблон для авторизации. Этот файл раздаем коллегам, коллеги устанавливают себе Pinniped и используют этот файл как обычный куб-конфиг файл. В файле нет никакой конфиденциальной информации типа паролей и токенов.
5. Пользуемся логином
Для работы с кластером коллеги будут выполнять подобную команду:
kubectl -n util get pods --kubeconfig kubeconfig-template.yml
Появится приглашение на ввод имени пользователя Username – тут надо написать свою почту с доменом.
Дальше появится приглашение на ввод пароля – пишем свой пароль домена Windows.
Если все работает правильно, то должен показаться список подов в неймспейсе util, примерно такой:
Всё, мы настроили логин в кубернетес с учеткой из домена Windows.
Заключение
Описанный инструмент помогает избавиться от рутинной операции создания новых учеток для использования в Kubernetes. При этом Pinniped оказался не самым популярным – чтобы его найти, пришлось спуститься в самые глубины CNCF Landscape. Тем ценнее навык работы с ним.
Надеюсь, эта инструкция была для вас полезной. Если вы решали подобную задачу иначе – поделитесь в комментариях.
ссылка на оригинал статьи https://habr.com/ru/articles/846000/
Добавить комментарий