1
2
3
4
5
作者:李晓辉

微信联系:lxh_chat

联系邮箱: 939958092@qq.com

今天我们要聊的是 Kubernetes 中一个非常实用但又有点小复杂的组件——Ingress。它的作用很简单,Ingress 允许你将外部流量引导到 Kubernetes 集群内的特定服务

就好像,你开了一家餐馆,Ingress 就是门口的那个接待员,负责告诉客人该去哪个座位,也就是决定流量怎么进来,指向你集群里的正确服务。为什么要有它呢?因为它能帮你集中管理流量,避免暴露很多端口,配置起来也相对简单。

今天我们就来聊聊 Kubernetes Ingress 究竟是什么、怎么用,它为什么能让你的生活更轻松。

什么是 Kubernetes Ingress?

简单来说,Ingress 就是 Kubernetes 用来管理外部流量的一个资源。它允许你通过 HTTP 或 HTTPS 协议把外部请求(比如网站访问)引导到集群里的特定服务上。

你可以把它理解为集群的“路由器”,它能够基于你配置的规则,把流量转发到不同的服务。比如你希望所有访问 example.com 的请求都转发到服务 A,而 test.com 的请求转到服务 B,Ingress 就可以搞定这些事。

但需要注意的是,Ingress 本身不做实际的流量转发,它只是定义了如何路由流量。而实际流量的转发是由你安装的 Ingress Controller 来负责的。

为什么要使用 Ingress?

你可能会想:“我不是可以直接用 Kubernetes 的 Service 来暴露服务吗?”当然可以!但是 Service 是通过 NodePortLoadBalancer 把服务暴露出来的,虽然这些方法可以解决问题,但暴露出来的端口和 IP 可能会很乱,管理起来麻烦,而且如果要做 HTTPS 配置,NodePort 或 LoadBalancer 又有点力不从心。

k8s-nodeport

Ingress 能帮你解决这些问题。它有以下几个优势:

  • 集中的流量控制:通过 Ingress,你可以在一个地方集中配置流量路由规则,不需要每个服务都暴露一个 IP 或端口。

  • HTTPS 支持:想用 SSL 加密你的应用?Ingress 支持非常方便的 TLS 配置,你只需要准备好证书,Ingress 就可以自动帮你处理 HTTPS 流量。

  • 域名路由:你可以使用域名来路由不同的请求,举个例子,app1.example.com 路由到服务 A,app2.example.com 路由到服务 B。

k8s-ingress

总之,Ingress 帮你管理外部流量,减少暴露端口的麻烦,方便集中管理和维护,为了让 Ingress 规则生效,我们还需要部署一个 Ingress Controller,这个控制器会按照规则转发流量。

控制器部署

Ingress Controller是最关键的部分。Ingress 只定义规则,实际的流量转发和路由任务是由 Ingress Controller 来做的。常见的 Ingress Controller 有 Nginx、Traefik 等。你可以选择一个你喜欢的,安装到 Kubernetes 集群中,Ingress Controller 就会自动读取 Ingress 资源,并按照定义的规则来处理流量。

我们选择使用nginx类型的ingress控制器,来吧,我们开始部署控制器

1
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.2/deploy/static/provider/baremetal/deploy.yaml

需要注意的是,在中国可能无法拉取yaml中需要的镜像,我给你列出一下镜像看看

你可以点此链接在我这里买一个容器镜像加速器,50块钱就能用3个月,不限速不限量

1
2
3
4
root@k8s-master:~# grep image: deploy.yaml
image: registry.k8s.io/ingress-nginx/controller:v1.12.2@sha256:03497ee984628e95eca9b2279e3f3a3c1685dd48635479e627d219f00c8eefa9
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.5.3@sha256:2cf4ebfa82a37c357455458f6dfc334aea1392d508270b2517795a9933a02524
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.5.3@sha256:2cf4ebfa82a37c357455458f6dfc334aea1392d508270b2517795a9933a02524
1
kubectl get pod -n ingress-nginx
1
2
3
4
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-c2wwb 0/1 Completed 0 2m28s
ingress-nginx-admission-patch-vg99g 0/1 Completed 0 2m28s
ingress-nginx-controller-64c84dfdb8-jnp6w 1/1 Running 0 2m28s

