# 使用 Ingress 进行域名访问
在上篇文章中我们已经使用 k8s 部署了第一个应用,此时我们可以使用 Ingress
使它可以在互联网上可以被访问到 (当然你要有自己的域名并且指向正确)
以下是官网搬用的关于 Ingress
的一幅图,用以描述 Ingress 的作用。如果你对它一无所知,你可以把它理解为传统的 nginx,用以配置自己网站的域名使之能够通过外网访问。
# Ingress 是什么
通过前面的学习,我们已经知道 K8S 中有 Service 的概念,同时默认情况下还有 CoreDNS 完成集群内部的域名解析等工作,以此完成基础的服务注册发现能力。
在第 7 节中,我们介绍了 Service 的 4 种基础类型,在前面的介绍中,我们一般都在使用 ClusterIP 或 NodePort 等方式将服务暴露在集群内或者集群外。
本节,我们将介绍另一种处理服务访问的方式 Ingress。
Ingress 是什么
通过 kubectl explain ingress 命令,我们来看下对 Ingress 的描述。
Ingress is a collection of rules that allow inbound connections to reach the endpoints defined by a backend. An Ingress can be configured to give services externally-reachable urls, load balance traffic, terminate SSL, offer name based virtual hosting etc.
Ingress 是一组允许外部请求进入集群的路由规则的集合。它可以给 Service 提供集群外部访问的 URL,负载均衡,SSL 终止等。
直白点说,Ingress 就类似起到了智能路由的角色,外部流量到达 Ingress ,再由它按已经制定好的规则分发到不同的后端服务中去。
看起来它很像我们使用的负载均衡器之类的。那你可能会问,Ingress 与 LoadBalancer 类型的 Service 的区别是什么呢?
Ingress 不是一种 Service 类型
Ingress 是 K8S 中的一种资源类型,我们可以直接通过 kubectl get ingress 的方式获取我们已有的 Ingress 资源。
Ingress 可以有多种控制器(实现)
通过之前的介绍,我们知道 K8S 中有很多的 Controller (控制器),而这些 Controller 已经打包进了 kube-controller-manager 中,通过 --controllers 参数控制启用哪些。
但是 Ingress 的 Controller 并没有包含在其中,而且有多种选择。
由社区维护(或是说官方支持的)有两个:适用于 Google Cloud 的 GLBC,当你使用 GKE 的时候,便会看到它;和 NGINX Ingress Controller 它是使用 ConfigMap 存储 NGINX 配置实现的。
第三方的实现还有:基于 Envoy 的 Contour; F5 的 F5 BIG-IP Controller; 基于 HAProxy 的 haproxy-ingress; 基于 Istio 的 Control Ingress Traffic; 现代化的反向代理服务器 Traefik; 以及 Kong 支持的 Kong Ingress Controller for Kubernetes 和 NGINX 官方支持的 NGINX Ingress Controller。
这里可以看到 K8S 社区和 NGINX 都有 NGINX Ingress Controller,很多人在一开始接触 Ingress 的时候便陷入了选择的苦恼中,除去前面的那些选择外,单 NGINX 的控制器就有两个,到底应该怎么选。
这里提供两点建议:
可能多数人使用的都是 NGINX 而非 NGINX Plus,如果你需要会话保持(Session persistence)的话,那你应该选择 K8S 社区维护的版本
即使我们平时使用 NGINX 的时候,也常常会有动态配置的需求,如果你仍然有这样的需求,那你还是继续使用 K8S 社区维护的版本(其中内置了 Lua 支持)。
internet
|
[ Ingress ]
--|-----|--
[ Services ]
其中,Ingress
包含两个组件
Ingress
: 配置转发规则,类似于 nginx 的配置文件Ingress Controller
: 转发,类似于 nginx,它会读取Ingress
的规则并转化为nginx
的配置文件
而 Ingress Controller
除了 nginx
外还有 haproxy
,ingress
等等,我们选用 nginx
作为 Ingress Controller
# 使用 helm 部署 nginx Ingress Controller
我们使用 helm 选择官方的 stable/nginx-ingress chart 进行部署。
nginx-ingress
会配置一个 type 为 LoadBalancer
的 service, 因此需要配置 EXTERNAL-IP
为k8s集群节点的 IP。 在这里 external-ip 会设置为 [172.17.68.39, 172.17.68.40]
我们可以通过 kubectl get nodes
来获取 IP 地址
# 获取node的 INTERNAL-IP,作为 LoadBalancer 的 EXTERNAL-IP
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
shanyue Ready master 13d v1.16.0 172.17.68.39 <none> CentOS Linux 7 (Core) 3.10.0-957.21.3.el7.x86_64 docker://18.6.2
shuifeng Ready <none> 13d v1.16.0 172.17.68.40 <none> CentOS Linux 7 (Core) 3.10.0-957.21.3.el7.x86_64 docker://18.6.2
在这里 external-ip 会设置为 [172.17.68.39, 172.17.68.40]
controller.service.externalIPs[0]=172.17.68.39
controller.service.externalIPs[1]=172.17.68.40
# 使用 helm v3 部署,如果使用 helm v2 部署的话,把 release-name 使用 --name 指定
$ helm install nginx-ingress stable/nginx-ingress --set "controller.service.externalIPs[0]=172.17.68.39,controller.service.externalIPs[1]=172.17.68.40"
NAME: nginx-ingress
LAST DEPLOYED: 2019-10-18 21:21:44.115902395 +0800 CST m=+1.904554085
NAMESPACE: default
STATUS: deployed
NOTES:
The nginx-ingress controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace default get services -o wide -w nginx-ingress-controller'
An example Ingress that makes use of the controller:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: example
namespace: foo
spec:
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: exampleService
servicePort: 80
path: /
# This section is only required if TLS is to be enabled for the Ingress
tls:
- hosts:
- www.example.com
secretName: example-tls
If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:
apiVersion: v1
kind: Secret
metadata:
name: example-tls
namespace: foo
data:
tls.crt: <base64 encoded cert>
tls.key: <base64 encoded key>
type: kubernetes.io/tls
校验 nginx-ingress 的部署情况
$ helm ls
NAME NAMESPACE REVISION UPDATED STATUS CHART
nginx-ingress default 1 2019-10-18 11:21:44.115902395 +0800 CST deployed nginx-ingress-1.24.0
# 查看 nginx-ingress 所有的 service
$ kubectl get svc -l app=nginx-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress-controller LoadBalancer 10.101.64.64 172.17.68.39,172.17.68.40 80:30285/TCP,443:31094/TCP 7m19s
nginx-ingress-default-backend ClusterIP 10.110.76.15 <none> 80/TCP 7m19s
# 配置 Ingress 映射域名
与已知知识关联有助于我们更好地学习新知识,以下是关于 nginx 与 ingress 部署一个博客应用的简单配置文件
- 外网通过域名 nginx.xiange.tech 来访问应用
- 代理服务 nginx 来做负载均衡
- nginx 暴露出 80 端口
server {
listen 80
server_name nginx.xiange.tech
location / {
proxy_pass: http://nginx:80
}
}
使用 Ingress
配置路由规则如下
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-service-ingress
spec:
rules:
- host: nginx.xiange.tech
http:
paths:
- backend:
serviceName: nginx-service
servicePort: 80
path: /
我们使用 Ingress
把它配置到了 nginx.xiange.tech
该域名下,在公网环境下的浏览器中打开域名 nginx.xiange.tech
,可以看到熟悉的 nginx 配置页面
# 小结
部署一个应用从 Deployment
,Service
再到 Ingress
的完整配置文件如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-service-ingress
spec:
rules:
- host: nginx.xiange.tech
http:
paths:
- backend:
serviceName: nginx-service
servicePort: 80
path: /
kubectl delete -f nginx-deployment.yaml kubectl delete -f nginx-service.yaml kubectl delete -f nginx-ingress.yaml
kubectl apply -f nginx-deployment.yaml kubectl apply -f nginx-service.yaml kubectl apply -f nginx-ingress.yaml