1

我在 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”,我没有看到 ingress 在 kubernetes 集群中有任何 pod。Ingress 运行良好,但我没有获得此主机的身份验证。(而且我还有http://IP address :8080 我通过 cloudflare 转换为域)

请让我知道我做错了什么?

4

1 回答 1

5

我不确切知道您的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

我在我的 GKE 上使用 1.13 版本,所以这个技巧也适用于我的案例:

小费

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

但我的处理方式完全不同。基本上你需要你Nodeskubernetes.io/os=linux标签,这样你就可以简单地给它们贴上标签。以下命令将完成这项工作:

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

然后我们将前往提供者特定步骤,如果是GKE,则归结为应用以下内容yaml

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

然后您可能想要验证您的安装:

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

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

或简单地运行:

kubectl get all -n ingress-nginx

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

接下来我们需要编写包含basic-auth相关的入口(入口对象/资源) 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中的文件略有不同,即我刚刚添加以确保使用我的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

$ 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(可以在集群中从任何Podor访问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传入.httphttp request

由于我没有指向此外部 IP 地址的域,并且无法通过访问来简单地访问我的网站,http://foo.bar.com因此我需要以某种方式传递hostname我从地址请求的35.111.112.113地址。可以通过以下几种方式完成:

我在我的Google Chrome 浏览器中安装了 ModHeader扩展程序,它允许我修改我的 http 请求标头并将hostnameI'm requestig 设置为我想要的任何值。

您也可以使用curl以下方法:

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

应提示您进行身份验证。

如果你不提供-u username:password标志,你应该得到401 Authorization Required.

基本上帽子就是全部。

让我知道它是否对您有帮助。如果某些事情不完全清楚,请不要犹豫,提出其他问题。

还有一件事。如果某些东西仍然不起作用,您可以从附加到您的nginx 入口控制器 开始(首先通过运行Pod检查您的名称):Podkubectl 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对您的定义的注释。容器专门公开端口 8080的事实pypiserver并不意味着您在通过入口访问它时需要使用此端口。在Service定义中,由 暴露的端口Container被称为targetPort。您需要在定义时指定它,ServiceService它本身可以公开完全不同的端口。我Service使用以下命令定义了我的:

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

请注意,type应设置为NodePortLoadBalancer。然后在您的入口定义中,您不必使用8080,而是80您的pypiserver Service. 请注意,servicePort: 80在我的ingress object/resource定义中有。您example.comcloudflare中的域应该指向A record您的nginx ingress controller LoadBalancer ServiceIP ( kubectl get svc -n ingress-nginx),而不指定任何端口。

于 2020-01-24T14:51:46.847 回答