摘要
安装 traefik 作为 ingress controller 和安装 metallb 作为 loadbalancer。
前言
昨天我们成功安装好了集群,并配置了网络插件,成功使用 nodeport 访问了我们在集群上面部署的应用。
但是,nodeport 类型的 service 仍然会有许多限制,我们需要合适的方式来暴露我们的服务。
目标
安装 traefik,使用 ingress 来暴露 nginx 服务。
PS:我之前在 k3s 上实现过,k3s 是预装了很多组件的发行版,我现在想在原版上面自己安装组件然后重现一遍。
前置知识
ingress 的定位
按照 k8s 的网络模型,service 通过对 pod 进行负载均衡,对外提供服务。而 ingress 又可以在 service 上面提供更高一层的访问控制。
整体可能是这样子的三层。
1
2
3
4
5
6
7
|
flowchart TD
Ingress--> Service1
Ingress--> Service2
Service1 --> Pod1
Service1 --> Pod2
Service1 --> ....
Service2 --> .....
|
service 更多的是用于集群内部服务的互相访问,而 ingress 更多的是用于外部访问集群内部的服务。
service 的分类
按照 官方文档,service 又能够分为几类(这里就直接引用官方文档了)
对一些应用的某些部分(如前端),你可能希望将其公开于某外部 IP 地址,
也就是可以从集群外部访问的某个地址。
Kubernetes Service 类型允许指定你所需要的 Service 类型。
可用的 type
值及其行为有:
ClusterIP
通过集群的内部 IP 公开 Service,选择该值时 Service 只能够在集群内部访问。
这也是你没有为服务显式指定 type
时使用的默认值。
你可以使用 Ingress
或者 Gateway API 向公共互联网公开服务。
NodePort
通过每个节点上的 IP 和静态端口(NodePort
)公开 Service。
为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址,
相当于你请求了 type: ClusterIP
的服务。
LoadBalancer
使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件;
你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。
ExternalName
将服务映射到 externalName
字段的内容(例如,映射到主机名 api.foo.bar.example
)。
该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME
记录。
集群不会为之创建任何类型代理。
服务 API 中的 type
字段被设计为层层递进的形式 - 每层都建立在前一层的基础上。
但是,这种层层递进的形式有一个例外。
你可以在定义 LoadBalancer
服务时 禁止负载均衡器分配 NodePort
。
安装 Helm
首先查看 traefik 的 安装说明,建议使用 helm,那我们就先安装 helm。
helm 是 k8s 的软件的「包管理器」,可以帮助我们更好的管理在 k8s 上面安装的资源。
helm 就是一个简单的二进制可执行文件,读取./kube 下的配置文件和集群进行通信。
查看 helm 的 安装说明,我选择使用包管理器进行安装
1
2
3
4
5
6
|
curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
helm completion bash | sudo tee /etc/bash_completion.d/helm > /dev/null && sudo chmod a+r /etc/bash_completion.d/helm
|
安装 traefik
有了 helm,现在可以安装 traefik 了。
1
2
3
4
|
helm repo add traefik https://traefik.github.io/charts
helm repo update
kubectl create ns kube-system
helm install traefik traefik/traefik -n kube-system
|
1
2
3
|
PS C:\Users\suyiiyii> k get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
traefik 1/1 1 1 111m
|
当 traefik ready 了,就可以访问了。
但是,当我尝试访问 master 的 80 端口时,却报错

