Мы в нашей организации, как и многие, переходим на отечественные продукты, коснулось это и среды контейнеризации. За годы эксплуатации мы нежно полюбили OKD (Openshift) и очень расстраивались в ванильном kubernetes, подмечая отсутствие ставших уже привычными вещей. Однако OKD состоит из свободно распространяемых компонентов, а значит что-то да можно переиспользовать, например, web-консоль. Ее то мы и решили перенести в насколько это возможной полноте функционала. Существующие гайды обычно покрывают лишь установку самой консоли, нам же хотелось использовать и SSO и дополнительные элементы консоли — каталог ссылок и объявления в заголовке.
Итак, нам потребуется:
-
Сертификаты для обслуживания web-console
-
OIDC провайдер. В нашем случае Keycloak
-
Кластер kubernetes
-
Образ openshift-console из quay.io
-
Репозитарий с CRD для web-консоли
-
cli от openshift (опционально, но команды cli придется адаптировать самостоятельно)
1. Настраиваем клиент в OIDC провайдере
Создаем клиент keycloak. Все изображения с примерами настройки спрячу под спойлер.
-
client ID:
kubernetes
-
root url:
<url консоли>
-
valid redirect urls:
/*
-
Client authentication:
on
-
Сохраняем клиент
-
Внутри клиента, во вкладке client scopes добавляем audience
-
переходим в scope kubernetes-dedicated (либо <cliendID>-dedicated если ID другой)
-
Жмем
Configure a new mapper
-
Выбираем тип:
Audience
-
прописываем имя и выбираем included client audience:
kubernetes
(cliendID) -
Add to ID token:
on
-
Остальные параметры оставляем по умолчанию, жмем save
-
-
В глобальной вкладке client scopes (слева) добавляем Groups:
-
name: groups
-
Type: Default
-
Переходим во вкладку Mappers, жмем Configure a new mapper
-
выбираем Group Membership
-
name: groups
-
Token Claim Name: groups
-
Full group path: off
-
-
Сохраняем изменения
-
Скрытый текст
Важно: Это рабочий конфиг, однако после необходимо захарденить клиент согласно политикам безопасности в вашей организации.
Сохраняем конфиг, сохраняем себе Client ID
и Client Secret
(вкладка Credentials). Также нам потребуется Issuer, взять его можно из раздела realm settings -> OpenID Endpoint Configuration.
Пример настройки:
2. Настройка kubernetes
Для того, чтобы консоль могла выполнять действия от имени пользователя, необходимо чтобы кластер kuebrentes мог аутентифицировать запросы с использование вашего jwt-токена. Наш кластер разворачивался через kubeadm, для других инсталляций локации конфигов могут отличаться
-
На ВМ с kubernetes apiserver необходимо добавить сертификат, который используется в keycloak по пути:
/etc/kubernetes/pki/oidc-ca.crt
-
Добавляем конфиг oidc в kubernetes apiserver:
/etc/kubernetes/manifests/kube-apiserver.yaml
... spec: containers: - command: - kube-apiserver ... - --oidc-issuer-url=https://auth.keycloak.myinfra.zone/auth/realms/myrealm - --oidc-client-id=kubernetes - --oidc-username-claim=preferred_username - --oidc-groups-claim=groups - --oidc-ca-file=/etc/kubernetes/pki/oidc-ca.crt - --oidc-username-prefix=- ...
-
oidc-issuer-url — урл из OpenID Endpoint Configuration
-
oidc-client-id — client id
-
oidc-username-claim — атрибут из jwt по которому определяется логин пользователя
-
oidc-groups-claim — claim, в котором содержится список групп
-
oidc-ca-file — путь до файла с сертификатом keycloak
-
oidc-username-prefix — префикс, который добавляется к логину пользователя внутри kubernetes (например, для rolebinding)
После перезапуска подов должны подтянуться новые настройки, проверить доступ можно сгенерировав access токен и обратившись с ним в kube-api
Скрытый текст
curl -k -L -X POST 'https://auth.keycloak.myinfra.zone/auth/realms/myrealm/protocol/openid-connect/token' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'client_id=kubernetes' \ --data-urlencode 'grant_type=password' \ --data-urlencode 'client_secret=<KUBERNETES_CLIENT_ID_TOKEN>' \ --data-urlencode 'scope=openid' \ --data-urlencode 'username=<KEYCLOAK_USER>' \ --data-urlencode 'password=<KEYCLOAK_USER_PASSWORD>'
oc login --token=ACCESS_TOKEN_HERE --server=https://apiserver_url:6443
3. Настройка openshift-console в кластере
Нам остается только грамотно настроить манифесты:
Скрытый текст
Вспомогательные манифесты, namespaces, serviceaccouns, clusterrolebindings:
--- kind: Namespace apiVersion: v1 metadata: name: openshift-console --- kind: Namespace apiVersion: v1 metadata: name: openshift-console-user-settings --- kind: ServiceAccount apiVersion: v1 metadata: name: console namespace: openshift-console --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: okd-console-role subjects: - kind: ServiceAccount name: console namespace: openshift-console roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin ---
Сертификаты для https консоли и ca для доверия к keycloak:
kind: Secret apiVersion: v1 metadata: name: console-serving-cert namespace: openshift-console data: ca.crt: >- ca_cert_base_64 tls.crt: >- public_cert_base_64 tls.key: >- private_cert_base_64 type: kubernetes.io/tls
Deployment:
Скрытый текст
--- kind: Deployment apiVersion: apps/v1 metadata: name: console namespace: openshift-console labels: app: console component: ui spec: replicas: 1 selector: matchLabels: app: console component: ui template: metadata: name: console creationTimestamp: null labels: app: console component: ui spec: nodeSelector: node-role.kubernetes.io/control-plane: '' restartPolicy: Always serviceAccountName: console schedulerName: default-scheduler affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: component operator: In values: - ui topologyKey: kubernetes.io/hostname terminationGracePeriodSeconds: 30 securityContext: {} containers: - name: console image: quay.io/openshift/origin-console:4.12.0 command: - /opt/bridge/bin/bridge - '--public-dir=/opt/bridge/static' - '--control-plane-topology-mode=HighlyAvailable' - '--k8s-public-endpoint=https://kubernetes_apserver:6443' - '--listen=http://[::]:8080' - '--k8s-auth=oidc' - '--k8s-mode=in-cluster' - '--tls-cert-file=/var/serving-cert/tls.crt' - '--tls-key-file=/var/serving-cert/tls.key' - '--base-address=https://console.apps.myinfra.zone' - '--user-auth=oidc' - '--user-auth-oidc-ca-file=/var/serving-cert/ca.crt' - '--user-auth-oidc-client-id=kubernetes' # the same as for kubernetes apiserver client - '--user-auth-oidc-client-secret=oidc_client_from_keycloak' - '--user-auth-logout-redirect=https://console.apps.myinfra.zone' - >- -user-auth-oidc-issuer-url=https://auth.keycloak.myinfra.zone/auth/realms/myrealm resources: {} volumeMounts: - name: console-serving-cert readOnly: true mountPath: /var/serving-cert terminationMessagePath: /dev/termination-log terminationMessagePolicy: File readinessProbe: httpGet: path: /health port: 8080 scheme: HTTP timeoutSeconds: 1 periodSeconds: 10 successThreshold: 1 failureThreshold: 3 livenessProbe: httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 150 timeoutSeconds: 1 periodSeconds: 10 successThreshold: 1 failureThreshold: 3 ports: - name: https containerPort: 8443 protocol: TCP - name: http containerPort: 8080 protocol: TCP imagePullPolicy: IfNotPresent serviceAccount: console volumes: - name: console-serving-cert secret: secretName: console-serving-cert defaultMode: 420 dnsPolicy: ClusterFirst strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 3 revisionHistoryLimit: 10 progressDeadlineSeconds: 600
Сервис и ingress:
--- kind: Service apiVersion: v1 metadata: name: console namespace: openshift-console spec: ports: - name: https protocol: TCP port: 443 targetPort: 8443 - name: http protocol: TCP port: 80 targetPort: 8080 internalTrafficPolicy: Cluster type: ClusterIP selector: app: console component: ui --- kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: okd-console namespace: openshift-console annotations: nginx.ingress.kubernetes.io/affinity: cookie nginx.ingress.kubernetes.io/force-ssl-redirect: 'true' nginx.ingress.kubernetes.io/ssl-passthrough: 'false' spec: ingressClassName: nginx tls: - secretName: console-serving-cert rules: - host: console.apps.myinfra.zone http: paths: - path: / pathType: Prefix backend: service: name: console port: number: 80
В зависимости от ваших требований можно включить ssl-passthrough, не забыв при этом поменять listen port в приложении и поправить раздел rules у ingress, однако я столкнулся с проблемой, что при такой конфигурации не работает > 1 пода — трафик round-robin отправляется на поды и возможны потери сессии.
На этом этапе у вас должна запуститься веб-консоль, при входе должно произойти перенаправление в SSO. После входа запросы будут выполняться от аутентифицированного пользователя.
4. Включаем console links, ConsoleNotification, ConsoleCLIDownload
Все что нам надо, это взять из репозитария манифесты CRD и применить их в кластере:
Скрытый текст
oc apply -f https://raw.githubusercontent.com/openshift/api/refs/heads/release-4.12/console/v1/0000_10_consolelink.crd.yaml oc apply -f https://raw.githubusercontent.com/openshift/api/refs/heads/release-4.12/console/v1/0000_10_consoleclidownload.crd.yaml oc apply -f https://raw.githubusercontent.com/openshift/api/refs/heads/release-4.12/console/v1/0000_10_consolenotification.crd.yaml
При желании можно применить и другие CRD console<type> из репозитория. Консоль подхватит и их.
После чего можно создавать соответствующие объекты (API Explorer -> group: console.openshift.io) и наблюдать эффект:
Вот и все, вы запустили web-консоль OKD с авторизацией, оповещениями и настраиваемыми ссылками!
ссылка на оригинал статьи https://habr.com/ru/articles/850864/
Добавить комментарий