创建service的时候必须打标签,并且与创建的deployment或者pod的标签一致
通过kubectl create deployment web --image=nginx --dry-run=client -o yaml > web-dp.yaml
命令导出deployment文件:
yaml示例:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web # deployment的标签
name: web
spec:
replicas: 3
selector: # 标签选择器
matchLabels:
app: web
template:
metadata:
labels:
app: web # Pod的标签
project: blog
spec:
containers:
- image: nginx
name: nginx
resources: {}
注意:
- 标签选择器里的标签是筛选Pod用的
- Pod的标签支持多个
应用:
kubectl apply -f web-dp.yaml
查看标签:
[root@k8s-master k8s]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
web-5b9bff6674-8wjlq 1/1 Running 0 12s app=web,pod-template-hash=5b9bff6674,project=blog
web-5b9bff6674-99ltd 1/1 Running 0 33s app=web,pod-template-hash=5b9bff6674,project=blog
web-5b9bff6674-skgsj 1/1 Running 0 15s app=web,pod-template-hash=5b9bff6674,project=blog
暴露服务:
kubectl expose deployment web --port=80 --target-port=80 --name=web --dry-run=client -o yaml > web-svc.yaml
参数解释:
--port
:k8s集群内部访问端口--target-port
:容器中服务提供端口,即应用程序端口,如nginx提供80 ,mysql提供3306--protocol
:指定协议类型,如TCP、UDP,SCTP等--name
:给svc起名,一般svc的名称与deployment一致
yaml示例:
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80 # 内部访问端口
protocol: TCP
targetPort: 80 # 容器提供服务的端口
selector:
app: web # 标签与deployment中Pod定义的标签一致
project: blog
应用:
kubectl apply -f web-svc.yaml
查看svc标签:
[root@k8s-master k8s]# kubectl get svc --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47m component=apiserver,provider=kubernetes
web ClusterIP 10.101.205.162 <none> 80/TCP 18m app=web
注意:从中可以发现,web这个Service的标签中并没有Project=blog这个标签,这是因为svc中app=web标签是svc本身的,它不是用于去关联Pod的,svc的详细信息可以使用
kubectl get svc -o wide
:
[root@k8s-master k8s]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47m <none>
web ClusterIP 10.101.205.162 <none> 80/TCP 18m app=web,project=blog
正常来讲,在任何节点机器上curl 10.101.205.162
是可以访问到的,而且svc中的IP地址是非常稳定的,只要这个svc资源不被删除,这个IP就会一直存在。
ClusterIP
:集群内部使用expose的默认类型,为一组pod分配一个稳定的虚拟IP,作为这组Pod提供统一入口,集群之外无法问问,只能在集群内部访问
(同Namespace内的Pod)
NodePort
:对外暴露应用在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。访问地址:<NodeIP>:<NodePort>
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
project: blog
type: NodePort
注意:
type
与ports
同级
[root@k8s-master k8s]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 61m
web NodePort 10.101.205.162 <none> 80:31495/TCP 11m
其中,31495
为宿主机端口,每个节点都会监听这个端口,而且这个端口是kube-proxy
创建的
[root@k8s-master k8s]# netstat -antp | grep 31495
tcp 0 0 0.0.0.0:31495 0.0.0.0:* LISTEN 2581/kube-proxy
当然,这个宿主机端口号也可以固定,写法如下(端口号范围:3000
-32767
):
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80 # 集群内部端口
protocol: TCP # 协议
targetPort: 80 # 容器端口
nodePort: 30000 # 节点端口
selector: # 标签选择器,关联对应Pod
app: web
project: blog
type: NodePort # 指定类型
[root@k8s-master k8s]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 74m
web NodePort 10.101.205.162 <none> 80:30000/TCP 23m
[root@k8s-master k8s]# netstat -antp | grep 3000
tcp 0 0 0.0.0.0:30000 0.0.0.0:* LISTEN 2581/kube-proxy
补充:
kube-proxy
:实现Service的功能,包含服务发现和提供负载均衡的能力。
LoadBalancer
:对外暴露应用,适用公有云与NodePort
类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台上的负载均衡器,将每个Node ([NodeIP]:[NodePort]
)作为后端添加进去。
LB解决的问题
前面加一个负载均衡器(公网):
工作流程:user
-> lb
-> node:port
-> [service]
-> pod
Service代理模式分为:Iptables
和IPVS
proxy模式:
iptables
(默认使用):用户态的工具主要用于netfilter规则管理ipvs
: # kubectl edit configmap kube-proxy -n kube-system
mode: "ipvs"
# kubectl delete pod kube-proxy-btz4p -n kube-system
# yum install ipvsadm -y
# ipvsadm -L -n
查看Service网络规则
iptables-save | grep <svc-name>
1.将/opt/kubernetes/cfg/kube-proxy-config.yaml
配置文件中,注销mode
参数,并在后面添加ipvs
(下面的一些参数是ipvs
的调度算法)
2.重启kube-proxy服务即可生效:
systemctl restart kube-proxy
3.安装ipvsadm
工具去查看ipvs规则:
yum -y install ipvsadm
ipvsadm -L -n
参数解释:
-L
:列出规则-n
:以数字而不是以主机名的形式显示IP地址1.由于kube-proxy
保存在k8s资源中,故需要编辑configmap
的配置文件
[root@k8s-master k8s]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
kube-proxy-grnpw 1/1 Running 11 12d
kube-proxy-mshjk 1/1 Running 11 12d
kube-proxy-nkkk4 1/1 Running 11 12d
[root@k8s-master k8s]# kubectl get configmaps -n kube-system
NAME DATA AGE
kube-proxy 2 12d
2.打开kube-peoxy的configmap:
kubectl edit configmap kube-proxy -n kube-system
3.找到mode
参数,在引号中写入ipvs
,保存即可
4.删除kube-proxy
的pod重建,等待集群自动拉起,ipvs即可生效:
kubectl delete pod kube-proxy-grnpw -n kube-system
kubectl delete pod kube-proxy-mshjk -n kube-system
kubectl delete pod kube-proxy-nkkk4 -n kube-system
[root@k8s-master k8s]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
kube-proxy-272qn 1/1 Running 0 42s
kube-proxy-gvq2n 1/1 Running 0 33s
kube-proxy-jbjfc 1/1 Running 0 61s
5.利用ipvsadm -L -n
命令查看规则
Iptables:
IPVS:
参数解释:
rr
:轮询模式wrr
:加权轮询模式lc
:最小连接模式wlc
:加权连接模式ip hash
:[root@k8s-master k8s]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7ff77c879f-cgfjw 1/1 Running 11 12d
coredns-7ff77c879f-pn8qk 1/1 Running 12 12d
DNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析。
测试coredns
,使用busybox:1.28.4
镜像并进入pod中
[root@k8s-master k8s]# kubectl run -it --rm --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
/ #
正常来讲,在这个busybox的Pod中是ping的通上面创建的svc的IP地址的,也可以访问svc的页面。
/ # ping 10.101.205.162
PING 10.101.205.162 (10.101.205.162): 56 data bytes
64 bytes from 10.101.205.162: seq=0 ttl=64 time=0.101 ms
64 bytes from 10.101.205.162: seq=1 ttl=64 time=0.099 ms
64 bytes from 10.101.205.162: seq=2 ttl=64 time=0.101 ms
64 bytes from 10.101.205.162: seq=3 ttl=64 time=0.107 ms
^C
--- 10.101.205.162 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.099/0.102/0.107 ms
/ # wget 10.101.205.162
Connecting to 10.101.205.162 (10.101.205.162:80)
index.html 100% |******************************************************************************************| 612 0:00:00 ETA
/ #
可以使用nslookup
命令解析dns名称
/ # nslookup web
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: web
Address 1: 10.101.205.162 web.default.svc.cluster.local
解析出来的IP对应svc的IP地址
注意:
nslookup
默认不能跨命名空间使用,若想解析跨命名空间的dns,则需要使用全格式
ClusterIP A记录格式:<service-name>.<namespace-name>.svc.cluster.local
示例:my-svc.my-namespace.svc.cluster.local
Pod在发送dns请求的时候,实际上是请求的/etc/resolv.conf
文件中的dns,这个dns就是部署coredns
的Service
,所以执行nslookup
命令时是向coredns发出请求,而coredns
里面有Service对应IP的记录,之后响应记录结果,并且coredns
对域名也有区分,若判断为外部域名,则走上层宿主机dns进行解析,然后再响应给Pod。
总结:
pod -> coredns service(10.0.0.2) -> coredns(service/clusterip记录) ->响应A记录结果
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
[root@k8s-node1 manifests]# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 12d
总结:
采用NodePort对外暴露应用,前面加一个LB实现统一访问入口
优先使用IPVS代理模式
IPVS性能高,调度算法丰富,可以满足多业务大并发的场景下
集群内应用采用DNS名称访问
当切换集群或者换ServiceIP的时候对应于程序没什么影响
“The first 90% of the code accounts for the first 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time.” – Tom Cargill
标 题:kubernetes网络简介(上)