service服务

  • 一.前言
  • (1)、service简述
  • (2)、service类型
  • 二、IPVS服务
  • (1)、简介
  • (2)、使用
  • 三、service外部访问方式
  • (1)、NodePort
  • (2)、LoadBalancer
  • (3)、configmap文件设置ip分配
  • (4)、ExternalName


一.前言

(1)、service简述

Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)

(2)、service类型

service的类型:
    ClusterIP:默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问。
    NodePort:将Service通过指定的Node上的端口暴露给外部,访问任意一个  NodeIP:nodePort都将路由到ClusterIP。
    LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 :NodePort,此模式只能在云服务器上使用。
    ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过spec.externlName 设定

二、IPVS服务

(1)、简介

此服务是由每个节点的 kube-proxy 组件,加上 iptables 来共同实现的。kube-proxy 调用物理机中 iptables 的地址转发功能处理service,有一个service就会写入一个 iptables 规则,一旦宿主机有大量的pod,需要写入很多规则,这会消耗大量cpu资源,不理想。如果开启lvs的负载均衡,使用一个虚拟ip,这样会不写入iptables规则了,可以支持更多量级的Pod。

(2)、使用

ipvsadm就是lvs均衡负载的服务支持
1、查看,安装组件
集群中的每个服务器都要查看是否具有ipvsadm模块

lsmod | grep ip_vs   查看是否有此服务
 yum install -y ipvsadm   木有的话可以下载此程序
 touch /etc/sysconfig/ipvsadm  ipvs启动需要手动简历文件
 kubectl -n kube-system get pod | grep proxy               图1、查看组件是否运行
 kubectl -n kube-system get pod -o wide| grep proxy        图1、查看组件是否进行

图1、发现当前集群是通过proxy服务进行的

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡


kube-system命名空间里cm里面存放着系统配置文件

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_02


2、更改名为kube-proxy的cm配置文件

在主节点修改系统配置文件模式为ipvs

[root@server2 pod]  kubectl edit cm kube-proxy -n kube-system

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_03


虽然更改了配置文件,但是发现ipvs的策略并没有启动

k8s 多个pod 负载均衡 k8s service 负载均衡_运维_04

3、更新kube-proxy pod
删除之前的pod会自动重建,重建后的pod会生效刚才修改的配置

kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_05


此时宿主机的ipvs策略已经生效已经具备了均衡调度的功能

k8s 多个pod 负载均衡 k8s service 负载均衡_kubernetes_06

4、开启控制副本,启动容器,并基于svc服务

[root@server2 pod] mkdir ipvs
[root@server2 pod] cd ipvs/
[root@server2 ipvs] kubectl  apply  -f deployment.yml		     %开启pod
[root@server2 ipvs] kubectl  apply  -f svc.yml 			            %分配虚拟ip分配

[root@server2 ipvs] cat deployment.yml 
//
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: myapp:v2
/



[root@server2  ipvsl] cat mysvc.yaml 
//
apiVersion: v1
kind: Service
metadata:
  name: mysvc                                                         此svc的名称叫mysvc
spec:
  ports:
  - protocol: TCP
    port: 80                                                          暴露80端口
    targetPort: 80                                                    暴露80端口
  selector:
    app: nginx                                                        选择标签为nginx的容器开启svc服务,暴露外部访问端口
//

5、查看虚拟ip的信息

[root@server2 ipvs] kubectl describe svc mysvc         图1、查看到svc服务
[root@server2 ipvs] ipvsadm -ln                        图2、查看ipvs服务
[root@server2 ipvs] ip a                               图1、查看网卡

图1、可以发现开启了虚拟vip,还有暴露出了容器的80端口

k8s 多个pod 负载均衡 k8s service 负载均衡_kubernetes_07


图2、可以发现lvs服务也用这个调度策略

k8s 多个pod 负载均衡 k8s service 负载均衡_运维_08

图3、查看网络设置可以发现在宿主机上添加了一个虚拟网卡:kube-ipvs0,并且找到了刚才分配的svc服务的虚拟ip

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_09


6、对暴露端口的虚拟vip进行访问测试

结果发现实现了容器的均衡负载

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_10

三、service外部访问方式

(1)、NodePort

NodePort:将Service通过指定的Node上的端口暴露给外部,访问任意一个NodeIP: nodePort都将路由到ClusterIP
1、新建svc文件,设置nodeport节点
上个实验的deployment控制器仍然运行

[root@server2 ipvs]# kubectl delete -f mysvc.yaml      
[root@server2 ipvs] kubectl apply -f svc.yaml 


[root@server2 pod] cat  svc.yaml
//
apiVersion: v1
kind: Service
metadata:
  name: svc                                    名字改为svc
spec:
  ports:
  - nodePort: 30175                        设置端口为30175
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: None                   在此修改访问类型为NodePort 
  type: NodePort

2、编译svc的配置文件,发现svc文件已经修改类型为NodePort

[root@server2  ipvs] kubectl edit svc svc

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_11

3、查看svc的信息
可以看到mysvc的外部访问端口是NodePort类型,将主机的30175映射到svc服务的80端口

[root@server2 control] kubectl get svc                           图1
[root@server2 control] netstat -antlp | grep 30175               图1

图1、发现开启了pod的虚拟ip,也开启了本地的30175端口。

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_12


4、访问测试

访问任意一个节点IP+节点端口都将路由到ClusterIP,可以实现外部的访问。并且访问方式是均衡负载的。

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_13


5、新建一个容器,进入查看解析

发现自动对svc进行了DNS解析

