-
svc是什么
-
创建svc
-
服务发现,clusterip/变量/dns方式
-
服务的发布,nodeport,loadbalance/ingress
一、svc
1、svc基础
1、svc介绍
-
svc定义了pod的逻辑集合和访问该集合的策略,是真实服务的抽象,service提供了一个统一的服务访问入口以及服务代理和发现机制,用户不需要了解pod是如何运行的,service是通过标签来找到pod组
-
service在整个集群中负责网络服务的,因为pod是不可靠的,可能会被停止或者重启,一但发生重启,ip地址就会发生变化,service就是通过kube-proxy进行网络的控制,pod的ip发生变化上层的业务并不会中断,因为是通过标签进行控制的,kube-proxy是采用负载均衡实现网络服务的
2、创建一个nginx容器
bash
[root@k-master svc]# kubectl run n1 --image nginx --image-pull-policy IfNotPresent --dry-run=client -o yaml > n1.yaml
[root@k-master svc]# ls
n1.yaml
[root@k-master svc]# kubectl apply -f n1.yaml
pod/n1 created
[root@k-master svc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
n1 1/1 Running 0 9s 10.244.82.165 k-node1 <none> <none>
# 创建一个pod,会获取到一个地址,这个pod地址就是创建k8s集群的时候定义的
# pod用这个ip与其他的pod的ip进行访问
# 集群内部服务的ip地址
[root@k-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d
# ClusterIP 集群内部可用,,所有组件和pod都通过这个svc与api-server进行通信
- nginx创建出来后,没有创建svc的话,外面的主机是访问不到的,但是k8s集群可以访问到
bash
[root@k-master svc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
n1 1/1 Running 0 6m45s 10.244.82.165 k-node1 <none> <none>
[root@k-master svc]# curl 10.244.82.165
<!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>
# k8s节点可以访问到pod
# 但是外面的其他主机访问不到的
# 就需要创建nodeport暴露宿主机的端口,访问宿主机ip和宿主机的端口,从而访问内部的pod服务
3、容器做个端口映射(hostPort)
bash
[root@k-master svc]# cat n1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: n1
name: n1
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: n1
ports:
- containerPort: 80 # 容器的监听的端口是80
hostPort: 5000 # 映射到主机的5000端口,会自动的修改iptables规则
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
[root@k-master svc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
n1 1/1 Running 0 4s 10.244.82.161 k-node1 <none> <none>
# 浏览器访问
http://192.168.50.101:5000/
# 在node1上面查看端口映射
[root@k-node1 ~]# iptables -S -t nat|grep '5000 -j'
-A CNI-HOSTPORT-DNAT -p tcp -m comment --comment "dnat name: \"k8s-pod-network\" id: \"f649f99e0c48438052497ccc9de48bf524bf0d52c217ffc464c9b13d45d98d3f\"" -m multiport --dports 5000 -j CNI-DN-410cd4f2b8823751dd68e
-A CNI-DN-410cd4f2b8823751dd68e -s 10.244.82.161/32 -p tcp -m tcp --dport 5000 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-410cd4f2b8823751dd68e -s 127.0.0.1/32 -p tcp -m tcp --dport 5000 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-410cd4f2b8823751dd68e -p tcp -m tcp --dport 5000 -j DNAT --to-destination 10.244.82.161:80
- 但是了这种很麻烦
bash
# 但是了这种很麻烦
# 如果节点是2个,创建一个deployment,副本数为3个
# 这样的话,就会有一个处于pending的状态了,就是端口被占用了
# 并且没有负载均衡,因为访问模式是主机ip+端口,因此访问一个主机,另外一个主机是空闲的
# 就麻烦
2、svc的访问流程
-
创建svc的访问流程
-
外部用户请求访问主机+端口
-
service接收流量,通过pod所在物理主机上的kube-proxy将请求转发到后端pod(具有标签的)
- kube-proxy有2种模式,ipvs和iptables模式
-
pod处理请求,流量到达容器的80端口
-
也能实现负载均衡(最外层的)
-
是通过标签关联的pod
bash
# 每个节点有一个
[root@k-master svc]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5bbd96d687-rsnp6 1/1 Running 15 (112m ago) 16d
coredns-5bbd96d687-svq2d 1/1 Running 15 (112m ago) 16d
etcd-k-master 1/1 Running 15 (112m ago) 16d
kube-apiserver-k-master 1/1 Running 15 (112m ago) 16d
kube-controller-manager-k-master 1/1 Running 15 (112m ago) 16d
kube-proxy-fgct4 1/1 Running 16 (112m ago) 16d
kube-proxy-lfsvb 1/1 Running 15 (112m ago) 16d
kube-proxy-mk56p 1/1 Running 15 (112m ago) 16d
kube-scheduler-k-master 1/1 Running 15 (112m ago) 16d
metrics-server-7b8674ccdc-fdp29 1/1 Running 13 (112m ago) 15d
[root@k-master svc]#
3、创建一个简单的svc
1、创建deployment个svc
- 创建deployment,副本数为3个
bash
[root@k-master svc]# kubectl get deploy,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/d-nginx 3/3 3 3 16s
NAME READY STATUS RESTARTS AGE
pod/d-nginx-59f7778498-2fzkf 1/1 Running 0 16s
pod/d-nginx-59f7778498-9d2v7 1/1 Running 0 16s
pod/d-nginx-59f7778498-fhzgn 1/1 Running 0 16s
# 修改nginx网页目录,后续访问的时候可以区分开来
[root@k-master svc]# kubectl get pod
NAME READY STATUS RESTARTS AGE
d-nginx-59f7778498-2fzkf 1/1 Running 0 5m
d-nginx-59f7778498-9d2v7 1/1 Running 0 5m
d-nginx-59f7778498-fhzgn 1/1 Running 0 5m
[root@k-master svc]# kubectl exec -ti d-nginx-59f7778498-2fzkf -- /bin/bash
root@d-nginx-59f7778498-2fzkf:/# cd /usr/share/nginx/html/
root@d-nginx-59f7778498-2fzkf:/usr/share/nginx/html# ls
50x.html index.html
root@d-nginx-59f7778498-2fzkf:/usr/share/nginx/html# echo 1 > index.html
root@d-nginx-59f7778498-2fzkf:/usr/share/nginx/html# exit
exit
[root@k-master svc]# kubectl exec -ti d-nginx-59f7778498-9d2v7 -- /bin/bash
root@d-nginx-59f7778498-9d2v7:/# echo 2 > /usr/share/nginx/html/index.html
root@d-nginx-59f7778498-9d2v7:/# exit
exit
[root@k-master svc]# kubectl exec -ti d-nginx-59f7778498-fhzgn -- /bin/bash
root@d-nginx-59f7778498-fhzgn:/# echo 3 > /usr/share/nginx/html/index.html
root@d-nginx-59f7778498-fhzgn:/# exit
exit
-
创建svc,没有指定svc的名字,默认使用就是deploy的名字
-
svc自己有一个端口,targetport是pod开放的端口
bash
[root@k-master svc]# kubectl expose --name svc1 deployment d-nginx --port 5500 --target-port 80 --dry-run=client -o yaml > svc1.yaml
[root@k-master svc]# cat svc1.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: d-nginx
name: svc1
spec:
ports:
- port: 5500
protocol: TCP
targetPort: 80
selector: # 标签选择器
app: d-nginx
status:
loadBalancer: {}
# 集群内部的svc都会分配一个ip和端口,都是虚拟出来的,clusterip类型,这个就是内部访问的
[root@k-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d
svc1 ClusterIP 10.104.191.252 <none> 5500/TCP 2s
# matser访问
[root@k-master svc]# curl 10.104.191.252:5500
2
[root@k-master svc]# curl 10.104.191.252:5500
3
[root@k-master svc]# curl 10.104.191.252:5500
1
# 不能ping 这个svc,因为没有开放icmp,但是可以wget或者curl访问
- 但是了,上面的svc是ClusterIP类型的,外面的主机访问不到的
2、svc标签选择
-
自动的识别具有相同标签的pod并且关联
-
通过标签来定位pod
bash
[root@k-master svc]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d <none>
svc1 ClusterIP 10.104.191.252 <none> 5500/TCP 7m45s app=d-nginx
[root@k-master svc]# kubectl describe endpoints svc1
Name: svc1
Namespace: default
Labels: app=d-nginx
Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2025-08-05T09:52:48Z
Subsets:
Addresses: 10.244.108.18,10.244.82.163,10.244.82.169
NotReadyAddresses: <none>
Ports:
Name Port Protocol
---- ---- --------
<unset> 80 TCP
Events: <none>
[root@k-master svc]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
d-nginx-59f7778498-2fzkf 1/1 Running 0 18m app=d-nginx,pod-template-hash=59f7778498
d-nginx-59f7778498-9d2v7 1/1 Running 0 18m app=d-nginx,pod-template-hash=59f7778498
d-nginx-59f7778498-fhzgn 1/1 Running 0 18m app=d-nginx,pod-template-hash=59f7778498
4、服务发现
- pod与pod之间是怎么通信的
1、ClusterIP
-
是直接通过这个ClusterIP的ip地址实现的
-
默认情况下,创建的svc是不能ping通的,因为这是一个虚拟的网络接口,没有真正的mac地址,没有开放icmp协议,kube-proxy开放tcp和udp协议
1、wordpress与mysql
-
wordpress与mysql,之前是直接连接的
-
现在的话对于mysql创建一个svc-mysql,因此,wordpress连接svc-mysql就能连接到mysql,不需要知道mysql地址
-
有个问题wordpress的pod怎么发现的mysql-svc的ip的地址, 是通过ClusterIP发现的,通过这个可以访问到mysql
-
wordpress也是内网的,创建一个wordpress-svc,暴露出来
-
从而外部就能访问到了
-
有三种模式,clusterip,变量方式,dns方式
bash
客户端
|
|
wordpress-svc
|
|
wordpress
|
|
mysql-svc
|
|
mysql
2、创建一个mysql
bash
# 创建mysql个svc
kubectl run db --image mysql --image-pull-policy IfNotPresent --env="MYSQL_ROOT_PASSWORD=abc123" --env="MYSQL_DATABASE=wordpress" --dry-run=client -o yaml > db.yaml
# expose暴露pod的端口,port是svc的端口,target-port是容器暴露的端口
[root@k-master svc]# kubectl expose pod db --name db --port 3306 --target-port 3306
service/db exposed
# 创建出来的默认是ClusterIP类型
[root@k-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP 10.98.174.106 <none> 3306/TCP 3s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d
[root@k-master svc]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
db ClusterIP 10.98.174.106 <none> 3306/TCP 7m56s run=db
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d <none>
# 就可以通过svc来登录mysql了,集群内部访问
[root@k-master svc]# mysql -uroot -pabc123 -h 10.98.174.106
3、创建一个wordpress
bash
# 连接数据库的地址为mysql-svc
[root@k-master svc]# kubectl run blog --image wordpress --image-pull-policy IfNotPresent --env="WORDPRESS_DB_HOST=10.98.174.106" --env="WORDPRESS_DB_USER=root" --env="WORDPRESS_DB_PASSWORD=abc123" --env="WORDPRESS_DB_NAME=wordpress" --dry-run=client -o yaml > blog.yaml
[root@k-master svc]# kubectl get pod
NAME READY STATUS RESTARTS AGE
blog 1/1 Running 0 30s
db 1/1 Running 0 18m
-
上面的wordpress创建成功了,但是了客户端是访问不到的,因为都是内网的,因此需要暴露wordpress的端口,NodePort类型svc
-
mysql-svc是ClusterIP的,但是wordpress是NodePort类型的,客户端就能访问了
bash
[root@k-master svc]# kubectl expose pod blog --name blog --port 80 --target-port 80 --type NodePort
service/blog exposed
[root@k-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
blog NodePort 10.99.53.20 <none> 80:32254/TCP 3s
db ClusterIP 10.98.174.106 <none> 3306/TCP 15m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d
# 这样客户端就能通过访问任意一个主机的ip+32254端口就能实现访问了
-
因此的话,客户端只要能与k8s节点能够互相通信的话,就能实现访问wordpress了
-
浏览器访问
bash
192.168.50.100:32254
2、变量的方式
-
一个时间轴的方式
-
先创建一个svc1,再创建一个pod1,这样的话,pod1里面的环境变量会包含这个svc1,然后在创建svc2,pod1不包含,因为是后创建的
-
再次创建pod2的时候,就会包含之前的svc1,svc2了
-
加载的是同一个名称空间下面的svc,不同名称空间是隔离的,不会加载其他名称空间的svc
bash
# 创建一个临时容器就能查看到之前创建的svc了
[root@k-master svc]# kubectl run pod1 --image nginx --image-pull-policy IfNotPresent --rm -ti -- bash
If you don't see a command prompt, try pressing enter.
root@pod1:/# env | grep -i blog
BLOG_PORT=tcp://10.99.53.20:80
BLOG_PORT_80_TCP_PROTO=tcp
BLOG_SERVICE_HOST=10.99.53.20
BLOG_SERVICE_PORT=80
BLOG_PORT_80_TCP_ADDR=10.99.53.20
BLOG_PORT_80_TCP=tcp://10.99.53.20:80
BLOG_PORT_80_TCP_PORT=80
-
之前创建wordpress的时候需要指定mysql-svc的ip地址,因此现在使用环境变量的方式来指定mysql-svc的ip地址
-
这样的话,mysql-svc的ip地址的变化就不影响了
-
DB_SERVICE_HOST 是记录svc-mysql的ip地址
bash
[root@k-master svc]# cat blog.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: blog
name: blog
spec:
containers:
- env:
- name: WORDPRESS_DB_HOST
value: $(DB_SERVICE_HOST) # 引用环境变量
- name: WORDPRESS_DB_USER
value: root
- name: WORDPRESS_DB_PASSWORD
value: abc123
- name: WORDPRESS_DB_NAME
value: wordpress
image: wordpress
imagePullPolicy: IfNotPresent
name: blog
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
- 这种就是通过变量的方式来实现服务发现
3、DNS方式(非常的好用)
-
在kube-system名称空间下面,有dns的pod
-
在创建svc的时候,svc会在dns上自动注册,对于dns而言就知道了svc的ip地址了
-
创建svc,创建pod,pod可以直接通过svc的服务名来访问,就不需要知道svc的ClusterIP地址了
-
一个pod的完整的域名是 pod-hostname.service-name.namespace.svc.cluster.local
bash
# 创建一个nginxpod和svc
[root@k-master svc]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/blog 1/1 Running 0 21m
pod/db 1/1 Running 0 72m
pod/pod1 1/1 Running 0 37s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/blog NodePort 10.99.53.20 <none> 80:32254/TCP 50m
service/db ClusterIP 10.98.174.106 <none> 3306/TCP 66m
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d
service/nginx-svc ClusterIP 10.101.32.16 <none> 80/TCP 4s
# 创建一个临时容器,访问nginx-svc就能下载对应的文件了
# 访问nginx-svc就能访问后端的pod了
# 直接通过服务名来实现的访问,因为有dns的记录,不需要知道nginx-svc的地址
# 在访问nginx-svc的时候给dns服务器,解析ip地址,从而实现了访问
[root@k-master svc]# kubectl run busybox1 --image busybox --image-pull-policy IfNotPresent --rm -ti -- sh
If you don't see a command prompt, try pressing enter.
/ # wget nginx-svc
Connecting to nginx-svc (10.101.32.16:80)
saving to 'index.html'
index.html 100% |**********************| 615 0:00:00 ETA
'index.html' saved
/ #
# 访问nginx-svc就能转发到10.96.0.10对应的dnsPod,上面有记录nginx-svc的ip地址,从而实现了解析nginx-svc的ip地址,实现了访问
/ # cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
-
但是了a空间的pod不能解析b空间的svc,有名称空间的隔离性
-
但是了也是可以访问的,需要带上完整的域名
bash
# 在test空间下创建pod和svc
[root@k-master svc]# kubectl expose pod pod1 --name t1 --port 80 --target-port 80 -n test
service/t1 exposed
[root@k-master svc]# kubectl get pod,svc -n test
NAME READY STATUS RESTARTS AGE
pod/pod1 1/1 Running 0 35s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/t1 ClusterIP 10.105.212.6 <none> 80/TCP 7s
# 在default空间访问,默认是访问到的
/ # wget t1
wget: bad address 't1'
# 可以通过svc.名称空间来实现不同空间下的方式
/ # wget t1.test
Connecting to t1.test (10.105.212.6:80)
saving to 'index.html'
index.html 100% |************************************************************************************************************************************| 615 0:00:00 ETA
'index.html' saved
/ #
- 回到上面的wordpress实验
bash
# 删除wordpress的pod
# 可以直接输出svc名称来实现访问
[root@k-master svc]# cat blog.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: blog
name: blog
spec:
containers:
- env:
- name: WORDPRESS_DB_HOST
value: db # 直接使用mysql-svc的名称,就能实现解析成ip地址,实现访问
- name: WORDPRESS_DB_USER
value: root
- name: WORDPRESS_DB_PASSWORD
value: abc123
- name: WORDPRESS_DB_NAME
value: wordpress
image: wordpress
imagePullPolicy: IfNotPresent
name: blog
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
- pod之间使用svc来进行访问
bash
# 创建2个nginx pod 和2个svc
[root@k-master svc]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/n1 1/1 Running 0 3m21s
pod/n2 1/1 Running 0 2m46s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
service/n1-svc ClusterIP 10.101.93.97 <none> 80/TCP 2m21s
service/n2-svc ClusterIP 10.105.67.195 <none> 80/TCP 2m11s
[root@k-master svc]# kubectl exec -ti n1 -- /bin/bash
# 在同一个名称空间下面,可以直接访问服务名称来实现通信
root@n1:/# curl n2-svc
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
# 因为n1的dns是集群内部的dns服务器,创建svc会在这个dns服务器上面进行注册,因此n1去dns服务器找到了这个域名对应的ip地址,从而实现了访问
root@n1:/# cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
4、服务发现总结
-
上面的wordpress与mysql的连接有多种方式,也就是服务发
-
通过dns发现,在同一个名称空间下面可以直接访问svc的名称就能实现访问了svc对应的pod
-
第二个通过变量,后创建的pod会加载同一个空间下的svc,因此就有一个环境变量记录了svc的ip地址,通过这个svc的变量名称来实现了访问
-
第三个使用ClusterIP,来实现了访问了pod
-
都是集群内部之间互相通信的,pod与pod之间进行访问的方式
-
但是了,客户端是不能进行访问到的,因为都是集群内网的
-
pod之间的访问,可以通过svc来进行访问,因为svc后台关联的就是pod,不需要访问pod,即可
5、服务发布
1、NodePort
-
之前的ClusterIP是集群内部进行访问的,因此web客户端不能进行访问集群内部的服务
-
NodePort就是做一个端口映射,访问物理主机+端口就能访问到集群内部的服务了
-
创建出来后,每个物理主机都有这个端口,并不是只有这一个主机
-
生成一个3w以上的端口
bash
[root@k-master svc]# kubectl get deployments.apps,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 3/3 3 3 2m23s
NAME READY STATUS RESTARTS AGE
pod/nginx-57cc89bc77-dqrjr 1/1 Running 0 2m23s
pod/nginx-57cc89bc77-lxq2h 1/1 Running 0 2m23s
pod/nginx-57cc89bc77-p7tst 1/1 Running 0 2m23s
[root@k-master svc]# kubectl expose deployment nginx --name nginx-svc --port 80 --target-port 80 --type NodePort
service/nginx-svc exposed
# 启用了30081端口,这个端口可以修改的NodePort指定的
[root@k-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
nginx-svc NodePort 10.100.250.171 <none> 80:30081/TCP 82s
# 每个主机都开放了这个端口
[root@k-master svc]# iptables -S -t nat | grep 30081
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/nginx-svc" -m tcp --dport 30081 -j KUBE-EXT-HL5LMXD5JFHQZ6LN
# 浏览器访问
http://192.168.50.100:30081/
http://192.168.50.101:30081/
http://192.168.50.102:30081/
-
访问的流程
-
先访问主机ip+端口
-
会转发到svc的ip+端口(充当一个负载均衡器)
-
然后转发到后端关联的pod,从而实现了访问
-
2、LoadBalance
-
默认的情况下,集群内部的主机是不会暴露在互联网上的,前面还有负载均衡器,防火墙等等,可以把防火墙或者LB的端口80暴露出去,然后80端口转发到指定端口上面去,通过DNS指定到防火墙或者LB上
-
loadbanlance 有一个公网的ip地址,创建svc类型为LB,会从公网地址池中分配一个公网ip地址
bash
[root@k-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
nginx-svc NodePort 10.100.250.171 <none> 80:30081/TCP 46m
# external-ip就是公网ip
1、使用第三方插件来模拟LB
- 下载文件
bash
[root@k-master svc]# wget https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml
kubectl apply -f metallb-native.yaml
[root@k-master svc]# kubectl get pod -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-68bf958bf9-5pzb5 1/1 Running 0 7m35s
speaker-2l6nf 1/1 Running 0 7m35s
speaker-m5cqg 1/1 Running 0 7m35s
speaker-pvxm4 1/1 Running 0 7m35s
2、创建地址池和绑定
bash
# 安装一个网络计算工具
yum -y install sipcalc
[root@k-master svc]# sipcalc 192.168.50.100/24
-[ipv4 : 192.168.50.100/24] - 0
[CIDR]
Host address - 192.168.50.100
Host address (decimal) - 3232248420
Host address (hex) - C0A83264
Network address - 192.168.50.0
Network mask - 255.255.255.0
Network mask (bits) - 24
Network mask (hex) - FFFFFF00
Broadcast address - 192.168.50.255
Cisco wildcard - 0.0.0.255
Addresses in network - 256
Network range - 192.168.50.0 - 192.168.50.255
Usable range - 192.168.50.1 - 192.168.50.254
bash
# 创建地址池
[root@k-master svc]# cat pools.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.50.200-192.168.50.220
# 创建实例绑定地址池
[root@k-master svc]# cat l2.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
[root@k-master svc]# kubectl get ipaddresspools.metallb.io -n metallb-system
NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES
first-pool true false ["192.168.50.200-192.168.50.220"]
3、创建svc
- 自动分配地址
bash
# 因为是LoadBalancer,所以会自动的分配外部ip地址,从之前创建的地址池中分配一个地址
# 如果是对外提供的,就需要使用公网ip
[root@k-master svc]# kubectl expose deployment nginx --name svc666 --port 80 --target-port 80 --type LoadBalancer
service/svc666 exposed
[root@k-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
svc666 LoadBalancer 10.99.233.85 192.168.50.200 80:31439/TCP 3s
4、访问
bash
# 直接访问这个模拟出来的公网ip地址就能访问到后端关联的pod
# 不需要添加端口
# 如果购买了域名的话,可以使用域名访问
[root@k-master svc]# curl 192.168.50.200
<!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>
3、Ingress
-
上面的NodePort的创建,如果需要创建很多的话,就需要占用很多的端口,安全风险就很大
-
是一个管理从集群外部到集群内部服务的http和https路由
-
只需要一个公网ip,所有的外部流量从这个入口进入
-
智能路由的功能,请求的主机名和路径将流量分发到后端不同的service
bash
# 流量的分发靠的就是这个ingress-nginx-controller和自己配置的ingress规则
[root@k-master ingress]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-gj9cg 0/1 Completed 0 84m
ingress-nginx-admission-patch-txm4g 0/1 Completed 0 84m
ingress-nginx-controller-6465b759fb-fsc4s 1/1 Running 0 84m
1、正向代理
- pc电脑访问华为云的过程中,有一个代理,一般用于出去
2、反向代理
- 用户访问百度的时候,反向代理关联的是服务器,而不是自己的pc电脑
3、ingress定义
-
可以定义规则
-
访问不同的域名转向不同的后台
-
访问1.com指向server1
-
访问2.com指向server2
4、创建三个pod和三个svc
-
使用的nginx镜像是
-
创建三个nginx的pod
bash
[root@k-master ~]# kubectl run n1 --image nginx --image-pull-policy IfNotPresent
pod/n1 created
[root@k-master ~]# kubectl run n2 --image nginx --image-pull-policy IfNotPresent
pod/n2 created
[root@k-master ~]# kubectl run n3 --image nginx --image-pull-policy IfNotPresent
pod/n3 created
[root@k-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
n1 1/1 Running 0 9s
n2 1/1 Running 0 6s
n3 1/1 Running 0 3s
# 修改访问页面
[root@k-master ~]# kubectl exec -ti n1 -- /bin/bash
root@n1:/# cd /usr/share/nginx/html/
root@n1:/usr/share/nginx/html# ls
50x.html index.html
root@n1:/usr/share/nginx/html# echo n1 > index.html
root@n1:/usr/share/nginx/html# exit
exit
[root@k-master ~]# kubectl exec -ti n2 -- /bin/bash
root@n2:/# cd /usr/share/nginx/html/
root@n2:/usr/share/nginx/html# ls
50x.html index.html
root@n2:/usr/share/nginx/html# echo n2 > index.html
[root@k-master ~]# kubectl exec -ti n3 -- /bin/bash
root@n3:/# ls
bin docker-entrypoint.d home media proc sbin tmp
boot docker-entrypoint.sh lib mnt root srv usr
dev etc lib64 opt run sys var
root@n3:/# cd /usr/share/nginx/html/
root@n3:/usr/share/nginx/html# ls
50x.html index.html
# 在html下面创建一个abc目录,并且创建一个index.html,模拟不同的页面
root@n3:/usr/share/nginx/html# mkdir abc
root@n3:/usr/share/nginx/html# ls
50x.html abc index.html
root@n3:/usr/share/nginx/html# cd abc/
root@n3:/usr/share/nginx/html/abc# ls
root@n3:/usr/share/nginx/html/abc# echo n3-abc > index.html
root@n3:/usr/share/nginx/html/abc# ls
index.html
root@n3:/usr/share/nginx/html/abc# exit
exit
bash
[root@k-master ~]# kubectl expose pod n1 --name svcn1 --port 80 --target-port 80
service/svcn1 exposed
[root@k-master ~]# kubectl expose pod n2 --name svcn2 --port 80 --target-port 80
service/svcn2 exposed
[root@k-master ~]# kubectl expose pod n3 --name svcn3 --port 80 --target-port 80
service/svcn3 exposed
[root@k-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d
svc666 LoadBalancer 10.99.233.85 192.168.50.200 80:31439/TCP 17d
svcn1 ClusterIP 10.106.109.188 <none> 80/TCP 20s
svcn2 ClusterIP 10.99.5.184 <none> 80/TCP 9s
svcn3 ClusterIP 10.101.42.143 <none> 80/TCP 3s
5、使用ingress-nginx镜像
-
使用下面这个deploy.yaml文件,注意版本
bash
[root@k-master ingress]# kubectl apply -f ingress-deploy.yaml namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
# 会有一个名称空间,pod
[root@k-master ingress]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-gj9cg 0/1 Completed 0 110s
ingress-nginx-admission-patch-txm4g 0/1 Completed 0 110s
ingress-nginx-controller-6465b759fb-fsc4s 1/1 Running 0 110s
[root@k-master ingress]# kubectl get deployments.apps -n ingress-nginx
NAME READY UP-TO-DATE AVAILABLE AGE
ingress-nginx-controller 1/1 1 1 2m58s
# 有这些svc的服务
[root@k-master ingress]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.101.96.191 192.168.50.201 80:31626/TCP,443:31346/TCP 119s
ingress-nginx-controller-admission ClusterIP 10.98.162.172 <none> 443/TCP 119s
[root@k-master ingress]#
- 使用的是LB这个svc,就能实现访问了ingress-nginx-controller了
6、定义ingress规则
- 访问哪一个域名指向哪一个svc,从而实现哪一个网站
bash
[root@k-master ingress]# cat in.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
spec:
rules:
- host: www.meme1.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svcn1
port:
number: 80
- host: www.meme2.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svcn2
port:
number: 80
- path: /abc
pathType: Prefix
backend:
service:
name: svcn3
port:
number: 80
# 访问 meme1.com 指向的是svcn1
# 访问meme2.com 指向的是svcn2
# 访问meme2.com/abc 只想的是svcn3
- 创建class类,使用默认的ingress,否则会报错
bash
[root@k-master ingress]# kubectl edit ingressclasses.networking.k8s.io
ingressclass.networking.k8s.io/nginx edited
8 annotations:
9 ingressclasses.kubernetes.io/is-default-class: "true"
- 运行ingress规则
bash
[root@k-master ingress]# kubectl apply -f in.yaml
ingress.networking.k8s.io/my-app-ingress created
[root@k-master ingress]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
my-app-ingress <none> www.meme1.com,www.meme2.com 80 36s
[root@k-master ingress]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
my-app-ingress <none> www.meme1.com,www.meme2.com 80 36s
[root@k-master ingress]# kubectl describe ingress
Name: my-app-ingress
Labels: <none>
Namespace: default
Address:
Ingress Class: <none>
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
www.meme1.com
/ svcn1:80 (10.244.82.155:80)
www.meme2.com
/ svcn2:80 (10.244.82.148:80)
/abc svcn3:80 (10.244.108.41:80)
Annotations: <none>
Events: <none>
bash
# 记录ingress-nginx-controller中的node1的ip地址为192.168.50.101
[root@k-master ingress]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-gj9cg 0/1 Completed 0 30m 10.244.108.42 k-node2 <none> <none>
ingress-nginx-admission-patch-txm4g 0/1 Completed 0 30m 10.244.82.149 k-node1 <none> <none>
ingress-nginx-controller-6465b759fb-fsc4s 1/1 Running 0 30m 10.244.82.146 k-node1 <none> <none>
7、浏览器访问
-
需要的就是这个LB的svc的ip地址与域名进行绑定
-
通过这个地址就能实现访问了ingress-nginx-controller了
bash
http://www.meme2.com/abc/
http://www.meme1.com/
8、ingress访问的整个流程
-
客户端访问域名,dns解析为LB的ip地址
-
访问LB对应的后端ingress-nginx-controller这个pod
-
然后根据自己编写的ingress规则,实现访问后端的pod
-
LB是这个集群的大门,获取了一个稳定的公网ip,外面访问的唯一入口
-
ingress controller 是一个智能路由器,守在大门内部,根据详细的ingress规则指挥流量去往不同的服务
-
ingress规则是路由表,定义了什么样的请求,哪一个域名,哪一个路径,被送到哪一个后端服务
-
后端服务是终点站,负责接收智能路由器的流量,转发给对应的pod
-
ingress-controller会监控所有名称空间下面的所有的ingress规则