摘要
安装 traefik 作为 ingress controller 和安装 metallb 作为 loadbalancer。
前言
昨天我们成功安装好了集群,并配置了网络插件,成功使用 nodeport 访问了我们在集群上面部署的应用。
但是,nodeport 类型的 service 仍然会有许多限制,我们需要合适的方式来暴露我们的服务。
目标
安装 traefik,使用 ingress 来暴露 nginx 服务。
PS:我之前在 k3s 上实现过,k3s 是预装了很多组件的发行版,我现在想在原版上面自己安装组件然后重现一遍。
前置知识
ingress 的定位
按照 k8s 的网络模型,service 通过对 pod 进行负载均衡,对外提供服务。而 ingress 又可以在 service 上面提供更高一层的访问控制。
整体可能是这样子的三层。
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](https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/)
或者 [Gateway API](https://gateway-api.sigs.k8s.io/) 向公共互联网公开服务。
- [`NodePort`](https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#type-nodeport) 通过每个节点上的 IP 和静态端口(`NodePort`)公开 Service。
为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址,
相当于你请求了 `type: ClusterIP` 的服务。
- [`LoadBalancer`](https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#loadbalancer) 使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件;
你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。
- [`ExternalName`](https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#externalname) 将服务映射到 `externalName` 字段的内容(例如,映射到主机名 `api.foo.bar.example`)。
该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 `CNAME` 记录。
集群不会为之创建任何类型代理。
服务 API 中的 `type` 字段被设计为层层递进的形式 - 每层都建立在前一层的基础上。
但是,这种层层递进的形式有一个例外。
你可以在定义 `LoadBalancer` 服务时 [禁止负载均衡器分配 ](https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation)[`NodePort`](https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation)。
安装 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
|
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik
|
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 懂请求是怎么路由的,还要懂网络懂数据包是怎么传输的,还有各种奇奇怪怪的。
不管怎么说,现在是在不断学习,不断进步的。🐋