当你觉活着没啥感受时,会陷入无尽虚无,越来越不像一人,存在的意义只能从某些快感中汲取,活着像海中的小舟一样,无所畏惧,亦畏惧所有。成长至此,大都是别人功劳,所以任有部分人性未曾泯灭,与其说努力,不如讲只求心安;希望每个小伙伴都不要像我一样,每天起床的第一句话,告诉自己,沉沦的小酒馆已经打烊了啦!要好好爱护自己的身体 —山河已无恙
写在前面
学习K8s
中Service
遇到,单独整理分享给小伙伴
博文内容涉及:
ingress-nginx-controller
的创建
基于ingress-nginx-controller
的Ingress
的创建
基于Ingress
的服务发布,SVC负载
时间关系,关于Ingress
http路由负载本文没有涉及
部分地方使用ansible
,不影响阅读
当你觉活着没啥感受时,会陷入无尽虚无,越来越不像一人,存在的意义只能从某些快感中汲取,活着像海中的小舟一样,无所畏惧,亦畏惧所有。成长至此,大都是别人功劳,所以任有部分人性未曾泯灭,与其说努力,不如讲只求心安;希望每个小伙伴都不要像我一样,每天起床的第一句话,告诉自己,沉沦的小酒馆已经打烊了啦!要好好爱护自己的身体 —山河已无恙
ingress Service的表现形式为IP:Port
,即工作在TCP/IP
层。 对于基于HTTP
的服务来说,不同的URL
地址经常对应到不同的后端服务或者虚拟服务器(Virtual Host)
这些应用层的转发机制仅通过Kubernetes
的Service
机制是无法实现的。
从Kubernetes 1.1
版本开始新增Ingress资源对象
,用于将不同URL
的访问请求转发到后端不同的Service
,以实现HTTP层的业务路由机制
。但是并不是说只能做7层路由,四层负载也可以
Kubernetes使用了一个Ingress策略定义和一个具体的Ingress Controller,两者结合并实现了一个完整的Ingress负载均衡器。
使用Ingress进行负载分发时是不是和kube-proxy没啥关系,直接分发到pod上了,使用Load Balancer和nodeport才会使用kube-proxy ?
使用Ingress
进行负载分发时, Ingress Controller
基于Ingress规则
将客户端请求直接转发到Service对应的后端Endpoint (Pod)
上,这样会跳过kube-proxy
的转发功能, kube-proxy
不再起作用。如果IngressController
提供的是对外服务,则实际上实现的是边缘路由器的功能。
控制器通过svc获取endpoints并获取对应的pod信息,然后通过nginx内部的lua代码进行处理
官网中的一些描述
Ingress
Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
个人理解,就是实现了一个Ngixn功能,可以更具路由规则分配流量等
命名空间里配置ingress规则,嵌入到控制器nginx-反向代理的方式(ingress-nginx-controller)
可以将 Ingress 配置为服务提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及提供基于名称的虚拟主机等能力。 Ingress 控制器
通常负责通过负载均衡器来实现 Ingress
,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort
或 Service.Type=LoadBalancer
类型的服务
为使用Ingress,需要创建Ingress Controller
(带一个默认backend
服务)和Ingress策略
设置来共同完成。
在定义Ingress策略
之前,需要先部署Ingress Controller
,以实现为所有后端Service
都提供一个统一的入口
。Ingress Controller
需要实现基于不同HTTP URL
向后转发的负载分发规则,并可以灵活设置7层负载分发策略
。
如果公有云服务商能够提供该类型的HTTP路由LoadBalancer
,则也可设置其为Ingress Controller
。在Kubernetes
中, Ingress Controller
将以Pod
的形式运行,监控APIServer的/ingress接口后端的backend services
,如果Service
发生变化,则Ingress Controller
应自动更新其转发规则。
下面的例子使用Nginx
来实现一个Ingress Controller
,正常情况下ingress-nginx-controller 会作为一个deamonSet,即位于没一个Node上。这里我们为了方便,只是在一个node上配置,同时写如NDS映射
ingress-nginx-controller 部署 需要的镜像,相关的资源文件,小伙伴可以在k8s官网获取
1 2 3 4 5 6 7 8 9 10 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$grep image nginx-controller.yaml image: docker.io/liangjw/ingress-nginx-controller:v1.0.1 imagePullPolicy: IfNotPresent image: docker.io/liangjw/kube-webhook-certgen:v1.1.1 imagePullPolicy: IfNotPresent image: docker.io/liangjw/kube-webhook-certgen:v1.1.1 imagePullPolicy: IfNotPresent ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$
准备工作,镜像上传,导入
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 ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible node -m copy -a "dest=/root/ src=./../ingress-nginx-controller-img.tar" 192.168.26.82 | CHANGED => { "ansible_facts" : { "discovered_interpreter_python" : "/usr/bin/python" }, "changed" : true , "checksum" : "a3c2f87fd640c0bfecebeab24369c7ca8d6f0fa0" , "dest" : "/root/ingress-nginx-controller-img.tar" , "gid" : 0, "group" : "root" , "md5sum" : "d5bf7924cb3c61104f7a07189a2e6ebd" , "mode" : "0644" , "owner" : "root" , "size" : 334879744, "src" : "/root/.ansible/tmp/ansible-tmp-1640207772.53-9140-99388332454846/source" , "state" : "file" , "uid" : 0 } 192.168.26.83 | CHANGED => { "ansible_facts" : { "discovered_interpreter_python" : "/usr/bin/python" }, "changed" : true , "checksum" : "a3c2f87fd640c0bfecebeab24369c7ca8d6f0fa0" , "dest" : "/root/ingress-nginx-controller-img.tar" , "gid" : 0, "group" : "root" , "md5sum" : "d5bf7924cb3c61104f7a07189a2e6ebd" , "mode" : "0644" , "owner" : "root" , "size" : 334879744, "src" : "/root/.ansible/tmp/ansible-tmp-1640207772.55-9142-78097462005167/source" , "state" : "file" , "uid" : 0 } ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible node -m shell -a "docker load -i /root/ingress-nginx-controller-img.tar"
创建ingress控制器ingress-nginx-controller
1 2 3 4 5 6 7 8 9 10 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl apply -f nginx-controller.yaml ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl get pods -n ingress-nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES ingress-nginx-admission-create--1-hvvxd 0/1 Completed 0 89s 10.244.171.171 vms82.liruilongs.github.io <none> <none> ingress-nginx-admission-patch--1-g4ffs 0/1 Completed 0 89s 10.244.70.7 vms83.liruilongs.github.io <none> <none> ingress-nginx-controller-744d4fc6b7-7fcfj 1/1 Running 0 90s 192.168.26.83 vms83.liruilongs.github.io <none> <none> ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$
我们这里只是在192.168.26.83上创建了一个ingress控制器pod,生产环境一般需要每个节点上存在一个,即通过deamonset的方式 DNS解析的地址为控制器的地址,这里控制器使用的是docker内部网络的方式,即直接把端口映射宿主机了
1 2 3 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$grep -i hostN nginx-controller.yaml hostNetwork: true
因为pod是在192.168.26.83节点,所以我们需要 配置DNS 创建域名到服务的映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible 192.168.26.83 -m shell -a "echo -e '192.168.26.83 liruilongs.nginx1\n192.168.26.83 liruilongs.nginx2\n192.168.26.83 liruilongs.nginx3' >> /etc/hosts" 192.168.26.83 | CHANGED | rc=0 >> ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible 192.168.26.83 -m shell -a "cat /etc/hosts" 192.168.26.83 | CHANGED | rc=0 >> 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.26.81 vms81.liruilongs.github.io vms81 192.168.26.82 vms82.liruilongs.github.io vms82 192.168.26.83 vms83.liruilongs.github.io vms83 192.168.26.83 liruilongs.nginx1 192.168.26.83 liruilongs.nginx2 192.168.26.83 liruilongs.nginx3 ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$
服务模拟,创建三个pod做为SVC提供能力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$cat pod.yaml apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: pod-svc name: pod-svc spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: pod-svc resources: {} dnsPolicy: ClusterFirst restartPolicy: Always status: {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl apply -f pod.yaml pod/pod-svc created ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$sed 's/pod-svc/pod-svc-1/' pod.yaml > pod-1.yaml ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$sed 's/pod-svc/pod-svc-2/' pod.yaml > pod-2.yaml ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl apply -f pod-1.yaml pod/pod-svc-1 created ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl apply -f pod-2.yaml pod/pod-svc-2 created ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-svc 1/1 Running 0 2m42s 10.244.171.174 vms82.liruilongs.github.io <none> <none> pod-svc-1 1/1 Running 0 80s 10.244.171.175 vms82.liruilongs.github.io <none> <none> pod-svc-2 1/1 Running 0 70s 10.244.171.176 vms82.liruilongs.github.io <none> <none> ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$
修改Nginx的主页,区分访问的pod,根据pod创建三个服务SVC
1 2 3 4 5 6 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS pod-svc 1/1 Running 0 3m7s run=pod-svc pod-svc-1 1/1 Running 0 105s run=pod-svc-1 pod-svc-2 1/1 Running 0 95s run=pod-svc-2
这个创建SVC通过 selector的方式
1 2 3 4 5 6 7 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$serve =pod-svc ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl exec -it $serve -- sh -c "echo $serve > /usr/share/nginx/html/index.html" ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl expose --name=$serve -svc pod $serve --port=80 service/pod-svc-svc exposed
1 2 3 4 5 6 7 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$serve =pod-svc-1 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl exec -it $serve -- sh -c "echo $serve > /usr/share/nginx/html/index.html" ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl expose --name=$serve -svc pod $serve --port=80 service/pod-svc-1-svc exposed
1 2 3 4 5 6 7 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$serve =pod-svc-2 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl exec -it $serve -- sh -c "echo $serve > /usr/share/nginx/html/index.html" ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl expose --name=$serve -svc pod $serve --port=80 service/pod-svc-2-svc exposed
创建了三个SVC做负载模拟
1 2 3 4 5 6 7 8 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR pod-svc-1-svc ClusterIP 10.99.80.121 <none> 80/TCP 94s run=pod-svc-1 pod-svc-2-svc ClusterIP 10.110.40.30 <none> 80/TCP 107s run=pod-svc-2 pod-svc-svc ClusterIP 10.96.152.5 <none> 80/TCP 85s run=pod-svc ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$
1 2 3 4 5 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl get ing No resources found in liruilong-svc-create namespace. ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$vim ingress.yaml
创建 Ingress,当然这里只是简单测试,可以更具具体业务情况配置复杂的路由策略 ingress.yaml,访问”/“的时候,会调度到三个SVC里,这里需要注意的是和kube-proxy没啥关系,Ngixn控制器内部的负载
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 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress annotations: kubernetes.io/ingress.class: "nginx" spec: rules: - host: liruilongs.nginx1 http: paths: - path: / pathType: Prefix backend: service: name: pod-svc-svc port: number: 80 - host: liruilongs.nginx2 http: paths: - path: / pathType: Prefix backend: service: name: pod-svc-1-svc port: number: 80 - host: liruilongs.nginx3 http: paths: - path: / pathType: Prefix backend: service: name: pod-svc-2-svc port: number: 80
创建查看Ingress。hsots中会列出所以的负载域名
1 2 3 4 5 6 7 ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl apply -f ingress.yaml ingress.networking.k8s.io/my-ingress created ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create] └─$kubectl get ing NAME CLASS HOSTS ADDRESS PORTS AGE my-ingress <none> liruilongs.nginx1,liruilongs.nginx2,liruilongs.nginx3 80 17s
负载测试
1 2 3 4 5 6 7 8 ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible 192.168.26.83 -m shell -a "curl liruilongs.nginx1" 192.168.26.83 | CHANGED | rc=0 >> pod-svc ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible 192.168.26.83 -m shell -a "curl liruilongs.nginx2" 192.168.26.83 | CHANGED | rc=0 >> pod-svc-1
这只是一个Ingress做SVC负载的一个Demo,时间关系,关于使用Ingree 做HTTP路由负载的Demo之后有时间和小伙伴分享,唉,心情不好,感觉浪费了好多时间,又啥也没学到