很明显,我们还没有配置好。
甚至于,机器连 80 端口都没有监听,这样能访问才有鬼了。
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
|
root@ubuntu-71:~# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=571,fd=15))
LISTEN 0 3 0.0.0.0:2623 0.0.0.0:* users:(("mgmtd",pid=32196,fd=15))
LISTEN 0 128 127.0.0.1:6011 0.0.0.0:* users:(("sshd",pid=33297,fd=8))
LISTEN 0 3 127.0.0.1:2601 0.0.0.0:* users:(("zebra",pid=32178,fd=25))
LISTEN 0 3 127.0.0.1:2605 0.0.0.0:* users:(("bgpd",pid=32225,fd=18))
LISTEN 0 3 127.0.0.1:2616 0.0.0.0:* users:(("staticd",pid=32236,fd=12))
LISTEN 0 3 127.0.0.1:2617 0.0.0.0:* users:(("bfdd",pid=32239,fd=19))
LISTEN 0 4096 10.21.22.71:2379 0.0.0.0:* users:(("etcd",pid=1263,fd=8))
LISTEN 0 4096 10.21.22.71:2380 0.0.0.0:* users:(("etcd",pid=1263,fd=7))
LISTEN 0 4096 127.0.0.1:10248 0.0.0.0:* users:(("kubelet",pid=983,fd=15))
LISTEN 0 4096 127.0.0.1:10249 0.0.0.0:* users:(("kube-proxy",pid=1509,fd=9))
LISTEN 0 4096 127.0.0.1:10259 0.0.0.0:* users:(("kube-scheduler",pid=1270,fd=3))
LISTEN 0 4096 127.0.0.1:10257 0.0.0.0:* users:(("kube-controller",pid=1253,fd=3))
LISTEN 0 4096 127.0.0.1:2379 0.0.0.0:* users:(("etcd",pid=1263,fd=9))
LISTEN 0 4096 127.0.0.1:2381 0.0.0.0:* users:(("etcd",pid=1263,fd=15))
LISTEN 0 4096 10.21.22.71:7472 0.0.0.0:* users:(("speaker",pid=32071,fd=13))
LISTEN 0 4096 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=571,fd=17))
LISTEN 0 4096 127.0.0.1:40045 0.0.0.0:* users:(("containerd",pid=775,fd=10))
LISTEN 0 4096 10.21.22.71:7946 0.0.0.0:* users:(("speaker",pid=32071,fd=8))
LISTEN 0 3 [::]:2623 [::]:* users:(("mgmtd",pid=32196,fd=16))
LISTEN 0 4096 *:6443 *:* users:(("kube-apiserver",pid=1277,fd=3))
LISTEN 0 4096 *:10256 *:* users:(("kube-proxy",pid=1509,fd=8))
LISTEN 0 4096 *:10250 *:* users:(("kubelet",pid=983,fd=17))
LISTEN 0 4096 *:7473 *:* users:(("frr-metrics",pid=32206,fd=8))
LISTEN 0 4096 *:22 *:* users:(("sshd",pid=2263,fd=3),("systemd",pid=1,fd=91))
LISTEN 0 128 [::1]:6011 [::]:* users:(("sshd",pid=33297,fd=7))
|
我们看一下当前的 service
1
2
3
4
5
6
|
root@ubuntu-71:~# k get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 63m
default whoami ClusterIP 10.102.215.208 <none> 80/TCP 36m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 63m
traefik traefik LoadBalancer 10.98.132.99 <pending> 80:30686/TCP,443:32627/TCP 43m
|
可以看到,traefik 有一项一直是 pending 状态。并且,traefik 的 service 被配置成了 LoadBalancer 类型的。
我们通过查阅相关资料,得知,lb 通常是由云服务商提供,而我们在本地搭建的集群,默认是没有 lb 的,所以,我们还要去搞一个 lb 来。(traefik 文档为什么不告诉我要 lb🤬)
通过网络搜索,在本地集群使用 lb,推荐的比较多的是 metallb。
首先,先了解一下基本概念。
我也不是很懂,也不会讲,所以就直接在这里给出其他参考资料吧:
https://blog.csdn.net/heian_99/article/details/135260444
https://www.qikqiak.com/post/openelb/
https://www.lixueduan.com/posts/cloudnative/01-metallb/
https://atbug.com/load-balancer-service-with-metallb/
我打算使用 L2 的网络,配置只有几个 ip 的小 ip 池来使用。
碎碎念:
怎么和我之前用的 k3s 不一样,k3s 自带 lb,开启了之后是在本机上面开指定端口,和 nodeport 差不多。这个 metallb 是会直接给一个新的 ip 地址,访问要访问这个 ip 地址,就和原来的机器的 ip 没有什么关系了。好像说其他大多数的 lb 都应该是新建一个 ip 地址的?
安装
参考文档:
1
2
3
|
helm repo add metallb https://metallb.github.io/metallb
kubectl create ns metallb-system
helm install metallb metallb/metallb -n metallb-system
|
然后等相关的 pod 就绪了就可以使用了
1
2
3
4
5
6
|
NAME READY STATUS RESTARTS AGE
metallb-controller-66fddf5ff-9zzl9 1/1 Running 0 6m29s
metallb-speaker-jjzf8 4/4 Running 0 6m29s
metallb-speaker-ns9w2 4/4 Running 0 6m29s
metallb-speaker-pnswq 4/4 Running 0 6m29s
metallb-speaker-sjwld 4/4 Running 0 6m29s
|
配置
配置主要分两步:
网络上大部分的教程是基于 configmap 来配置的,但是 metallb 已经支持使用 CR 进行配置,所以我们全部使用 CR,这样可读性更佳,也便于修改。
下面给出的都是 k8s 的 manifest,使用 kubectl apply 即可
分配 ip
这里是配置 mentallb 可以使用哪一些 ip 地址,要用 CIRD 格式,用 - 表示范围也可以。
1
2
3
4
5
6
7
8
|
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: cheap
namespace: metallb-system
spec:
addresses:
- 10.21.22.80-10.21.22.84
|
ip 地址要根据实际情况填写。
这里我用的是内网 ip,为了节约使用就只开了/30 的地址范围。
声明 ip
我用的是 L2 模式的,声明很简单,就应用这一段就行了:
1
2
3
4
5
|
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
|
到此,关于 metallb 就配置完成了。我们就有一个本地的 lb 了。
再查看 service,我们可以看到 traefik 已经正常获取到 ip 了
1
2
3
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h49m
traefik LoadBalancer 10.108.193.80 10.21.22.80 80:32191/TCP,443:31252/TCP 159m
|
验收
同样的,我们先创建一个 deployment 和对应的 service
1
2
|
k create deployment nginx --image nginx
k create svc clusterip nginx --tcp=80
|
然后,再创建一个到 nginx service 的 ingress
1
|
k create ingress nginx --rule="/=nginx:80"
|
最后,我们访问 traefik 的地址,就可以打开网页了

到此,ingress 就可以使用啦。😁
traefik 控制面板
在文档的 这个部分,提供了访问 traefik dashboard 的方法。在本机运行这行命令开启端口转发。
1
|
kubectl port-forward $(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name) 9000:9000
|
然后,我们就可以在本机打开 http://127.0.0.1:9000/dashboard/
访问 dashboard 了。

页面做的还是很美观的,在上面可以直观的看到添加的路由。

由于 traefik 是一个独立的路由,里面的一些配置和 k8s 的 ingress 有一些不同,还需要学习一会。
总结
搞得比较顺利吧。(怎么每次都这样说~~,搞得不顺利就不会写出来了😓~~)
感觉要学习的东西好多,搞个 k8s,既要懂 linux 懂容器是怎么运行的,又要懂 http 懂请求是怎么路由的,还要懂网络懂数据包是怎么传输的,还有各种奇奇怪怪的。
不管怎么说,现在是在不断学习,不断进步的。🐋