Доступ к Jaeger REST API программным способом в OpenShift

Вы когда-нибудь пытались получить программный доступ к Jaeger в OpenShift? Это может быть немного сложно. Иногда это необходимо, потому что вы хотите, например, получить доступ к REST API, который не документирован, потому что предназначен для внутреннего использования. Или вы хотите (как в моем случае) протестировать что-то из пользовательского интерфейса.

Перед прочтением этой статьи

Эта статья о том, как получить доступ к службе запросов Jaeger при использовании стратегии развертывания «production» и развертывании через Jaeger Operator. Некоторые шаги могут быть такими же, если вы используете другие методы развертывания. Даже если вы отключили безопасность, эти шаги могут быть не нужны:

apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
  name: disable-oauth-proxy
spec:
  ingress:
    security: none
Войдите в полноэкранный режим Выход из полноэкранного режима

Кроме того, учтите, что это описание для OpenShift. Поэтому, если вы используете Kubernetes без прокси безопасности или чего-то подобного, вам не нужно будет выполнять эти шаги для доступа к конечным точкам запросов Jaeger. Или (если вы используете другой прокси) вам нужно будет настроить свои учетные данные для доступа к API. Я буду считать, что вы используете OpenShift Oauth Proxy.

Получение доступа к службе запросов Jaeger

Представим, что я развернул следующий CRD (kubectl create -f simple-prod.yaml) в пространстве имен israel:

apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
  name: simple-prod
spec:
  strategy: production
  storage:
    type: elasticsearch
    elasticsearch:
      nodeCount: 1
      resources:
        requests:
          cpu: 200m
          memory: 1Gi
        limits:
          memory: 1Gi
Войти в полноэкранный режим Выход из полноэкранного режима

Результатом выполнения curl против созданного маршрута OpenShift будет ошибка 403:

$ curl https://$(kubectl get route simple-prod -o jsonpath='{.spec.host}') -I
HTTP/1.1 403 Forbidden
Set-Cookie: _oauth_proxy=; Path=/; Domain=simple-prod-israel.apps.mycluster.iblancasa.com; Expires=Thu, 05 May 2022 11:09:34 GMT; HttpOnly; Secure; SameSite
Date: Thu, 05 May 2022 12:09:34 GMT
Content-Type: text/html; charset=utf-8
Set-Cookie: 3f978cf9c2d3ee8d70cad1d11aef9dcd=8d2f11be8db90157d1e73d19b515f187; path=/; HttpOnly; Secure; SameSite=None
Вход в полноэкранный режим Выйти из полноэкранного режима

Если вы не указали опцию -I для получения только заголовков, вы получите полный HTML-код с веб-страницы регистрации. Давайте посмотрим, как получить «правильный» ответ от сервера.

Первым шагом будет создание учетной записи службы. Из документации OpenShift:

Сервисный аккаунт — это аккаунт OpenShift Container Platform, который позволяет компоненту напрямую обращаться к API.

Я назову свой сервисный аккаунт «automation-access». Итак, мой файл sa.yaml содержит:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: automation-access
Войти в полноэкранный режим Выйти из полноэкранного режима

И создадим его в OpenShift с помощью kubectl create -f sa.yaml:

$ kubectl create -f sa.yaml
serviceaccount/automation-access created
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь нам нужно создать Cluster Role Binding. Из документации Kubernetes:

Привязка роли предоставляет права, определенные в роли, пользователю или набору пользователей. Она содержит список субъектов (пользователей, групп или учетных записей служб) и ссылку на предоставляемую роль. RoleBinding предоставляет разрешения в пределах определенного пространства имен, в то время как ClusterRoleBinding предоставляет такой доступ в масштабах всего кластера.

В качестве упрощения мы можем использовать привязки ролей кластера для установления отношений между, например, учетной записью службы и ролью кластера. В нашем случае будет достаточно system:auth-delegator для учетной записи службы jaeger-operator из пространства имен observability и cluster-reader для учетной записи службы, которую мы создали ранее. Наш файл crb.yaml будет похож на этот:

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jaeger-operator-with-auth-delegator
  namespace: observability
subjects:
- kind: ServiceAccount
  name: jaeger-operator
  namespace: observability
roleRef:
  kind: ClusterRole
  name: system:auth-delegator
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: automation-access-bind
subjects:
- kind: ServiceAccount
  name: automation-access
  namespace: israel
roleRef:
  kind: ClusterRole
  name: cluster-reader
  apiGroup: rbac.authorization.k8s.io
Вход в полноэкранный режим Выход из полноэкранного режима

И применим его к нашему кластеру OpenShift, используя: kubectl create -f crb.yaml:

