我不确切知道您的 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你的安装:
要检查入口控制器 pod 是否已启动,请运行
以下命令:
kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
或者直接运行:
kubectl get all -n ingress-nginx
它还会告诉您是否正确部署了所有必需的资源。
接下来我们需要编写包含basic-auth相关annotations的入口(入口对象/资源)。如您的问题所述,我正在关注same tutorial。
首先我们需要创建包含username 和散列password 的auth 文件:
$ 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 文件看起来与the instruction 中的文件略有不同,即我刚刚添加了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
在您的示例中,您可能需要在 basic-auth 相关注释中添加 nginx 前缀:
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"
首先我使用了我的入口资源中列出的地址(在我的ingress 定义中添加kubernetes.io/ingress.class: nginx 注释后,它就不再出现在那里:
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
ingress-with-auth foo.bar.com 80 117m
当我尝试使用此 IP 访问 pypi-server 时,它直接将我带到该页面,无需任何身份验证。但看起来如果您没有定义正确的入口类,则使用默认值,因此在实践中您的 ingress 定义与 auth-basic 细节没有被考虑在内,也不会传递给 nginx 入口控制器我们在前面的步骤之一中安装。
那么应该使用什么 IP 地址来访问您的应用程序?运行以下命令,这将显示您的 nginx 入口控制器的CLUSTER-IP(可以在您的集群中从任何Pod 或Node 访问)和EXTERNAL-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
您基本上可以在集群中托管许多不同的网站,并且所有这些网站都可以通过此 IP 访问。所有这些都可以在默认的http 80 端口(或https 443 在您的情况下)上可用。它们之间的唯一区别是您在http request 的http 标头中传递的hostname。
由于我没有指向此外部 IP 地址的域,并且无法通过转到 http://foo.bar.com 来简单地访问我的网站,因此我需要以某种方式传递 hostname 我从 35.111.112.113 地址请求的地址。可以通过以下几种方式完成:
我在我的 Google Chrome 浏览器中安装了 ModHeader 扩展程序,它允许我修改我的 http 请求标头并将 hostname I'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 开始(首先通过运行kubectl get pods -n ingress-nginx 检查您的Pod 名称):
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,这是您的pypiserverService 公开的端口。请注意,我的ingress object/resource 定义中有servicePort: 80。您在 cloudflare 中的 example.com 域应该使用它的 A record 指向您的 nginx ingress controller LoadBalancer Service IP (kubectl get svc -n ingress-nginx),而不指定任何端口。