k8s学习-Service

4.4、Service

可能会用到ipvs,先安装:

yum install -y openssl openssl-devel popt popt-devel libnl-devel kenel-devel
yum install -y ipvsadm

4.4.1、概念

说明

kubernetes的Service(简称svc)定义了一种抽象,一个Pod的逻辑分组,一种可以访问他们的策略,通过Label Selector选择对应的一组Pod。简单来说就是服务发现;

类型

  1. ClusterIp:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP。
  2. NodePort:在ClusterIP的基础上为Service在每太机器上绑定一个端口,这样通过NodePort来访问该服务。
  3. LoadBalance:在NodePort的基础上,借助cloud provider创建一个外部负载均衡器。并将请求转发到NodePort
  4. ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,只有>=kubernetes1.7的版本才支持。

结构图:

代理的分类

1)namespace

频繁的和kubeproxy交互,性能不高。

2)iptables

使用iptables继续转发,提高了性能。

3)ipvs

在该模式下kube-proxy会监视kubernetes的Service对象和Endpoints,调用netlink接口已以响应的创建ipvs规则并定期与Service对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被定重定向到其中一个后端Pod。

与iptables类似,ipvs于netfilter的hook功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着ipvs可以更快的重定向流量,并且在同步代理规则时具有更好的性能。此外ipvs为负载均衡算法做出了更多的选项:

  • rr:轮询调度
  • lc:最小连接
  • dn:目标哈希
  • sh:源哈希
  • sed:最短期望延迟
  • nq:不排队调度

4.4.2、使用

ClusterIp

clusterIp在每个node节点使用iptables,将发向clusterIp对饮端口的数据转发到kube-proxy中,然后kube-proxy自己内部实现由负载均衡的方法,并且可以查询到这个service下对应的pod地址和端口,然后把数据转发给这个pod的地址和端口;

  • apiServer用户通过kubectl命令想apiServer发送创建service的命令,apiserver接收到请求后将数据存储到etcd中
  • kube-proxy kubernetes的每个节点中都有一个kube-proxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入到本地的iptables规则中
  • iptables使用NAT等技术将virtualIP的流量转至endpoint中
测试
mkdir -p /usr/local/docker/kubernetes/plugins/test/service/clusterip
cd /usr/local/docker/kubernetes/plugins/test/service/clusterip

1)创建deployment

vim myapp-deploy.yml

apiVersion: apps/v1
kind: Deployment # 类型为Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3 # 副本数 3
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata: # 必须和上面定义的label匹配
      labels:
        app: myapp
        release: stabel
        env: test
    spec:
      containers:
      - name: myapp
        image: habor-repo.com/library/nginx:v1
        imagePullPolicy: IfNotPresent # 如果本地没有才拉取
        env: # 容器添加环境变量(这里没用,只是有这个功能)
        - name: GET_HOST_FROM
          value: dns
        ports:
        - name: http # 端口的名字定义为 http
          containerPort: 80 # 容器的端口

2)创建service

vim myapp-service.yml

apiVersion: v1
kind: Service # 类型为 Service
metadata:
  name: myapp
  namespace: default
spec:
  type: ClusterIP # service类型为 ClusterIP
  selector: # 这里的labels匹配上面的 matchLabels 用来发现deployment
    app: myapp
    release: stabel
  ports:
  - name: http # 端口的名字定义为 http
    port: 8000 # 暴露的svc外部端口
    targetPort: 80 # 容器内部端口
# 创建 deployment
kubectl apply -f myapp-deploy.yml
kubectl get deploy
kubectl get pod

# 创建 svc
kubectl apply -f myapp-service.yml
kubectl get svc

# 通过 curl 访问 svc 的ip:8000负载均衡访问

HeadlessService

和ClusterIP一样只不过不会暴露service的IP和端口,只能通过域名方式访问:

测试

vim myapp-headless-service.yml

apiVersion: v1
kind: Service # 类型为 Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  clusterIP: "None" # 表示为一个headless服务
  selector: # 这里的labels匹配上面的 matchLabels 用来发现deployment
    app: myapp
    release: stabel
  ports:
  - name: http # 端口的名字定义为 http
    port: 80 # 容器内部端口
    targetPort: 8000 # 暴露的svc外部端口
# 创建 svc
kubectl apply -f myapp-headless-service.yml
# 查看 svc 发现为 None 
[root@k8s-master clusterip]# kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP    2d5h
myapp            ClusterIP   10.101.230.183   <none>        8000/TCP   5m13s
myapp-headless   ClusterIP   None             <none>        80/TCP     5s

# 查看 dns 任意找一个,例如: coredns-bccdc95cf-m4jg5   10.244.0.16
kubectl get pod -n kube-system -o wide

# 通过headless自带的域名解析访问
yum install -y bind-utils
# 使用 dig 命令指定dns域名解析
# service名.命名空间.集群域名(默认svc.cluster.local)
dig -t A myapp-headless.default.svc.cluster.local @10.244.0.16

NodePort

在每个节点上开启一个端口,将该端口的流量导入kube-proxy,然后由kube-proxy进一步给对应的pod

vim nodeport.yml

apiVersion: v1
kind: Service # 类型为 Service
metadata:
  name: myapp-nodeport
  namespace: default
spec:
  type: NodePort # service类型为 NodePort
  selector: # 这里的labels匹配上面的 matchLabels 用来发现deployment
    app: myapp
    release: stabel
  ports:
  - name: http # 端口的名字定义为 http
    port: 9000 # 暴露的svc外部端口
    targetPort: 80 # 容器内部端口
kubectl apply -f nodeport.yml

# 查看 svc
[root@k8s-master clusterip]# kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP          2d5h
myapp            ClusterIP   10.101.230.183   <none>        8000/TCP         34m
myapp-headless   ClusterIP   None             <none>        80/TCP           29m
myapp-nodeport   NodePort    10.106.39.25     <none>        9000:31714/TCP   6s

# 访问
# 9000:31714/TCP 9000 是这个service自己ip的端口,31714是每个节点上暴露的端口
curl 10.106.39.25:9000
curl k8s-master:31714
curl k8s-node1:31714
curl k8s-node2:31714

LoadbBlancer

和nodeport其实是同一种,只不过添加了负载均衡的功能。这个是收费的功能。

ExternalName

将服务映射到externalName字段(可以是域名或者IP)。ExternalName是Service的特例,他没有selector,也没有定义任何的端口和Endpoint。相当于将外部流量导入到内部。

vim external-name.yml

apiVersion: v1
kind: Service # 类型为 Service
metadata:
  name: myapp-external-name
  namespace: default
spec:
  type: ExternalName # service类型为 ExternalName
  externalName: habor-repo.com
kubectl apply -f external-name.yml

# 查看
kubectl get svc

# 查看 dns 任意找一个,例如: coredns-bccdc95cf-m4jg5   10.244.0.16
kubectl get pod -n kube-system -o wide

# 测试域名解析 
dig -t A myapp-external-name.default.svc.cluster.local @10.244.0.16
posted @ 2020-05-31 11:48  bartggg  阅读(242)  评论(0编辑  收藏  举报