$ kubectl create -f crb.yaml
clusterrolebinding.rbac.authorization.k8s.io/jaeger-operator-with-auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/automation-access-bind created
Вход в полноэкранный режим Выход из полноэкранного режима

Наконец, нам нужно установить некоторые дополнительные опции для нашего развертывания Jaeger (jaeger-sar.yaml):

apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
  name: simple-prod
spec:
  query:
    options:
      query.bearer-token-propagation: true
  ingress:
    openshift:
      sar: '{"namespace": "israel", "resource": "pods", "verb": "get"}'
      delegateUrls: '{"/":{"namespace": "israel", "resource": "pods", "verb": "get"}}'
    options:
      pass-access-token: true
      pass-user-bearer-token: true
      scope: "user:info user:check-access"
      pass-basic-auth: false
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем мы применим его с помощью kubectl apply -f jaeger-sa.yaml:

$ kubectl apply -f jaeger-sar.yaml
Warning: resource jaegers/simple-prod is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
jaeger.jaegertracing.io/simple-prod configured
Войти в полноэкранный режим Выход из полноэкранного режима

Хорошо! Мы почти у цели. Следующим шагом будет получение маркера, который позволит нам получить программный доступ к службе запросов Jaeger. Чтобы получить токен, нам нужно узнать имя используемого секрета Kubernetes. Мы можем получить эту информацию с помощью следующей команды:

$ kubectl get sa automation-access -o jsonpath='{.secrets}'
[{"name":"automation-access-token-q2p2x"},{"name":"automation-access-dockercfg-xvzsq"}]
Войти в полноэкранный режим Выйти из полноэкранного режима

В результате мы получим имена двух секретов. Мы будем использовать тот, который называется auomation-access-token-<ID>. Если вы используете yq, команда может быть такой:

$ kubectl get sa automation-access -o yaml | yq eval '.secrets[] | select( .name == "*-token-*")'.name 
automation-access-token-q2p2x
Войти в полноэкранный режим Выйти из полноэкранного режима

И, наконец, мы извлекаем токен из секрета:

$ kubectl get secret automation-access-token-q2p2x -o jsonpath='{.data.token}' |  base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6Iks3TXcwUWhyb3BVdUVJblhkQmVQT25Fek1KVVlfa2RPV3dDZWpJVXpmekUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJpc3JhZWwiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoiYXV0b21hdGlvbi1hY2Nlc3MtdG9rZW4tcTJwMngiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYXV0b21hdGlvbi1hY2Nlc3MiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI1NGY1ZDE0MC1lMDEwLTQ5NWYtYWE4Yy0wNmQ3ZjIwNjg3OGIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6aXNyYWVsOmF1dG9tYXRpb24tYWNjZXNzIn0.J5USv-olD1vU0A5tL8TT1SDoH-jf5f58hSIEPnkkiZzTiOjHHx2Vj2v1p0bm26epfTQwLV3TfIsgcsV7tnpC0cR64MmDQe9EuBtNonJqV45nTkSoboWuBfeSxXqjk7Tuj_bcZcutcA0vsVHzAglb-Z0wavx9ETfQJueDWTzF6Cry5HxVxYn6ytogHfbaEgiLN9HNeZBWW4xi7JAzY-2viECrFq1yEIJKzWDihZScFkyX2fu1UDpFLH2ewA8N6bdqSd5FTEna0JS0e8yxQcGo-oXykDW2G_YcLDBSrCpQaji390FgMp_6dEl1yHSazGgCaKwulwOU4Rr6usf807mdBQ
Войти в полноэкранный режим Выйти из полноэкранного режима

Эта команда получает токен из секрета и декодирует его. Нам нужно указать этот токен в заголовке Authorization при выполнении вызова curl:

$ export TOKEN=$(kubectl get secret automation-access-token-q2p2x -o jsonpath='{.data.token}' |  base64 -d)
$ curl https://$(kubectl get route simple-prod -o jsonpath='{.spec.host}') -I -H "Authorization: Bearer $TOKEN"
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Date: Thu, 05 May 2022 12:44:06 GMT
Gap-Auth: system:serviceaccount:israel:automation-sa@cluster.local
Gap-Upstream-Address: localhost:16686
Vary: Accept-Encoding
Set-Cookie: 3f978cf9c2d3ee8d70cad1d11aef9dcd=2e6b6fcf2050268c74e1aabcf71e9bab; path=/; HttpOnly; Secure; SameSite=None
Cache-control: private
Войти в полноэкранный режим Выход из полноэкранного режима

Спасибо за прочтение! Надеюсь, эта статья помогла вам! 🙂

Оцените статью
Procodings.ru
Добавить комментарий