k8s的Service概念及常用操作
Service常用操作
创建Service
一个Service支持暴露多个端口: 多端口 Service-yaml示例
创建Service的yaml示例
为service再发布一个service
https://blog.youkuaiyun.com/zhengzaifeidelushang/article/details/122545435
# 将nginx服务的8443端口暴露为443,并在创建一个新服务名为nginx-https
kubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https
kubectl为deployment创建service
# 将一个已存在的deployment暴露为新的service
kubectl espose deployment/应用名 -–type=NodePort -—port 8080
# 为tomcatdemo的8080端口映射为80端口,暴露方式为NodePort,NodePort端口会随机生成
## --port=80 集群内部的端口
## --target-port=8080 容器中应用的端口
## --type=NodePort 暴露端口的方式,NodePort是允许外网访问
kubectl expose deployment tomcatdemo --port=80 --target-port=8080 --type=NodePort
svc暴露UDP服务端口
## --protocol=UDP 暴露UDP端口
kubectl expose deployment 应用名 --port=服务端口 --protocol=UDP --target-port=容器内端口 --type=NodePort --name=服务名-udp --save-config -o yaml --dry-run=client
yaml资源清单创建
apiVersion: v1
kind: Service
metadata:
name: gost-udp
spec:
selector:
app: gost
type: NodePort
ports:
- name: udp
port: 3389
protocol: UDP
targetPort: 1080
- name: tcp
port: 3389
protocol: UDP
targetPort: 1080
yaml创建service
在vscode中创建yaml文件,输入service
即可自动补全。
https://blog.youkuaiyun.com/omaidb/article/details/125104491
https://blog.youkuaiyun.com/omaidb/article/details/121855353
生成service的yaml资源清单
# 生成service的yaml资源清单
## --port=80 集群内部的端口
## --target-port=8080 pod中容器的端口
## --type=NodePort 暴露端口的方式,NodePort是允许外网访问
## --save-config 加到注释中
kubectl expose deployment gost --port=3389 --target-port=1080 --type=NodePort --name=gost --save-config -o yaml --dry-run=client > my-service.yaml
apply资源清单
# apply这个service的yaml资源清单
kubeclt apply -f my-server.yaml
查看创建的service
# 查看{deployment:gost}的service的端口
## NodePort外部访问的端口是随机生成的,端口在30000以上
## NodePort端口是在node宿主机上暴露的随机端口
kubectl get services gost
# 查看service关联的pod的ip地址和端口号
kubectl get svc,endpoints tomcatdemo
## 访问http://masterip:31102/即可成功访问到gost的页面
# 查看宿主机上监听的端口
netstat -tunlp|grep 31102
lsof -i:31102
查看svc选择的标签
# 查看指定service选择的标签
kubectl get svc gost --show-labels
# 通过yaml方式查看service选择的标签
kubectl get svc gost -o yaml|grep -A 2 selector
修改Service的端口
# 修改svc的端口
kubectl edit svc/svc名
删除Service
# 1.删除服务
## 1.1查看服务
kubectl get sv
## 1.2删除服务
kubectl delete svc/服务名
# 2.删除deployment
## 2.1查看deployments
kubectl get deployments
## 2.2删除deployments
kubectl delete deployments/应用名
Service(服务)概念
Service也是k8s里核心的资源对象之一, k8s里面的每个Service就是我们提起的“微服务”,之前所介绍的Pod、 RC等资源都是为Service做“嫁衣”的。
Service定义了一个服务的访问入口地址, 前端的应用( Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实例, Service与其后端Pod副本集群之间是通过Label Selector来实现“无缝对接”的。而RC的作用实际上是保证Service的服务能力和服务质量始终处于预期的标准。通过分析、识别并建模系统中的所有服务的微服务,最终我们的系统由多个提供不同业务功能而又彼此独立的微服务单元所组成,服务之间通过TCP/IP进行通信,从而形成了我们强大而又灵活的弹性网络,拥有了强大的分布式能力、弹性扩展能力、容错能力.
运行在Node节点上的kube-proxy
进程其实就是一个智能的负载均衡器,他负责把Service的请求转发到后端的某个Pod实例上, 并在内部实现服务的负载均衡与会话保持机制。
但是Service不是共用一个负载均衡器的IP地址,而是每个Service分配了一个全局唯一的虚拟IP地址,这个虚拟IP地址称为Cluster IP
。这样一来,每个服务就变成了具备唯一IP地址的“通信节点” ,服务调用就变成了最基础的TCP/IP网络通信问题。 Service一旦创建, k8s就会自动为期分配一个可用的Cluster IP
,而且在Service的整个生命周期内,他的Cluster IP不会发生改变。只要用Service的Name与Service的Cluster IP地址做一个DNS域名映射即可完成服务发现.
k8s通过插件的方式引入了DNS系统(CoreDNS),把服务名作为DNS域名,这样程序就可以直接使用服务名来建立通信连接了。
什么是Service
参考 https://www.toutiao.com/a6938010733057688102/?log_from=815c41886752e_1646033414390
k8s中service的定义:
- 将一组pod公开为网络服务的抽象方法.
Service引入主要是解决Pod的动态变化,提供统一访问人口: - 防止Pod失联,找到提供同一个服务的Pod(服务发现)
- 定义一组Pod的访问策略(负载均衡)
创建一个pod,同时也会创建一个对应的EndPoint
理解k8s系统里面的三种IP:
Node IP
: Node节点的IP地址
Node IP
是k8s集群中每个节点的物理网卡IP地址,他是一个真实存在的物理网络,所有属于这个网络的服务器之间都能通过这个网络直接通信,不管他们中是否有部分节点不属于这个k8s集群,这个也表明k8s集群之外的节点访问k8s集群内的某个节点或者TCP/IP服务时,必须使用Node IP进行通信。
Pod IP
: Pod的IP地址
Pod IP
是每一个Pod的IP,他是Docker Engine根据docker0网桥的IP地址进行分配的,通常是一个虚拟的二层网络。k8s位于不同Node上的Pod能够直接通信,所以k8s里的一个Pod里面容器访问另一个Pod里面的容器,就是通过Pod IP所在的虚拟二层网络实现通信的,而真实的TCP/IP流量则是通过Node IP所在的物理网卡流出的。
Cluster IP
: Service的IP地址,cluster ip只能在容器内访问
Cluster IP
:它也是一个虚拟的IP,更像一个“伪造”的IP地址。应用内访问使用这个IP.
Service常用三种服务类型(NodePort
和LoadBalancer
)
ClusterIP
:默认,分配一个集群内部可以访问的虚拟IP(VIP)NodePort
:在每个Node上分配一个端口作为外部访问入口LoadBalancer
:与NodePort类似,在每个节点上启用一个端口来暴露服务,除此之外,K8S会请求底层云平台(aliyun, aws等)上负载均衡器,将每个Node([NodeIP]:[NodePort])
作为后端添加进去.创建LoadBalancer
类型的Service
会自动创建和绑定外部LoadBalancer
到节点映射的NodePort
上。
Service DNS名称
官方文档: https://kubernetes.io/zh/docs/concepts/services-networking/dns-pod-service/
参考: https://kubernetes.renkeju.com/chapter_6/6.3.3.ClusterDNS_and_service_discovery.html
ClusterDNS
配置文件
[node root ~]# cat /var/lib/kubelet/config.yaml|grep -i -A1 clusterdns
clusterDNS:
- 10.80.0.10
ClusterIP A记录格式:
<service-name>.<namespace-name>.svc.cluster.local
示例:
my-svc.my-namespace.svc.cluster.local
svc域名格式
k8s中service的域名规则
服务名.命名空间名.svc
根据svc的ip地址查询svc域名
clusterIP
的Service域名
解析响应的DNS记录类型
是A记录
.
nslookup
和host
命令来自bind-utils
包
# 安装bind-utils
yum install bind-utils -y
# 查询clusterDNS
[node root ~]# cat /var/lib/kubelet/config.yaml|grep -i -A1 clusterdns
clusterDNS:
- 10.80.0.10
# 使用clusterDNS根据svc的ip地址查询svc的域名
## nslookup 要反查的ip地址 指定要使用的DNS地址(clusterDNS地址)
[master root ~]# nslookup 10.83.28.128 10.80.0.10
128.28.83.10.in-addr.arpa name = web.aliang-cka.svc.cluster.local.
# 使用host命令指定dns查询svc的域名
host ip地址 指定dnsip
[master root ~]# host 10.83.28.128 10.80.0.10
Using domain server:
Name: 10.80.0.10
Address: 10.80.0.10#53
Aliases:
128.28.83.10.in-addr.arpa domain name pointer web.aliang-cka.svc.cluster.local.
普通的 Service:
会生成servicename.namespace.svc.cluster.local
的域名,会解析到 Service 对应的 ClusterIP 上,
在 Pod 之间的调用
可以简写成 servicename.namespace
,
如果处于同一个命名空间下面
,甚至可以只写成 servicename
即可访问
Headless Service:
无头服务,就是把 clusterIP 设置为 None 的,会被解析为指定 Pod 的 IP 列表,同样还可以通过podname.servicename.namespace.svc.cluster.local
访问到具体的某一个 Pod。
service分发策略
一种是 轮询模式
一种是会话保持模式
修改kube-proxy代理模式
services
由kube-proxy
管理的.负载均衡默认是用的iptables
;可以手动修改为ipvs
.
查看负载均衡规则
# iptables模式查看负载均衡规则
iptables-save|grep service名
# ipvs模式查看负载均衡规则
ipvsadm -L -n
安装IPVS
参考 Centos安装IPVS
kubeadm方式修改为ipvs模式:
# 修改configmap kube-proxy
kubectl -n kube-system edit cm kube-proxy
搜索mode
关键字,参数默认为“ ”
# 修改为ipvs模式
mode: "ipvs"
删除所有kube-proxy的pod,重建所有节点kube-proxy
# 重建所有kube-proxy的pod
kubectl -n kube-system delete pod kube-proxy-*
ipvs模式查看负载均衡规则
# ipvs模式查看负载均衡规则
ipvsadm -L -n
二进制安装方式修改ipvs模式
# 查看kube=proxy配置目录
systemctl cat kube-proxy
# 修改kube-proxy配置文件
vim kube-proxy-config.yaml
# 修改配置为ipvs
mode: ipvs
ipvs:
scheduler: "rr "
# 重启kube-proxy服务
systemctl restart kube-proxy
ipvs模式查看负载均衡规则
# ipvs模式查看负载均衡规则
ipvsadm -L -n
service解除nodeport端口限制
vim /etc/kubernetes/manifests/kube-apiserver.yaml
设置service-node-port-range=20000-50000
,删除原有pod即可,静态pod无需自己再kubectl apply
,会自动watch
到的
编辑master节点的kube-apiserver.yaml
service NodePort 模式
默认只能开放 30000-32767
端口,解除限制方法:
- 登录 master节点 编辑文件
/etc/kubernetes/manifests/kube-apiserver.yaml
# 修改文件添加 - --service-node-port-range=0-65535
sed -i '/--service-cluster-ip-range/a\ - --service-node-port-range=0-65535' /etc/kubernetes/manifests/kube-apiserver.yaml
# ......
重启所有master节点apiserver容器
# 重启所有master节点apiserver
kubectl get pod -n kube-system | grep apiserver
kubectl delete pod -n kube-system kube-apiserver-master1
# 重启所有apiserver pod
kubectl get pod -n kube-system | grep kube-apiserver | awk '{print "kubectl -n kube-system delete pod " $1}' |bash
Svc常见故障排查
一个service无法对外提供服务的常见问题可能是?
service
和endpoint
之间的label
不匹配
service
的后端映射端口
不匹配
service
后端Pod
状态异常