Basi c Auth не работает при входе в kubernetes - PullRequest
0 голосов
/ 22 января 2020

Я создал pypiserver в кластере kubernetes, я использовал https://hub.docker.com/r/pypiserver/pypiserver docker изображение. Мне нужно создать аутентификацию basi c для сервера, который я создал. Я использовал этот метод https://kubernetes.github.io/ingress-nginx/examples/auth/basic/

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: pypiserver
  labels:
    app: pypiserver
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: 'true'
    ingress.kubernetes.io/auth-type: basic
    ingress.kubernetes.io/auth-secret: secret
    ingress.kubernetes.io/auth-realm: "Authentication Required - ok"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: pypiservice
          servicePort: 8080
  tls:
  - hosts:
    - example.com
    secretName: secret-tls

Но мое имя хоста будет "www.example.com/8080", и я не вижу, что у входа есть какой-либо модуль в кластере kubernetes. Ingress работает нормально, но я не получаю авторизацию для этого хоста. (А также у меня есть http://IP адрес: 8080, который я преобразовал в домен через cloudflare)

Пожалуйста, дайте мне знать, что я делаю неправильно?

1 Ответ

1 голос
/ 24 января 2020

Я точно не знаю, какая у вас nginx входная версия контроллера , но я могу поделиться тем, что сработало для меня. Я воспроизвел его на своем кластере GKE .

Я установил свой nginx входной контроллер, следуя этому руководству. В основном это сводилось к выполнению следующих команд:

Если вы используете GKE, вам нужно инициализировать вашего пользователя как администратор кластера с помощью следующей команды:

kubectl create clusterrolebinding cluster-admin-binding \
  --clusterrole cluster-admin \
  --user $(gcloud config get-value account)

Следующая обязательная команда требуется для всех развертываний.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.27.1/deploy/static/mandatory.yaml

Я использую версию 1.13 в моем GKE, поэтому этот совет также применяется в моем случае:

Совет

Если вы используете версию Kubernetes, предшествующую 1.14, вам нужно изменить kubernetes.io/os на beta.kubernetes.io/os в строке 217 из mandatory.yaml, см. Детали меток.

Но я имел дело с этим совершенно по-другому. В основном вам нужно, чтобы у вашего Nodes была метка kubernetes.io/os=linux, чтобы вы могли просто пометить их. Следующая команда выполнит эту работу:

kubectl label node --all kubernetes.io/os=linux

Затем мы перейдем к Спецификация поставщика c Шаги , который в случае GKE сводится к применению следующие yaml:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.27.1/deploy/static/provider/cloud-generic.yaml

Затем вы можете проверить вашу установку:

Чтобы проверить, запущены ли модули входного контроллера, запустите следующая команда:

kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch

или просто запустить:

kubectl get all -n ingress-nginx

Она также сообщит вам, правильно ли развернуты все необходимые ресурсы.

Далее мы нужно написать наш входной (входной объект / ресурс), содержащий basic-auth related annotations. Я следовал тому же уроку , как указано в вашем вопросе.

Сначала нам нужно создать наш auth файл, содержащий username и хэшированный password:

$ htpasswd -c auth foo
New password: <bar>
New password:
Re-type new password:
Adding password for user foo

Как только мы его получим, нам нужно создать Secret объект, который мы будем использовать во входе:

$ kubectl create secret generic basic-auth --from-file=auth
secret "basic-auth" created

Как только он будет создан, мы можем проверить, все ли прошло хорошо:

$ kubectl get secret basic-auth -o yaml
apiVersion: v1
data:
  auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK
kind: Secret
metadata:
  name: basic-auth
  namespace: default
type: Opaque

Хорошо, пока все хорошо ...

Тогда нам нужно создать наш ingress resource/object.

Мой ingress-with-auth.yaml файл выглядит немного иначе, чем в инструкции , а именно я только что добавил kubernetes.io/ingress.class: nginx, чтобы убедиться, что мой nginx входной контроллер используется вместо встроенного решения GKE:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-with-auth
  annotations:
    kubernetes.io/ingress.class: nginx
    # type of authentication
    nginx.ingress.kubernetes.io/auth-type: basic
    # name of the secret that contains the user/password definitions
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    # message to display with an appropriate context why the authentication is required
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /
        backend:
          serviceName: pypiserver
          servicePort: 80

В вашем примере вам может понадобиться добавить префикс nginx в ваши basic-auth связанные аннотации:

ingress.kubernetes.io/auth-type: basic
ingress.kubernetes.io/auth-secret: secret
ingress.kubernetes.io/auth-realm: "Authentication Required - ok"

, чтобы он выглядел как это:

nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: secret
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - ok"

Сначала я использовал адрес, указанный в моем входном ресурсе (он больше не появляется, когда я добавил kubernetes.io/ingress.class: nginx аннотацию в моем ingress определении:

$ kubectl get ingress 
NAME                HOSTS         ADDRESS   PORTS   AGE
ingress-with-auth   foo.bar.com             80      117m

Когда я пытался получить доступ к pypi-server с использованием этого IP-адреса, он сразу выводил меня на страницу без необходимости какой-либо аутентификации. Но похоже, что если вы не определили правильный класс доступа, вместо него используется значение по умолчанию, поэтому в попрактикуйтесь в определении ingress с auth-basic, детали не принимаются во внимание и не передаются на nginx входной контроллер , который мы установили на одном из предыдущих шагов.

Так какой IP-адрес следует использовать для получить доступ к вашему приложению? Выполните следующую команду, которая покажет вам как CLUSTER-IP (доступ к которому возможен в вашем кластере из любого Pod или Node), так и EXTERNAL-IP вашего nginx входного контроллера :

$ kubectl get service --namespace ingress-nginx 
NAME            TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx   LoadBalancer   10.0.3.220   35.111.112.113   80:30452/TCP,443:30006/TCP   18h

Вы можете разместить в своем кластере много разных сайтов, и все они будут доступны через этот IP. Все они могут быть доступны по умолчанию http 80 порт (или https 443 в вашем случае). Единственная разница между ними будет hostname, который вы передадите в http заголовок вашего http request.

, так как у меня нет домена, указывающего на этот внешний IP-адрес, и я не могу просто зайдите на мой сайт, перейдя по http://foo.bar.com Мне нужно как-то передать hostname, который я запрашиваю с 35.111.112.113 адреса. Это можно сделать несколькими способами:

Я установил в своем браузере Google Chrome ModHeader расширение, которое позволяет мне изменять заголовки http-запроса и устанавливать hostname Я запрашиваю любое значение, которое хочу.

Вы также можете сделать это, используя curl следующим образом:

curl -v http://35.111.112.113 -H 'Host: foo.bar.com' -u 'foo:bar'

Вам будет предложено ввести аутентификацию.

Если вы не поставите флаг -u username:password, вы должны получить 401 Authorization Required.

В основном это все.

Дайте мне знать, помогло ли это вам. Не стесняйтесь задавать дополнительные вопросы, если что-то не совсем понятно.

Еще одна вещь. Если что-то по-прежнему не работает, вы можете начать с подключения к nginx входному контроллеру Pod (сначала проверьте свое имя Pod, введя kubectl get pods -n ingress-nginx):

kubectl exec -ti -n ingress-nginx nginx-ingress-controller-pod /bin/bash

и проверьте содержимое вашего /etc/nginx/nginx.conf файла. Ищите foo.bar.com (или в вашем случае example.com). Он должен содержать аналогичные строки:

auth_basic "Authentication Required - foo";
            auth_basic_user_file /etc/ingress-controller/auth/default-ingress-with-auth.passwd;

Затем проверьте, присутствует ли файл в указанном месте /etc/ingress-controller/auth/default-ingress-with-auth.passwd.

Одна заметка к вашему определению Service. Тот факт, что контейнер pypiserver предоставляет конкретный порт 8080, не означает, что вам нужно использовать этот порт при доступе к нему через вход. В определении Service порт, предоставляемый Container, называется targetPort. Вы должны указать это при определении вашего Service, но сам Service может предоставить совершенно другой порт. Я определил Service, используя следующую команду:

kubectl expose deployment pypiserver --type=LoadBalancer --port=80 --target-port=8080

Обратите внимание, что type должно быть установлено на NodePort или LoadBalancer. Тогда в вашем входном определении вам не нужно использовать 8080, а 80, который является портом, выставленным вашим pypiserver Service. Обратите внимание, что в моем определении ingress object/resource есть servicePort: 80. Ваш example.com домен в cloudflare должен указывать с A record на ваш nginx ingress controller LoadBalancer Service IP (kubectl get svc -n ingress-nginx) без указания каких-либо портов.

...