0%

Kubernetes Service之Ingress Service

这里介绍K8s Service中的Ingress Service

abstract.png

楔子

LoadBalance Service虽然可以对外暴露服务,但每个LoadBalance Service都需要占用一个公网IP资源。故我们可以利用Ingress Service来暴露自己的服务。事实上,Ingress Service并不是一种服务类型。其通过主机地址、路径等路由规则实现将多个内部服务整合到一个统一的集群入口当中。换言之,其可以实现在同一IP地址下公开多个服务

配置K8s集群

这里先通过Kind部署一个单节点的K8s集群,配置文件如下所示。需要注意,一方面我们给该节点设置ingress-ready=true的标签信息;另一方面,对80、443端口设置映射, 便于后续通过宿主机访问K8s节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Kind配置文件: 创建单节点的K8s集群 

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
# 该集群包含1个控制平面节点
nodes:
- role: control-plane
# 设置节点标签信息, 标签名为ingress-ready、值为true
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
# 设置端口映射, 便于通过宿主机访问节点
extraPortMappings:
- containerPort: 80
hostPort: 80
listenAddress: "127.0.0.1"
- containerPort: 443
hostPort: 443
listenAddress: "127.0.0.1"

效果如下所示,集群创建成功

figure 1.jpeg

部署Ingress控制器

对于Ingress类型的资源而言,其必须依靠Ingress控制器才可以正常运行。故这里我们先部署一个Ingress控制器,事实上由于Ingress控制器有多种不同的实现。这里我们选择常用的Ingress控制器实现——Ingress NGINX。首先通过下述链接下载获取部署Ingress Nginx的配置文件

1
2
# 部署Ingress Nginx的配置文件
https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

上述配置文件中包含3个镜像,其中有2个镜像是一样的。但由于众所周知的原因,大多数情况下我们无法正常从境外仓库拉取相应的镜像文件。故我们需要修改上述配置文件,将镜像替换为阿里云仓库的镜像。具体如下所示

1
2
3
4
5
6
7
8
9
# 原镜像
image: registry.k8s.io/ingress-nginx/controller:v1.2.1@sha256:5516d103a9c2ecc4f026efbd4b40662ce22dc1f824fb129ed121460aaa5c47f8
# 阿里云镜像
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.2.1

# 原镜像
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660
# 阿里云镜像
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1

将镜像修改为国内镜像后,就可以利用kubectl apply命令部署Ingress Nginx了。效果如下所示,可以看到当Ingress控制器的Pod为Running时。即说明部署成功了

figure 2.jpeg

现在我们来看下Ingress控制器Pod的详细信息,从节点选择器的标签信息其实不难看出。该Pod对于部署的节点是有要求的。这也是为什么我们在此前创建集群的时候,需要给集群节点打上相关标签的原因

figure 3.jpeg

最后,为了后续能够让我们成功创建相应的Ingress资源,我们还需要删除ingress-nginx-admission。具体命令如下所示

1
2
3
4
5
# 查看 webhook
kubectl get validatingwebhookconfigurations

# 删除 ingress-nginx-admission
kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission

执行效果如下所示

figure 4.jpeg

部署应用

至此,我们就可以部署应用,包含RS、NodePort、Ingress等资源。具体如下所示,简单来说,我们通过RS部署了两个应用——foo app、bar app。并分别为这两个应用提供了相应的NodePort资源。然后创建了一个Ingress资源,用于实现访问同一域名下的不同路径时,将请求转发至两个不同的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# 创建 foo 应用的RS资源

apiVersion: apps/v1
# 资源类型
kind: ReplicaSet
metadata:
# RS名称
name: my-rs-foo-app
spec:
# 副本数量
replicas: 1
# 标签选择器
selector:
matchLabels:
app: foo-app
# Pod 模板
template:
metadata:
# 标签信息
labels:
app: foo-app
spec:
# 容器信息
containers:
- name: my-foo-app
image: hashicorp/http-echo:0.2.3
args:
- "-text=this is foo app"
# 仅用于展示容器所使用的端口
ports:
- containerPort: 5678

