1.如何理解和启动 Ingress 控制器
问题:
Ingress
与Service
有啥不同?
答:KubernetesService
是Pod
endpoint
(pod-ip:port)的抽象,而Ingress
是Service
的抽象。这并不意味着所有的Ingress
都必须通过Service
进行路由。为了实现路由、安全性和身份鉴权的功能,需要Ingress
封装Service
的功能,因此只要配置Ingress
就可以路由到Service
的 DNS 名称、ClusterIP
和Nodeport
,或者直接路由到Pod
的Endpoint
。
① 启动 nginx Ingress 控制器
基于 Minikube,使用命令 minikube start
创建集群。
# 1.查询 kubernetes 版本
$kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.0", GitCommit:"af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38", GitTreeState:"clean", BuildDate:"2020-12-08T17:59:43Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.0", GitCommit:"af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38", GitTreeState:"clean", BuildDate:"2020-12-08T17:51:19Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
# Client 即 kubectl 的版本是 v1.20.0
# Server 即 kubernetes 的版本是 v1.20.0
# 2.启动 nginx Ingress 控制器
$minikube addons enable ingress
基于开源 nginx-Ingress,nginx-Ingress 控制器的安装指南。
# 下载 nginx-Ingress 部署的 yaml
$wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/cloud/deploy.yaml
$ls
deploy.yaml
$kubectl apply -f deploy.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
② 检查 nginx Ingress 控制器
# 如果 kubernetes 的版本大于等于 v1.19
$kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-g9g49 0/1 Completed 0 11m
ingress-nginx-admission-patch-rqp78 0/1 Completed 1 11m
ingress-nginx-controller-59b45fb494-26npt 1/1 Running 0 11m
2.如何使用 Ingress
问题:
Ingress
是什么?
答:Ingress
公开了从集群外部到集群内Service
的 HTTP 和 HTTPS 路由,其中流量路由的规则由Ingress
资源来定义,例如,Ingress
配置为Service
提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及提供基于名称的虚拟主机等能力。
Ingress
支持 host
、path
和 pathType
的相关配置,其中 host
可以精确匹配和通配符匹配,而 path
和 pathType
可以精确匹配和前缀匹配
2.1 Ingress 的后端为 Service
2.1.1 同一主机地址的流量路由到多个 Service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-one-to-two-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
kubectl apply -f ingress-one-to-two-example.yaml
创建 Ingress
:
$kubectl describe ingress ingress-one-to-two-example
Name: ingress-one-to-two-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
# 如果 service1,service2 存在,则 Address 字段看到负载均衡器的地址 178.91.123.132
# 如果 Default backend 存在且 1 个 service 都不存在的时候,请求会直接路由到 default-http-backend:80
注意事项:如果 1 个 spec.service.rules[].http.paths[].backend.sevice
且 Default backend
存在,则请求会直接路由到 default-http-backend:80。然而,当 Default backend 不存在 Ingress 会不断重试陷入无限循环,即客户端跟 nginx 建立了长连接,不断发起请求。
2.1.2 多个主机名的流量路由到不同 Service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-two-to-two-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
如果创建的 Ingress
资源没有在 spec.rules[].host
中定义的任何 hosts,则可以匹配指向 Ingress
控制器 IP 地址的任何网络流量。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-multi-to-one-example
spec:
rules:
- http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service3
port:
number: 80
2.1.3 TLS 认证
说明:
Ingress
只支持单个 TLS 端口 443,并假定 TLS 连接终止于Ingress
节点,而Service
及其Pod
之间的流量都以明文传输。
kubectl apply -f secret-testsecret-tls.yaml
创建 Secret
。如下所示,TLS Secret
必须包含名为 tls.crt
和 tls.key
的键名,用于 TLS 的证书和私钥,其中 https-example.foo.com
客户端必须有 TLS 的公钥。
apiVersion: v1
kind: Secret
metadata:
name: secret-testsecret-tls
namespace: default
data:
tls.crt: base64 编码的 cert
tls.key: base64 编码的 key
type: kubernetes.io/tls
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-tls-example
spec:
tls:
- hosts:
- https-example.foo.com
secretName: secret-testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80