准备普通业务pod

首先,我们得创建一个 Pod,并让它用 Nginx 镜像,创建pod的目的是用来模拟我们公司的普通业务,我们要运行 3 个副本,这样可以确保高可用性和负载均衡。

这就像在你的集群里放了 3 个 Nginx 服务器,每个服务器都可以处理请求。下面是一个简单的 YAML 配置来定义这个 Deployment:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cat > pod.yml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-ingress
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: registry.myk8s.cn/library/nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
EOF

来创建出我们的业务

1
2
root@k8s-master:~# kubectl create -f pod.yml
deployment.apps/nginx-deployment-ingress created

看看业务是否工作正常

1
2
3
4
5
6
root@k8s-master:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-ingress-6c6c8b4489-cj25c 1/1 Running 0 89s 172.16.194.75 k8s-worker1 <none> <none>
nginx-deployment-ingress-6c6c8b4489-dhl7p 1/1 Running 0 89s 172.16.194.74 k8s-worker1 <none> <none>
nginx-deployment-ingress-6c6c8b4489-kq4wf 1/1 Running 0 89s 172.16.194.76 k8s-worker1 <none> <none>

访问一下看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@k8s-master:~# curl http://172.16.194.74
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

完美,我们的业务已经可以正常访问了

准备Service

Kubernetes 中的 Pod 是临时性的,也就是说,它们可能会因为扩容、更新或者重启而消失。为了避免这些问题,Kubernetes 通过 Service 来抽象化 Pod,确保即使 Pod 发生变化,外部系统也可以稳定地访问到它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
cat > service.yml <<EOF
apiVersion: v1
kind: Service
metadata:
name: ingressservice
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
EOF

我创建了一个名为ingressservice的service,工作在80端口,并通过app: nginx来找到我们的普通业务的pod的80端口

1
2
3
4
5
6
root@k8s-master:~# kubectl create -f service.yml
service/ingressservice created
root@k8s-master:~# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingressservice ClusterIP 10.105.179.52 <none> 80/TCP 2s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 36d

看看service是否能访问到后端的pod,先看看是否有endpoint

1
2
3
root@k8s-master:~# kubectl get endpoints
NAME ENDPOINTS AGE
ingressservice 172.16.194.74:80,172.16.194.75:80,172.16.194.76:80 75s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@k8s-master:~# curl http://10.105.179.52
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

创建ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat > ingress.yml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: lixiaohui
spec:
ingressClassName: nginx
rules:
- host: www.lixiaohui.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: ingressservice
port:
number: 80
EOF
1
2
3
4
5
root@k8s-master:~# kubectl create -f ingress.yml
ingress.networking.k8s.io/lixiaohui created
root@k8s-master:~# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
lixiaohui nginx www.lixiaohui.com 192.168.8.4 80 101s

访问ingress

我们前面已经看到ingress的地址是192.168.8.4,这是我的节点IP,我们看看ingress控制器工作在哪个节点的端口上

1
2
3
4
root@k8s-master:~# kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.110.168.32 <none> 80:30614/TCP,443:30187/TCP 15m
ingress-nginx-controller-admission ClusterIP 10.99.2.77 <none> 443/TCP 15m

看到控制器工作在80:30614/TCP,443:30187/TCP,我们是80,所以要访问30614端口

把上述ADDRESS部分的IP和域名绑定解析

1
echo 192.168.8.4 www.lixiaohui.com >> /etc/hosts

访问一下看看,别忘了加端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@k8s-master:~# curl http://www.lixiaohui.com:30614
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

主机网络模式

什么?访问域名还加30614的端口???太烦人了,其实你在部署控制器的时候将其部署成hostNetwork: true,这样的话,ingress就会工作在物理IP的标准80和443端口了

ingress-hostnetwork

1
kubectl edit deployments.apps -n ingress-nginx ingress-nginx-controller

不要加错层级

1
2
3
4
5
6
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
hostNetwork: true

直接访问就行,不用加端口了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@k8s-master:~# curl http://www.lixiaohui.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>