---

# 创建 foo 应用的Service资源

kind: Service
apiVersion: v1
metadata:
name: my-service-foo-app
spec:
# Service类型
type: NodePort
selector:
app: foo-app
ports:
- port: 11111 # 服务监听端口
targetPort: 5678 # 服务将请求转发到Pod的目标端口
# 集群节点端口, 可通过集群中任一节点的该端口号访问该服务
nodePort: 31119

---

# 创建 bar 应用的RS资源

apiVersion: apps/v1
kind: ReplicaSet
metadata:
# RS名称
name: my-rs-bar-app
spec:
# 副本数量
replicas: 1
# 标签选择器
selector:
matchLabels:
app: bar-app
# Pod 模板
template:
metadata:
# 标签信息
labels:
app: bar-app
spec:
# 容器信息
containers:
- name: my-bar-app
image: hashicorp/http-echo:0.2.3
args:
- "-text=this is bar app"
# 仅用于展示容器所使用的端口
ports:
- containerPort: 5678

---

# 创建 bar 应用的Service资源

kind: Service
apiVersion: v1
metadata:
name: my-service-bar-app
spec:
# Service类型
type: NodePort
selector:
app: bar-app
ports:
- port: 22222 # 服务监听端口
targetPort: 5678 # 服务将请求转发到Pod的目标端口
# 集群节点端口, 可通过集群中任一节点的该端口号访问该服务
nodePort: 32229

---

# 创建 Ingress 资源

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: aaron.ingress.com
http:
paths:
# 对aaron.ingress.com/foo的请求 将会转发到 名为my-service-foo-app的服务
- pathType: Prefix
path: "/foo"
backend:
# 服务名称、端口
service:
name: my-service-foo-app
port:
number: 11111
# 对aaron.ingress.com/bar的请求 将会转发到 名为my-service-bar-app的服务
- pathType: Prefix
path: "/bar"
backend:
# 服务名称、端口
service:
name: my-service-bar-app
port:
number: 22222

---

# 创建一个内置了bash、curl工具的Pod, 用于测试

apiVersion: v1
kind: Pod
metadata:
# Pod 名称
name: my-pod-bootcamp
spec:
# 容器信息
containers:
- name: my-bootcamp
# 镜像信息
image: jocatalin/kubernetes-bootcamp:v1
# 仅用于展示容器所使用的端口
ports:
- containerPort: 8080
protocol: TCP

---

现在利用 kubectl create 命令进行部署。如下所示,资源全部部署成功

figure 5.jpeg

由于我们在配置Ingress资源时,使用了一个域名:aaron.ingress.com。为了顺利在宿主机下进行测试,我们需要修改本地的DNS映射,即etc目录下的hosts文件。实现将该域名映射到本机上。如下所示

figure 6.jpeg

验证

上面我们还额外地部署了一个名为my-pod-bootcamp的Pod。目的就在于其内置了bash、curl等常见工具,非常方便我们开展测试验证工作

我们先分别通过NodePort的集群IP、服务端口实现对两个应用的访问,测试结果如下,符合预期

figure 7.jpeg

然后通过K8s节点的端口实现对两个应用的访问,测试结果如下,符合预期

figure 8.jpeg

至此说明我们的应用、NodePort部署是成功的。现在我们来验证下Ingress是否成功生效。在宿主机下通过curl分别访问aaron.ingress.com/bar、aaron.ingress.com/foo即可。测试结果如下,符合预期

figure 9.jpeg

参考文献

  1. Kubernetes in Action中文版 Marko Luksa著
  2. 深入剖析Kubernetes 张磊著
请我喝杯咖啡捏~

欢迎关注我的微信公众号:青灯抽丝