k8s 多个pod 负载均衡 k8s service 负载均衡_运维_14

6、查看svc的dns解析信息

发现此svc虚拟ip与上图的虚拟ip相同

k8s 多个pod 负载均衡 k8s service 负载均衡_nginx_15


可以查看kube-dns这个服务的后端就是两个core-dns,作地址解析的

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_16

(2)、LoadBalancer

从外部访问 Service 的第二种方式,适用于公有云上Kubernetes 服务。这时候,你可以指定一个 LoadBalancer 类型的 Service。

负载均衡由service提供
公有云提供ip分配

在service提交后,Kubernetes就会调用 CloudProvider 在公有云上为你创建一个负载均衡服务,并且把被代理的 Pod 的 IP地址配置给负载均衡服务做后端。

1、更改配置文件
修改系统的配置文件,开启云端调度服务

[root@server2 control] kubectl edit configmap -n kube-system kube-proxy
[root@server2 control] kubectl get pod -n kube-system |grep kube-proxy |awk '{system("kubectl delete pod "$1" -n kube-system")}'    修改后刷新生效

k8s 多个pod 负载均衡 k8s service 负载均衡_nginx_17


2、上传镜像至harbor,部署metallb服务

获取镜像文件,和一个yaml文件

wget https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml
wget https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml

k8s 多个pod 负载均衡 k8s service 负载均衡_运维_18


3、更改获取的metallb.yaml文件

搜索image,将文中多处的image更换为下图的镜像

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_19

[root@server1 metallb] kubectl  apply  -f metallb.yaml

4、查看情况服务

[root@server2 metallb] kubectl get ns                               图1
[root@server2 metallb] kubectl -n metallb-system get all            图2

图1

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_20


图2、云端控制的pod

k8s 多个pod 负载均衡 k8s service 负载均衡_负载均衡_21

(3)、configmap文件设置ip分配

ConfigMap是一种API对象,用来将非加密数据保存到键值对中。可以用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap可以将环境变量配置信息和容器镜像解耦,便于应用配置的修改。如果需要存储加密信息时可以使用Secret对象。

1、编写应用configmap.yaml文件

[root@server2 metallb] vim configmap.yaml


//
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 172.25.42.10-172.25.42.20              设置ip分配范围
//

[root@server2 metallb] kubectl apply -f configmap.yaml

2、编写、应用svc文件
这里取名叫lb-svc.yaml

[root@server2 metallb] cat lb-svc.yaml 


apiVersion: v1
kind: Service
metadata:
  name: lb-svc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer                       方式为负载均衡
//

[root@server2 metallb]# kubectl apply -f lb-svc.yaml

3、查看信息

此策略已生效

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_22


此时分配的外部端口为172.25.42.11

k8s 多个pod 负载均衡 k8s service 负载均衡_kubernetes_23


4、访问测试,发现负载均衡,实现了云服务调度

[root@server1 metallb] kubectl  apply  -f lb-svr.yml 
service/lb-svc created
[root@server1 metallb] curl 172.25.3.11
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@server1 metallb] curl 172.25.3.11/hostname.html
nginx-deployment-6456d7c676-ldq7x
[root@server1 metallb] curl 172.25.3.11/hostname.html
nginx-deployment-6456d7c676-rlhkv
[root@server1 metallb] curl 172.25.3.11/hostname.html
nginx-deployment-6456d7c676-7zhl5

在service提交后,Kubernetes就会调用 CloudProvider 在公有云上为你创建一个负载均衡服务,并且把被代理的 Pod 的 IP地址配置给负载均衡服务做后端。

(4)、ExternalName

从外部访问的第三种方式叫做ExternalName
ExternalName Service是k8s中一个特殊的service类型,它不需要指定selector去选择哪些pods实例提供服务,而是使用DNS CNAME机制把自己CNAME到你指定的另外一个域名上,可以提供集群内的名字,也可以指定外部真实域名。
将集群的虚拟ip转换为另一个域名,并且给这个域名一个ip,使得外部可以通过访问这个ip访问到集群的容器。
1、简历hostyml文件
指定暴露给外部的域名

[root@server1 ipvs] kubectl  apply  -f host.yml 
[root@server1 upvs] cat host.yml 

/
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ExternalName
  externalName: test.westos.org               指定外部的域名为test.westos.org
///

k8s 多个pod 负载均衡 k8s service 负载均衡_kubernetes_24


2、查看解析过程

进入容器查看到当前的DNS解析地址

k8s 多个pod 负载均衡 k8s service 负载均衡_运维_25


通过dig命令查看一下解析过程

当查找服务时,群集DNS服务返回 CNAME 记录,其值为 www.westos.org。 访问 my-service 的方式与其他服务的方式相同,但主要区别在于重定向发生在 DNS 级别,而不是通过代理或转发。

发现其进行了地址转换,将其服务的地址转换为test.westos.org

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_26

3、设置外部访问端口
service允许为其分配一个公有IP,注意 k8s的externalIPs只是提供了给了一个外部访问的ip,但如果没有pod开放对应接口是无法获取到内容的,因此需要与实际pod相对应。

vim ex-service.yaml 


apiVersion: v1
kind: Service
metadata:
  name: ex-service
spec:
  selector:
    app: nginx
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  externalIPs:
  - 172.25.42.100

4、外部访问

首先在宿主机上能够能查看到外部的虚拟ip

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_27


在真机上可以实现对外部对集群内容器的均衡访问

k8s 多个pod 负载均衡 k8s service 负载均衡_k8s 多个pod 负载均衡_28