本指南将演示如何在使用 Kubernetes Nginx 入口控制器 时将 HTTP 和 HTTPS 入口配置到 osm-edge 托管服务网格的部分服务。
先决条件
- Kubernetes 集群版本 v1.19.0 或者更高。
- 使用
kubectl
与 API server 交互。 - 安装的 osm-edge 版本不低于 v1.1.0。
- 已安装
osm
命令行工具,用于管理服务网格。 - 以安装
helm
命令行工具,用于安装 Nginx 入口控制器。
演示
首先,部署 Nginx 入口控制器:
nginx_ingress_namespace=ingress-nginx # replace ingress-nginx with the namespace where Nginx will be installed
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace $nginx_ingress_namespace --create-namespace \
--set controller.service.httpPort.port="80"
注意 osm-edge 和 Nginx 入口控制器安装的相关细节:
osm_namespace=osm-system # Replace osm-system with the namespace where osm-edge is installed
osm_mesh_name=osm # replace osm with the mesh name (use `osm mesh list` command)
nginx_ingress_service=ingress-nginx-controller # replace ingress-nginx-controller with the name of the nginx ingress controller service
nginx_ingress_host="$(kubectl -n "$nginx_ingress_namespace" get service "$nginx_ingress_service" -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
nginx_ingress_port="$(kubectl -n "$nginx_ingress_namespace" get service "$nginx_ingress_service" -o jsonpath='{.spec.ports[?(@.name=="http")].port}')"
为了将后端的入口流量限制到授权客户端,我们将设置 IngressBackend 配置,以便只有来自 Nginx 入口控制器服务端点的入口流量才能将流量路由到服务后端。为了能够发现该服务的端点,我们需要 osm-edge 控制器来监控相应的命名空间。 但是,Nginx 正常运行不能注入 Pipy sidecar。
osm namespace add "$nginx_ingress_namespace" --mesh-name "$osm_mesh_name" --disable-sidecar-injection
接下来是部署 httpbin
示例服务。
# Create a namespace
kubectl create ns httpbin
# Add the namespace to the mesh
osm namespace add httpbin
# Deploy the application
kubectl apply -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.1/manifests/samples/httpbin/httpbin.yaml -n httpbin
确认 httpbin
客户端 pod 启动并运行。
$ kubectl get pods -n httpbin
NAME READY STATUS RESTARTS AGE
httpbin-74677b7df7-zzlm2 2/2 Running 0 11h
$ kubectl get svc -n httpbin
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpbin ClusterIP 10.0.22.196 <none> 14001/TCP 11h
HTTP 入口
下一步,我们将创建必要的 Ingress 和 IngressBackend 配置来允许外部的客户端访问 httpbin
命名空间下 httpbin
服务的 14001
端口。因为没有使用 TLS,Nginx 入口服务到 httpbin
后端 pod 的连接无需加密。
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpbin
namespace: httpbin
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin
port:
number: 14001
---
kind: IngressBackend
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
name: httpbin
namespace: httpbin
spec:
backends:
- name: httpbin
port:
number: 14001 # targetPort of httpbin service
protocol: http
sources:
- kind: Service
namespace: "$nginx_ingress_namespace"
name: "$nginx_ingress_service"
EOF
现在,我们期望外部的客户端可以通过 HTTP 的方式访问 httpbin
服务:
$ curl -sI http://"$nginx_ingress_host":"$nginx_ingress_port"/get
HTTP/1.1 200 OK
Date: Mon, 04 Jul 2022 06:55:26 GMT
Content-Type: application/json
Content-Length: 346
Connection: keep-alive
access-control-allow-origin: *
access-control-allow-credentials: true
HTTPS 出口 (mTLS 和 TLS)
为了将连接代理到 HTTPS 后端,我们将在 Ingress 和 IngressBackend 配置中指定使用 https
作为后端协议,同时由 osm-edge 颁发证书,Nginx 将使用该证书作为客户端证书将 HTTPS 连接代理到 TLS 后端。客户端证书和 CA 证书将保存在 Kubernetes secret 中,Nginx 将使用该证书来认证服务网格后端。
需要更新 osm-mesh-config
MeshConfig
资源来为 Nginx 入口 service 颁发证书。
kubectl edit meshconfig osm-mesh-config -n "$osm_namespace"
在 spec.certificate
下添加字段 ingressGateway
:
certificate:
ingressGateway:
secret:
name: osm-nginx-client-cert
namespace: <osm-namespace> # replace <osm-namespace> with the namespace where osm-edge is installed
subjectAltNames:
- ingress-nginx.ingress-nginx.cluster.local
validityDuration: 24h
注意:主体备用名称(Subject Alternative Name,SAN)使用类似
<service-account>.<namespace>.cluster.local
格式,sevice account 和 namespace 使用 Nginx service 的。
接下来,我们需要创建一个 Ingress 和 IngressBackend 配置以使用 TLS 代理到后端服务,同时通过 mTLS 启用到后端的代理。为此,我们必须创建一个 IngressBackend 资源,指定指向 httpbin
服务的 HTTPS 入口流量只能接受来自受信任客户端的流量。osm-edge 使用 主体备用名称(Subject Alternative Name,SAN)ingress-nginx.ingress-nginx.cluster.local
为 Nginx 入口服务提供了一个客户端证书,因此 IngressBackend 配置需要引用相同的 SAN 用于 Nginx 入口服务和 httpbin
后端之间的 mTLS 身份验证。
应用配置:
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpbin
namespace: httpbin
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
# proxy_ssl_name for a service is of the form <service-account>.<namespace>.cluster.local
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_ssl_name "httpbin.httpbin.cluster.local";
nginx.ingress.kubernetes.io/proxy-ssl-secret: "osm-system/osm-nginx-client-cert"
nginx.ingress.kubernetes.io/proxy-ssl-verify: "on"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin
port:
number: 14001
---
apiVersion: policy.openservicemesh.io/v1alpha1
kind: IngressBackend
metadata:
name: httpbin
namespace: httpbin
spec:
backends:
- name: httpbin
port:
number: 14001 # targetPort of httpbin service
protocol: https
tls:
skipClientCertValidation: false
sources:
- kind: Service
name: "$nginx_ingress_service"
namespace: "$nginx_ingress_namespace"
- kind: AuthenticatedPrincipal
name: ingress-nginx.ingress-nginx.cluster.local
EOF
现在,我们期望外部客户端能够通过入口网管和服务后端之间的 mTLS 上的 HTTPS 代理访问 httpbin
服务。
$ curl -sI http://"$nginx_ingress_host":"$nginx_ingress_port"/get
HTTP/1.1 200 OK
Date: Wed, 18 Aug 2021 18:12:35 GMT
Content-Type: application/json
Content-Length: 366
Connection: keep-alive
access-control-allow-origin: *
access-control-allow-credentials: true
要验证未经授权的客户端无法访问后端,更新 IngressBackend 配置中指定的 sources
。让我们将主题更新为 Nginx 客户端证书中编码的 SAN 以外的其他内容。
kubectl apply -f - <<EOF
apiVersion: policy.openservicemesh.io/v1alpha1
kind: IngressBackend
metadata:
name: httpbin
namespace: httpbin
spec:
backends:
- name: httpbin
port:
number: 14001 # targetPort of httpbin service
protocol: https
tls:
skipClientCertValidation: false
sources:
- kind: Service
name: "$nginx_ingress_service"
namespace: "$nginx_ingress_namespace"
- kind: AuthenticatedPrincipal
name: untrusted-client.cluster.local # untrusted
EOF
确认请求被拒绝并收到 HTTP 403 Forbidden
响应:
$ curl -sI http://"$nginx_ingress_host":"$nginx_ingress_port"/get
HTTP/1.1 403 Forbidden
Date: Wed, 18 Aug 2021 18:36:09 GMT
Content-Type: text/plain
Content-Length: 19
Connection: keep-alive
接下来,我们通过更新 IngressBackend 配置以设置 skipClientCertValidation: true
来演示对在服务后端禁用客户端证书验证的支持,同时仍使用不受信任的客户端:
kubectl apply -f - <<EOF
apiVersion: policy.openservicemesh.io/v1alpha1
kind: IngressBackend
metadata:
name: httpbin
namespace: httpbin
spec:
backends:
- name: httpbin
port:
number: 14001 # targetPort of httpbin service
protocol: https
tls:
skipClientCertValidation: true
sources:
- kind: Service
name: "$nginx_ingress_service"
namespace: "$nginx_ingress_namespace"
- kind: AuthenticatedPrincipal
name: untrusted-client.cluster.local # untrusted
EOF
确认在允许未信任的经过身份验证的主题连接到后端后请求成功。
$ curl -sI http://"$nginx_ingress_host":"$nginx_ingress_port"/get
HTTP/1.1 200 OK
Date: Wed, 18 Aug 2021 18:36:49 GMT
Content-Type: application/json
Content-Length: 364
Connection: keep-alive
access-control-allow-origin: *
access-control-allow-credentials: true
反馈
该内容是否有帮助?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.