service介绍
Service 将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。 使用 Kubernetes,你无需修改应用程序即可使用不熟悉的服务发现机制。
Kubernetes 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进 行负载均衡。
Kubernetes Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 — — 通常称为微服务。
Service 所针对的 Pods 集合通常是通过选择算符来确定的。
ClusterIP类型
service的连接对所有的后端 pod 是负载均衡的,至于哪些 pod 被属于哪个服务,通过在定义 服务的时候设置标签选择器
service的创建
apiVersion apps/v1 kind Deployment metadata name test1 spec replicas1 selector matchLabels app test1 template metadata labels app test1 spec containersimage nginx1.7.9 name test portscontainerPort80 resources requests cpu0.1 limits cpu1---apiVersion v1 kind Service metadata name test1 spec portsname myngx-http port2180 targetPort80 selector app test1 type ClusterIP
注意:在不指定type: ClusterIP, 默认创建的是 ClusterIP类型的
使用之前的 yaml 文件创建 pod,模版中设置的标签为 app: test1,所以创建servic的 yaml中也需要指定相同的标签: 首先指定的资源类型为 Service,然后指定了两个端口分别:port 服务提供的端口,targetPort 指定 pod 中进程监听的端口,最后指定标签选择器,相同标签的 pod 被当前服务管理
创建service命令
kubectl apply -f test1.yaml -n test
创建完服务之后,可以发现给 pod分配了 CLUSTER-IP,这是一个内部 ip;
可以使用 kubectl exec 命令远程地在一个已经存在的 pod 容器上执行任何命令;
pod 名称 可以随意指定三个中的任何一个,接收到 crul 命令的 pod,会转发给 Service,由 Service 来 决定将请求交给哪个 pod 处理
如 果 希 望 特 定 客 户 端 产 生 的 所 有 请 求 每 次 都 指 向 同 一 个 pod, 可 以 设 置 服 务 的 sessionAffinity 属性为 ClientIP
- 通过serviceName访问
- CoreDNS解析serviceName,返回clusterIP
- clusterIP根据机器的iptables的配置,转发到指定的Pod
service 服务发现
通过删除和增加 Pod 观看服务发现的作用
kubectl delete svc service-name -n namespace-name
测试service可用性
curl serviceIP/clusterIP:port
headless service(无头service)
有时候 client 想自己来决定使用哪个 Real Server,可以通过查询 DNS 来获取 Real Server 的信息。 Headless Service 的对应的每一个 Endpoints,即每一个 Pod,都会有对应的 DNS 域名;这 样 Pod 之间就可以互相访问
- 通过serviceName访问
- 由于没有clusterIP,也就无法指定转发规则(iptables)和负载均衡
- 因此只能返回所有待转发对象(Pod)的请求方式
- 命名规则:podName.headlessServiceName.namespace.clusterDomainName
常规的service服务和无头服务的区别
● service:一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现
● Headless service 无头服务,不需要cluster-IP,clusterIP为None的service,直接绑定具体的Pod的IP,无头服务经常用于statefulset的有状态部署。
注:server资源默认分配给cluster-IP是为了让客户端能访问。而server还提供了pod之间的相互发现,互相访问资源,他们不需要cluster-IP
无头服务yaml格式: apiVersion v1 kind Service metadata name myweb-service spec selector python myweb type ClusterIP clusterIP None ## 集群IP为None portsport81 targetPort80正常的service的yaml格式: apiVersion v1 kind Service metadata name myweb-service spec selector python myweb portsport81 targetPort80在yaml中,默认不写代表分配集群ClusterIP,声明None无ClusterIP
headless service使用场景
1、无头服务用于服务发现机制的项目或者中间件,如kafka和zookeeper之间进行leader选举,采用的是实例之间的实例IP通讯。
2、既然不需要负载均衡,则就不需要Cluster IP,如果没有Cluster IP则kube-proxy 不会处理它们, 并且kubernetes平台也不会给他创建负载均衡。
同一个service暴露多个端口
apiVersion apps/v1 kind Deployment metadata name test1 spec replicas1 selector matchLabels app test1 template metadata labels app test1 spec containersimage nginx1.7.9 name test portscontainerPort80 resources requests cpu 10m limits cpu 100m ---apiVersion v1 kind Service metadata name test1 spec selector app test1 portsname myngx port2180 targetPort80name myngx1 port3180 targetPort80
这里在 Service 里面配置两个端口都指向同一个目标端口
对容器端口命名
apiVersion apps/v1 kind Deployment metadata name test1 spec replicas1 selector matchLabels app test1 template metadata labels app test1 spec containersimage nginx1.7.9 name test portsname http containerPort80 resources requests cpu 10m limits cpu 100m ---apiVersion v1 kind Service metadata name test1 spec selector app test1 portsname myngx port2180 targetPort http name myngx1 port3180 targetPort http
targetPort 直接使用了名称 http
NodePort类型
创建一个服务并将其类型设置为 NodePort,通过创建 NodePort 服务,可以让 kubernetes 在其所有节点上保留一个端口(所有节点上都使用相同的端口号),然后将传入的连接转发 给 pod;
yaml配置
apiVersion apps/v1 kind Deployment metadata name dp-test-for-ingress spec replicas1 selector matchLabels app test1 template metadata labels app test1 spec containersimage nginx name test portscontainerPort80 resources requests cpu1 limits cpu1---apiVersion v1 kind Service metadata name svc-test-for-ingress spec portsname myngx port2280 targetPort80 selector app test1 type NodePort
查看service状态
╰─# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.20.0.1 <none> 443/TCP 4d11h svc-test-for-ingress NodePort 10.20.221.238 <none> 2280:30041/TCP 14h
端口说明
注意:
2280端口: 是service 的 Port
30041端口:有k8s自动创建分配的NodePort端口
访问方式
在集群外部,nodeport 方式访问
NodeIP: NodePort
NodeIP:宿主机,物理机,虚机的IP
http://192.168.10.201:30041
在集群内部,物理节点上访问
ClusterIP: Port
curl 10.20.221.238:2280
在集群内部,Pod内部访问
serviceName:Port
curl svc-test:2280
在集群内部,Pod地址直接访问
podIP: containerPort
查看pod的IP
╰─# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES curl 1/1 Running 2 3d19h 10.10.0.28 k201 <none> <none> dp-test-for-ingress-5cf548d748-nd7fh 1/1 Running 0 14h 10.10.0.59 k201 <none> <none>
curl 10.10.0.59:80
k8s中三种地址和端口
targetPort
是指具体Pod上端口
targetPort : PodIP - container
port The port on the pod that the service should proxy traffic to.
targetPort 很好理解,targetPort 是 pod 上的端口,从 port 和 nodePort 上,到来 的数据最终经过 kube-proxy 流入到后端 pod 的 targetPort 上进入容器。
Port
是指具体的服务名称和IP
Port : ServiceIP/clusterIp The port that the service is exposed on the service’s cluster ip (virsual ip). Port is the service port which is accessed by others with cluster ip.
即,这里的 port 表示:service 暴露在 cluster ip 上的端口,:port 是 提供给集群内部客户访问 service 的入口。
NodePort
对应的宿主机-物理机或者虚拟机
NodePort : NodeIP
On top of having a cluster-internal IP, expose the service on a port on each node of the cluster (the same port on each node). You'll be able to contact the service on any:nodePortaddress. So nodePort is alse the service port which can be accessed by the node ip by others with external ip.
首先,nodePort 是 kubernetes 提供给集群外部,客户访问 service 入口的一种方 式(另一种方式是 LoadBalancer)
所以,nodePort 是提供给集群外 部客户访问 service 的入口。 考虑到安全因素,这个方法不被推荐。相当于后门。
port、nodePort 区别
总的来说,port 和 nodePort 都是 service 的端口
port暴露给集群内客户访问服务,nodePort暴露给集群外客户访问服务。
从这两个端口到来的数据都需要经过反向代理 kube-proxy 流入后端 pod 的 target Pod,从而到达 pod 上的容器内
LoadBalance类型
相比 NodePort 方式,LoadBalancer 方式拥 有自己独一无二的可公开访问的 IP 地址
LoadBalance 其实是 NodePort 的一种扩展,使得 service可以通过一个专用的负载均衡器来访问:
metaLB 负载均衡器
Kubernetes 没 有 为 裸 机 集 群 提 供 网 络 负 载 平 衡 器 的 实 现 ( svc 类 型 为 loadbalance),Kubernetes 附带的 Network LB 的实现都是调用各种 IaaS 平台(GCP,AWS, Azure 等)的粘合代码。如果未在受支持的 IaaS 平台(GCP,AWS,Azure 等)上运行, 则 LoadBalancers 在创建时将无限期保持 pending 状态
metalb 解决了这种问题,使得裸机集群也能使用 svc 类型为 loadbalancer.
MetaLB 是搭建私有 Kubernet 集群负载均衡的利器,可以提供 Layer 2 mode 和 BGP 模式的 负载均衡。
Layer 2 模式下,每个 Service 会有集群中的一个 Node 来负责。服务的入口流量全部经由 单个节点,然后该节点的 Kube-Proxy 会把流量再转发给服务的 Pods。也就是说,该模式 下 MetalLB 并没有真正提供负载均衡器。尽管如此,MetalLB 提供了故障转移功能,如果 持有 IP 的节点出现故障,则默认 10 秒后即发生故障转移,IP 会被分配给其它健康的节 点
优点: 是它的通用性:它可以在任何以太网网络上运行,不需要特殊的硬件。 缺点: Layer 2 模式下存在单节点瓶颈,服务所有流量都经过一个 Node 节点。这意味着服务的入 口带宽被限制为单个节点的带宽。
metaLB负载均衡器搭建
创建 kubernets 域名空间
kubectl apply -f namespace.yaml
metalb负载均衡器的配置
metallb.yaml配置
apiVersion policy/v1beta1 kind PodSecurityPolicy metadata labels app metallb name controller namespace metallb-system spec allowPrivilegeEscalationfalse allowedCapabilities allowedHostPaths defaultAddCapabilities defaultAllowPrivilegeEscalationfalse fsGroup rangesmax65535 min1 rule MustRunAs hostIPCfalse hostNetworkfalse hostPIDfalse privilegedfalse readOnlyRootFilesystemtrue requiredDropCapabilities ALL runAsUser rangesmax65535 min1 rule MustRunAs seLinux rule RunAsAny supplementalGroups rangesmax65535 min1 rule MustRunAs volumes configMap secret emptyDir ---apiVersion policy/v1beta1 kind PodSecurityPolicy metadata labels app metallb name speaker namespace metallb-system spec allowPrivilegeEscalationfalse allowedCapabilities NET_ADMIN NET_RAW SYS_ADMIN allowedHostPaths defaultAddCapabilities defaultAllowPrivilegeEscalationfalse fsGroup rule RunAsAny hostIPCfalse hostNetworktrue hostPIDfalse hostPortsmax7472 min7472 privilegedtrue readOnlyRootFilesystemtrue requiredDropCapabilities ALL runAsUser rule RunAsAny seLinux rule RunAsAny supplementalGroups rule RunAsAny volumes configMap secret emptyDir ---apiVersion v1 kind ServiceAccount metadata labels app metallb name controller namespace metallb-system ---apiVersion v1 kind ServiceAccount metadata labels app metallb name speaker namespace metallb-system ---apiVersion rbac.authorization.k8s.io/v1 kind ClusterRole metadata labels app metallb name metallb-system controller rulesapiGroups'' resources services verbs get list watch update apiGroups'' resources services/status verbs update apiGroups'' resources events verbs create patch apiGroups policy resourceNames controller resources podsecuritypolicies verbs use ---apiVersion rbac.authorization.k8s.io/v1 kind ClusterRole metadata labels app metallb name metallb-system speaker rulesapiGroups'' resources services endpoints nodes verbs get list watch apiGroups'' resources events verbs create patch apiGroups policy resourceNames speaker resources podsecuritypolicies verbs use ---apiVersion rbac.authorization.k8s.io/v1 kind Role metadata labels app metallb name config-watcher namespace metallb-system rulesapiGroups'' resources configmaps verbs get list watch ---apiVersion rbac.authorization.k8s.io/v1 kind Role metadata labels app metallb name pod-lister namespace metallb-system rulesapiGroups'' resources pods verbs list ---apiVersion rbac.authorization.k8s.io/v1 kind ClusterRoleBinding metadata labels app metallb name metallb-system controller roleRef apiGroup rbac.authorization.k8s.io kind ClusterRole name metallb-system controller subjectskind ServiceAccount name controller namespace metallb-system ---apiVersion rbac.authorization.k8s.io/v1 kind ClusterRoleBinding metadata labels app metallb name metallb-system speaker roleRef apiGroup rbac.authorization.k8s.io kind ClusterRole name metallb-system speaker subjectskind ServiceAccount name speaker namespace metallb-system ---apiVersion rbac.authorization.k8s.io/v1 kind RoleBinding metadata labels app metallb name config-watcher namespace metallb-system roleRef apiGroup rbac.authorization.k8s.io kind Role name config-watcher subjectskind ServiceAccount name controller kind ServiceAccount name speaker ---apiVersion rbac.authorization.k8s.io/v1 kind RoleBinding metadata labels app metallb name pod-lister namespace metallb-system roleRef apiGroup rbac.authorization.k8s.io kind Role name pod-lister subjectskind ServiceAccount name speaker ---apiVersion apps/v1 kind DaemonSet metadata labels app metallb component speaker name speaker namespace metallb-system spec selector matchLabels app metallb component speaker template metadata annotations prometheus.io/port'7472' prometheus.io/scrape'true' labels app metallb component speaker spec containersargs --port=7472 --config=config envname METALLB_NODE_NAME valueFrom fieldRef fieldPath spec.nodeName name METALLB_HOST valueFrom fieldRef fieldPath status.hostIP name METALLB_ML_BIND_ADDR valueFrom fieldRef fieldPath status.podIP # needed when another software is also using memberlist / port 7946#- name: METALLB_ML_BIND_PORT# value: "7946"name METALLB_ML_LABELS value"app=metallb,component=speaker"name METALLB_ML_NAMESPACE valueFrom fieldRef fieldPath metadata.namespace name METALLB_ML_SECRET_KEY valueFrom secretKeyRef name memberlist key secretkey image registry.cn-hangzhou.aliyuncs.com/liuyik8s/speaker v0.9.6 imagePullPolicy IfNotPresent name speaker portscontainerPort7472 name monitoring resources limits cpu 100m memory 100Mi securityContext allowPrivilegeEscalationfalse capabilities add NET_ADMIN NET_RAW SYS_ADMIN drop ALL readOnlyRootFilesystemtrue hostNetworktrue nodeSelector kubernetes.io/os linux serviceAccountName speaker terminationGracePeriodSeconds2 tolerationseffect NoSchedule key node-role.kubernetes.io/master ---apiVersion apps/v1 kind Deployment metadata labels app metallb component controller name controller namespace metallb-system spec revisionHistoryLimit3 selector matchLabels app metallb component controller template metadata annotations prometheus.io/port'7472' prometheus.io/scrape'true' labels app metallb component controller spec containersargs --port=7472 --config=config image registry.cn-hangzhou.aliyuncs.com/liuyik8s/controller v0.9.6 imagePullPolicy IfNotPresent name controller portscontainerPort7472 name monitoring resources limits cpu 100m memory 100Mi securityContext allowPrivilegeEscalationfalse capabilities drop all readOnlyRootFilesystemtrue nodeSelector kubernetes.io/os linux securityContext runAsNonRoottrue runAsUser65534 serviceAccountName controller terminationGracePeriodSeconds0
Layer2模式负载均衡配置
cm.yaml
apiVersion v1 kind ConfigMap metadata namespace metallb-system name config data config address-pools: - name: default protocol: layer2 addresses: - 192.168.56.250-192.168.56.254 # 负载均衡对可分配的节点IP地址的范围定义
注意:
- 范围指定的IP地址:也就是负载均衡器,访问的请求,负载到指定的ip地址的node节点上
- 指定的IP地址的节点,不可以指定metalLB所在节点上的IP地址。
假如:192.168.1.1 , 192.168.1.2 ,192.168.1.3 ,把192.168.1.1作为负载均衡器的节点。192.168.1.2 ,192.168.1.3 作为处理负载均衡之后的节点
安装metallb和layger2的配置
kubectl apply -f metallb.yaml kubectl create -f cm.yaml
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
metallb负载均衡器访问
访问方式:
方式一:
通过使用 NodePort 的方式来访问服务(节点 IP+节点端口);
NodeIP:NodePort
方式二:
同时也 可以通过 EXTERNAL-IP 来访问
External-IP:port
访问方式三:
ClusterIP:port
部署LoadBalance服务
搭建好metallb负载均衡器之后,创建 service
apiVersion apps/v1 kind Deployment metadata name test2 spec replicas1 selector matchLabels app test2 template metadata labels app test2 spec containersimage nginx1.7.9 name test portscontainerPort80 resources requests cpu0.1 limits cpu1---apiVersion v1 kind Service metadata name test2 spec portsname myngx2 port2280 targetPort80 selector app test2 type LoadBanlance
指定type: LoadBanlance
查看service状态信息
10.20.80.114:为clusterIP
192.168.56.252: 为ExteneralIP
2180端口:为Port端口
32187端口: 我们没有指定节点端口,但是创建完之后自动启动了 32187 节点端口 ,其类型为NodePort端口(因为 LoadBanlance类型其实就是NodePort类型的扩展)
使用:ExteneralIP:port 进行外部访问