Service简介
在kubernetes中每个Pod都存在生命周期;当一个Pod出现故障,极有可能被Pod控制器销毁并新建一个同类Pod取代(Pod控制器对Pod进行扩容也会新建Pod)。因此每个新建的Pod的都会重新获取IP,因此可以说通过IP获取Pod的服务是不可靠的。
service是一个有固定域名作为访问入口的服务,接受用户的访问请求,通过算法代理至后端的Pods上。Pods创建和销毁都会及时关联至service上。
工作原理简介
各Node节点上的kubelet关注各自节点上的pod,如有变动会及时通知master上的kube-apiserver。
各节点上的kube-proxy又实时监测着kube-apiserver上关于pod的变动,获取变动信息后及时修改本地的iptables(或ipvs),生成新的代理规则。
service依赖的名称解析
CoreDNS(新版本K8S)和kube-dns(老版本K8S)
DNS是一个可选(尽管强烈推荐)集群插件。 DNS 服务器监视着负责创建新 Service 的 Kubernetes API,从而为每一个 Service 创建一组 DNS 记录。 如果整个集群的 DNS 一直被启用,那么所有的 Pod 应该能够自动对 Service 进行名称解析。
例如,有一个名称为 “my-service” 的 Service,它在 Kubernetes 集群中名为 “my-ns” 的 Namespace 中,为 “my-service.my-ns” 创建了一条 DNS 记录。 在名称为 “my-ns” 的 Namespace 中的 Pod 应该能够简单地通过名称查询找到 “my-service”。 在另一个 Namespace 中的 Pod 必须限定名称为 “my-service.my-ns”。 这些名称查询的结果是 Cluster IP
service的三种工作模式
v1.1版本之前使用userspace
v1.10版本之前使用iptables
v1.11版本之后使用ipvs
service的类型
- ClusterIP 仅用于集群内部的访问(默认类型) ,随机生成一个集群内的service网段ip,通过ClusterIP+port代理一组Pod的服务。
- Nodeport 用于向集群外部的访问方式,k8s会为集群中的运行指定Pod的每一个node打开nodePort端口以供外部访问,默认nodePort的范围是30000-32767。node的ip+nodeport代理这一组pod服务。(如果node挂了可能就需要换另一个node的ip)
- LoadBalancer 调用公有云Iaas服务生成一个集群外的负载均衡器,将Nodeport和对应的nodeip添加到负载均衡器中,让访问直接打到node中的pod。
- ExternalName service代理集群外的服务,实现K8S集群中的pod访问集群外的服务
Service应用
Cluster类型的Service
目前k8s集群中已经有一组Pod
新建一个service作为他们的代理(通过label selector)
service的定义清单如下
kind: Service
apiVersion: v1
metadata:
name: ngx-service
spec:
selector:
app: ngx ##选择label为app:ngx的pod建立代理关系
ports:
- protocol: TCP ##代理的协议,可选TCP或者UDP
port: 80 ##service对外服务端口
targetPort: 80 ##Pod上的服务端口
依据清单创建service并观察代理情况
[root@k8s-master k8s-yaml]# kubectl apply -f ngx-service.yaml
service/ngx-service created
[root@k8s-master k8s-yaml]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d
ngx-service ClusterIP 10.105.184.128 <none> 80/TCP 43s
[root@k8s-master k8s-yaml]# curl 10.105.184.128/hostname.html
ngx-deployment-58d847f49c-9tbwh
[root@k8s-master k8s-yaml]# curl 10.105.184.128/hostname.html
ngx-deployment-58d847f49c-vvnrj
docker 镜像事先构建好,提供nginx服务并/hostname.html显示docker主机名。
代理多服务的cluster类型
定义清单如下
kind: Service
apiVersion: v1
metadata:
name: ngx-service
spec:
selector:
app: ngx ##选择label为app:ngx的pod建立代理关系
ports:
- name: http
protocol: TCP ##代理的协议,可选TCP或者UDP
port: 80 ##service对外服务端口
targetPort: 80 ##Pod上的服务端口
- name: https
protocol: TCP ##代理的协议,可选TCP或者UDP
port: 443 ##service对外服务端口
targetPort: 443 ##Pod上的服务端口
NodePort类型的Service
定义清单如下
kind: Service
apiVersion: v1
metadata:
name: ngx-sr-nodeport
spec:
type: NodePort ##虽然为NodePort但仍会为其分配一个ClusterIP
selector:
app: ngx
ports:
- protocol: TCP
port: 80 ##供集群内部使用CluserIP+port访问服务
targetPort: 80 ##Pod上的服务端口
nodePort: 30080 ##供集群外部使用node的IP+nodeport访问服务
依据清单创建service并观察代理情况
`仍会生成clusterIP,也能提供服务`
[root@k8s-master k8s-yaml]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d
ngx-sr-nodeport NodePort 10.106.74.134 <none> 80:30080/TCP 6s
[root@k8s-master k8s-yaml]# curl 10.106.74.134/hostname.html
ngx-deployment-58d847f49c-9tbwh
[root@k8s-master k8s-yaml]# curl 10.106.74.134/hostname.html
ngx-deployment-58d847f49c-vvnrj
`从集群外的主机访问服务`
[root@192-168-80-121 ~]# curl 192.168.80.147:30080/hostname.html
ngx-deployment-58d847f49c-9tbwh
[root@192-168-80-121 ~]# curl 192.168.80.147:30080/hostname.html
ngx-deployment-58d847f49c-vvnrj
[root@192-168-80-121 ~]# curl 192.168.80.147:30080/hostname.html
ngx-deployment-58d847f49c-9tbwh
外部Service
实现访问集群外(或另一个k8s集群或同个集群中的另一个namespace)的服务。需要自建service使用Endpoint,service不需要使用spec.selector。为了将Endpoint和service绑定,需要定义Endpoint的name与service相同。
service清单
kind: Service
apiVersion: v1
metadata:
name: ngx-service
spec:
ports:
- protocol: TCP ##代理的协议,可选TCP或者UDP
port: 80 ##service对外服务端口
targetPort: 80 ##Pod上的服务端口
自建Endpoint清单
kind: Service
apiVersion: v1
metadata:
name: ngx-service
subsets:
- address:
- IP:1.2.3.4
ports:
- port:80
Headless Service
不为Service设置ClusterIP(即clusterIP:none),同个spec.selector将后端的Pod列表直接返回给用户,尤其自行负载调度。
kind: Service
apiVersion: v1
metadata:
name: ngx-service
spec:
selector:
app: ngx ##选择label为app:ngx的pod建立代理关系
clusterIP: None
ports:
- name: http
protocol: TCP ##代理的协议,可选TCP或者UDP
port: 80 ##service对外服务端口
targetPort: 80 ##Pod上的服务端口