service四层代理
kubectl explain service
template:
metadata:
label:
app: xxx
流程:service通过selector找到指定标签的pod(pod通过deployment的template模版创建),从而实现转发请求。已经获取到的pod的ip和端口会存放在endpoint中,需要访问服务时直接通过endpoint查找而非每次都重新查找pod。在删除pod时也是先删除endpoint。
endpoint是防火墙规则,存放pod的IP和端口
service创建的时候有ip,关联的pod的ip和端口都是保存到防火墙规则力的:iptables或者ipvs。service的ip是固定不变的
1、pod ip经常变化,service是pod的代理,我们客户端访问,只需要访问service,就会把请求代理到Pod
2、pod ip在k8s集群之外无法访问,所以需要创建service,这个service可以在k8s集群外访问的。
# type四种类型
kubectl explain service.spec.type
# Defaults to ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
kubectl explain service.spec.ports
FIELDS:
appProtocol <string>
name <string> #定义端口的名字
nodePort <integer> #service在物理机映射的端口,默认在 30000-32767 之间
port <integer> -required- #service的端口,这个是k8s集群内部服务可访问的端口
protocol <string>
targetPort <string> # targetPort是pod上的端口,从port和nodePort上来的流量,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
ClusterIP
# 创建clusterIP类型的service
# 1.创建pod资源
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
# 两个副本是可以相互ping和通信的
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80 #pod中的容器需要暴露的端口
startupProbe:
periodSeconds: 5
initialDelaySeconds: 60
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
livenessProbe:
periodSeconds: 5
initialDelaySeconds: 60
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
readinessProbe:
periodSeconds: 5
initialDelaySeconds: 60
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
# 2.创建service
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
# clusterIP类型,会自动生成一个ip
type: ClusterIP
ports:
- port: 80 #service的端口,暴露给k8s集群内部服务访问
# 四层代理,不支持http,有tcp/udp等
protocol: TCP
targetPort: 80 #pod容器中定义的端口
selector: # key: value 类型
run: my-nginx #选择拥有run=my-nginx标签的pod
# 检查
kubectl get svc
kubectl get ep
ipvsadm -Ln
# 查看详细信息
kubectl describe svc my-nginx
# 服务名.命名空间.域名后缀
SVC_NAME.NS_NAME.DOMAIN.LTD.
# 集群默认的域名后缀是svc.cluster.local.
# 就像我们上面创建的my-nginx这个服务,它的完整名称解析就是
my-nginx.default.svc.cluster.local
## 域名在k8s内部是可以解析的,但是在k8s环境外部没有办法访问和解析
## 外部访问是通过service代理访问,使用endpoint找到对应pod并解析访问
NodePort
# 创建nodeport类型的service
# 1.创建pod资源
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-nodeport
spec:
selector:
matchLabels:
run: my-nginx-nodeport
replicas: 2
template:
metadata:
labels:
run: my-nginx-nodeport
spec:
containers:
- name: my-nginx-nodeport-container
image: nginx
imagePullPolicy: IfNotPresent
# 2.创建nodeport service资源
apiVersion: v1
kind: Service
metadata:
name: my-nginx-nodeport
labels:
run: my-nginx-nodeport
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30380
selector:
run: my-nginx-nodeport
### 数据转发流程
# nodeport会开启一个物理端口,一般是代理在物理机docker0的虚拟网卡上,然后再关联到具体的pod上
客户端请求http://192.168.40.180:30380->docker0虚拟网卡:172.17.0.1:30380->10.244.121.36:80,10.244.102.86:80
ExternalName
应用场景:跨名称空间访问
需求:default名称空间下的client 服务想要访问nginx-ns名称空间下的nginx-svc服务
# 创建externalname类型的service
自定义Endpoints资源
应用场景:在K8S外部(如物理机)使用Endpoint资源
需求:通过k8s的pod资源调用外部sql资源,需要使用自定义的endpoint资源作代理
#1. 创建svc资源
cat > mysql_service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
type: ClusterIP
ports:
- port: 3306
EOF
kubectl apply -f mysql_service.yaml
kubectl get svc | grep mysql
kubectl describe svc mysql # 此时还没有endpoint
#2. 创建endpoint资源
cat > mysql_endpoint.yaml << EOF
apiVersion: v1
kind: Endpoints
metedata:
name: mysql
subsets:
- addresses:
- ip: 192.168.30.182
ports:
- port: 3306
EOF
kubectl apply -f mysql_endpoint.yaml
kubectl describe svc mysql # 此时endpoint会指向定义的外部数据库
service服务发现:crondns
在解析k8s内部的dns域名时,是使用crondns进行域名解析,把域名解析成IP