基本身份验证在kubernetes入口中不起作用

时间:2020-01-22 16:45:51

标签: kubernetes-ingress pypiserver

我已经在kubernetes集群中创建了pypiserver,我使用了https://hub.docker.com/r/pypiserver/pypiserver docker镜像。我需要为我创建的服务器创建基本身份验证。我使用了这种方法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集群中有任何Pod。 Ingress运行正常,但我没有对此主机进行身份验证。 (而且我还有http://IP地址:8080,我通过cloudflare转换为域)

请让我知道我在做错什么吗?

1 个答案:

答案 0 :(得分:4)

我不确定您的 nginx入口控制器版本是什么,但是我可以分享对我有用的版本。我已经在我的GKE 集群上复制了它。

我按照this指南安装了Nginx入口控制器。基本上可以归结为运行以下命令:

如果您使用的是GKE,则需要将用户初始化为 使用以下命令执行cluster-admin:

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

我在GKE上使用的是1.13版本,因此本技巧也适用于我的情况:

提示

如果您使用的是1.14之前的Kubernetes版本,则需要 在第217行的kubernetes.io/os更改为beta.kubernetes.io/os mandatory.yaml,请参阅标签详细信息。

但是我处理的方式大不相同。基本上,您需要Nodes加上kubernetes.io/os=linux标签,以便您可以简单地对其进行标签。以下命令将完成这项工作:

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

然后我们要前往Provider Specific Steps,在GKE的情况下,可以应用以下yaml

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

然后,您可能要verify安装:

要检查入口控制器舱是否已启动,请运行 以下命令:

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

或简单地运行:

kubectl get all -n ingress-nginx

它还会告诉您是否正确部署了所有必需的资源。

接下来,我们需要编写包含basic-auth相关annotations的入口(入口对象/资源)。如您所提,我正在关注same tutorial

首先,我们需要创建包含auth和哈希值username的{​​{1}}文件:

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文件看起来与the instruction中的文件略有不同,即我刚刚添加了ingress-with-auth.yaml以确保使用了我的 nginx入口控制器,而不是内置的GKE解决方案:

kubernetes.io/ingress.class: nginx

在您的示例中,您可能需要在与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

当我尝试使用此IP访问$ kubectl get ingress NAME HOSTS ADDRESS PORTS AGE ingress-with-auth foo.bar.com 80 117m 时,无需任何身份验证即可直接将我带到该页面。但是,如果您没有定义适当的入口类,则看起来像是使用默认值,因此实际上,您的pypi-server定义和ingress的详细信息不会被考虑,也不会传递给<我们在之前的步骤之一中安装了strong> nginx入口控制器。

那么应该使用哪个IP地址访问您的应用程序?运行以下命令,该命令将同时显示您的 nginx入口控制器auth-basic(可以从群集中的任何CLUSTER-IPPod访问Node) / strong>:

EXTERNAL-IP

您基本上可以在群集中托管许多不同的网站,并且所有这些网站都可以通过此IP访问。所有这些都可以在默认的$ 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 端口(或您的情况下为http 80)上使用。它们之间的唯一区别是您在https 443的{​​{1}}标头中传递的hostname

由于我没有指向该外部IP地址的域,并且无法通过访问http来访问我的网站,因此我需要以某种方式传递我从{ {1}}地址。可以通过以下几种方式完成:

我已安装在 Google Chrome浏览器 ModHeader扩展程序中,该扩展程序允许我修改http请求标头并将http request我的requestig设置为所需的任何值。

您也可以使用http://foo.bar.com进行以下操作:

hostname

应该提示您进行身份验证。

如果您不提供35.111.112.113标志,则应该获得hostname

基本上就是帽子。

让我知道它是否对您有帮助。如果有一些不清楚的地方,请随时询问其他问题。

还有一件事。如果仍然无法解决问题,则可以从连接到 nginx入口控制器 curl开始(通过运行curl -v http://35.111.112.113 -H 'Host: foo.bar.com' -u 'foo:bar' 首先检查-u username:password的名称):

401 Authorization Required

并检查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容器专门公开了端口8080的事实并不意味着您在通过入口访问该端口时需要使用此端口。在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时需要指定它,但是Service本身可以公开完全不同的端口。我使用以下命令定义了Container

targetPort

请注意,Service应该设置为ServiceService。然后,在入口定义中,您不必使用kubectl expose deployment pypiserver --type=LoadBalancer --port=80 --target-port=8080 ,而需要使用type NodePort公开的端口LoadBalancer。请注意,我的8080定义中有80。您在 cloudflare 中的pypiserver网域应指向Service servicePort: 80 ingress object/resource IP(example.comA record而不指定任何端口。