service暴露端口的方式与代理方式

service 概念

SVC 通过 Label Selector 标签选择的方式,匹配一组 Pod,对外访问服务。每一个 SVC可以理解成为一个微服务。
在这里插入图片描述
service 能够提供负载均衡的能力,但是在使用上有以下限制:

只提供4层负载均衡能力(只有 RR 轮询算法),而没有7层功能,如果需要更多的匹配规则来转发请求,4层上的负载均衡是不支持的。

service 类型

Clusterip:默认类型,自动分配一个仅 Cluster 内部可以访问的 虚拟IP,一般用作集群内部负载均衡。

NodePort(service向外暴露):在ClusterIP 基础上为 Service 在每台机器上绑定一个映射端口,外网客户端可以通过 NodeIP,Nodeport访问。

LoadBalancer(service向外暴露):在 NodePort 基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到 NodeIP 和 NodePort

ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,只有1.7之后版本的 kube-dns支持。

SVC 访问流程组件

首先 apiserver 监听 kube-proxy 去进行服务和端口的发现。
通过kube-proxy监控,kube-proxy监控所有 Pod 节点信息,标签、IP、port 等,并负责把它们写入到 iptables 规则当中。
client 访问 SVC,其实访问的是 iptables规则。再由 iptables 导向后端 Pod 节点。
ipvs,图片上没有,现在的ClusterIP,NodePort 都是采取 ipvs 调度算法对后端 Pod 节点进行调度访问。

VIP 和 Service 代理

在kubernetes集群中,每个 Node 运行一个 Kube-porxy 进程。kube-proxy负责为 service 实现了一种 VIP (虚拟IP) 的形式,而不是 ExternaName 的形式。

  • 1.0版本,代理完全在 userspace
  • 1.1版本,新增 iptables 代理,但并不是默认的运行模式
  • 1.2版本,默认采用 iptables 代理
  • 1.4版本,默认采用 ipvs 代理

service 是 “4层(TCP/UDP over IP)概念”,在1.1版本 新增了 Ingress API(beat 版),用来表示“7层代理”。

代理模式分类

userspace 代理模式

在这里插入图片描述
client Pod 想要访问 Server Pod

  1. 首先经过 Service IP(iptables),由 iptables转发至kube-proxy,kube-proxy根据访问的地址,端口进行转发,需要 kube-proxy 充当代理功能。
  2. 其次 kube-apiserver 也会去监听 kube-proxy,kube-proxy 是否进行所有 Pod 信息的写入。
  3. 导致 kube-proxy 的工作负载量过大,压力过大。

Iptables 代理模式

在这里插入图片描述
client Pod 访问 Server Pod

所有的请求,代理全部由 iptables 来完成,不再需要 kube-proxy 充当代理角色。 提高了 稳定性和访问效率,压力减少

ipvs 代理模式

ipvs (IP Virtual Server) 实现了传输层负载均衡,也就是我们常说的4层LAN交换,作为 Linux 内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。ipvs可以将基于TCP和UDP的服务请求转发到真实服务器上,并使真实服务器的服务在单个 IP 地址上显示为虚拟服务。

ipvs 对比 iptables
我们知道kube-proxy支持 iptables 和 ipvs 两种模式, 在kubernetes v1.8 中引入了 ipvs 模式,在 v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。iptables 模式在 v1.1 中就添加支持了,从 v1.2 版本开始 iptables 就是 kube-proxy 默认的操作模式,ipvs 和 iptables 都是基于netfilter的,那么 ipvs 模式和 iptables 模式之间有哪些差异呢?

  • ipvs 为大型集群提供了更好的可扩展性和性能
  • ipvs 支持比 iptables 更复杂的复制均衡算法(最小负载、最少连接、加权等等)
  • ipvs 支持服务器健康检查和连接重试等功能

ipvs为负载均衡提供算法:

  • rr:轮询带哦都
  • lc:最小连接数
  • dh:目标地址哈希
  • sh:源地址哈希
  • sed:最短期望延迟
  • nq:不排队调度

注意:ipvs 模式假定在运行 kube-proxy 之前在节点上都已经安装了 IPVS 内核模块。当 kube-proxy 以 ipvs 代理模式启动时,kube-proxy 将验证节点上是否安装了 IPVS 模块,如果未安装,则 kube-proxy 将回退到 iptables 代理模式

在这里插入图片描述
client Pod 访问 Server Pod

  • 首先,service IP 的 iptables代理变成了 ipvs 模块,实现负载均衡和流量导向。
  • client 访问到 IPvs 服务,将流量分发到不同的 Pod 上运行。

kubernetes暴露端口的方式

集群内部实现访问:Clusterip

Clusterip是集群内部的私有ip,在集群内部访问服务非常方便,也是kuberentes集群默认的方式,直接通过service的Clusterip访问,也可以直接通过ServiceName访问。集群外部则是无法访问的。

默认类型,自动分配一个仅Cluster内部能够访问的虚拟IP

[root@master ~]# cat cluster.yml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apache
  template: 
    metadata:
      labels:
        app: apache 
    spec:
      containers:
      - image: bravealove1/apache:v1.0 
        imagePullPolicy: IfNotPresent
        name: apache

---
apiVersion: v1
kind: Service
metadata:
  name: apache
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: apache
  type: ClusterIP  #指定网络模式

[root@master ~]# kubectl  apply -f cluster.yml 
deployment.apps/apache created
service/apache created


[root@master ~]# kubectl  get pods,svc
NAME                          READY   STATUS    RESTARTS   AGE
pod/apache-599bc546b8-xp5rg   1/1     Running   0          12s

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/apache       ClusterIP   10.98.249.14   <none>        80/TCP    12s
service/kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   4d12h


[root@master ~]# curl 10.98.249.14
hello,this is a test page 1 

集群外部方式访问:NodePort

NodePort在kubenretes里是一个早期广泛应用的服务暴露方式。Kubernetes中的service默认情况下都是使用的ClusterIP这种类型,这样的service会产生一个ClusterIP,这个IP只能在集群内部访问,要想让外部能够直接访问service,需要将service type修改为 nodePort。将service监听端口映射到node节点。

nodePort的原理在于在node上开了一个端口,将向该端口的流量导入到kube-proxy,然后由 kube-proxy进一步到给对应的pod

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apache
  template: 
    metadata:
      labels:
        app: apache 
    spec:
      containers:
      - image: wjj200112/apache:v1.0 
        imagePullPolicy: IfNotPresent
        name: apache

---
apiVersion: v1
kind: Service
metadata:
  name: apache
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30000   //指定对外端口
  selector:
    app: apache
  type: NodePort   #指定网络模式


[root@master ~]# kubectl  apply -f nodeport.yml 
deployment.apps/apache created
service/apache created
[root@master ~]# kubectl get pods,svc
NAME                          READY   STATUS    RESTARTS   AGE
pod/apache-599bc546b8-w6xnd   1/1     Running   0          10s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/apache       NodePort    10.96.90.92   <none>        80:30000/TCP   10s
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        4d12h
[root@master ~]# curl 192.168.47.160:30000
hello,this is a test page 1 

LoadBalancer

LoadBlancer Service 是 kubernetes 深度结合云平台的一个组件;当使用 LoadBlancer Service 暴露服务时,实际上是通过向底层云平台申请创建一个负载均衡器来向外暴露服务;目前 LoadBlancer Service 支持的云平台已经相对完善,比如国外的 GCE、DigitalOcean,国内的 阿里云,私有云 Openstack 等等,由于 LoadBlancer Service 深度结合了云平台,所以只能在一些云平台上来使用。

Ingress

Ingress是自kubernetes1.1版本后引入的资源类型。必须要部署Ingress controller才能创建Ingress资源,Ingress controller是以一种插件的形式提供。

DNS解析

Service

  • 创建普通service 会以my-svc.my-namespace.svc.cluster.local 的形式指派一个 DNS A 记录,并解析到该service的Cluster IP。
  • 创建“Headless” Service(没有Cluster IP)也会以 my-svc.my-namespace.svc.cluster.local 的形式被指派一个 DNS A 记录,但是并不会解析到的Cluster IP,而是解析到一组被选中的- - pod 的IP,如果没有backend则不做处理。

Pod

  • 创建Pod 会以 pod-ip-address.my-namespace.pod.cluster.local 这种形式被指派一个 DNS A 记录。

案例
创建一个deployment副本数3,然后滚动更新镜像版本,并记录这个更新记录,最后再回滚到上一个版本

[root@master ~]# vi deploy.yml
[root@master ~]# cat deploy.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
   matchLabels:
     app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80


#参数--record可以记录当前版本的Deployment都执行过哪些命令
[root@master ~]# kubectl create -f deploy.yml  --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/nginx-deployment created


#创建完成后立即执行get命令查看这个Deployment
[root@master ~]# kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           2m14s
[root@master ~]# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-74d589986c-kxcvx   1/1     Running   0          2m11s
nginx-deployment-74d589986c-s277p   1/1     Running   0          2m11s
nginx-deployment-74d589986c-zlf8v   1/1     Running   0          2m11s

#使用 nginx:1.9.1 的镜像来代替原来的 nginx的镜像
[root@master ~]# kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment.apps/nginx-deployment image updated

#查看更新进度
[root@master ~]# kubectl rollout status deployment/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out

#查看镜像信息
[root@master ~]# kubectl describe deployment/nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Fri, 24 Dec 2021 22:24:10 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 4
                        kubernetes.io/change-cause: kubectl create --filename=deploy.yml --record=true
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 4 total | 3 available | 1 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.9.1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>


#使用rollout history命令查看Deployment的版本(revision)
[root@master ~]# kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy.yml --record=true
2         kubectl create --filename=deploy.yml --record=true

#使用rollout undo命令回滚到前一个revision
[root@master ~]# kubectl rollout undo deployment/nginx-deployment
deployment.apps/nginx-deployment rolled back


查看镜像信息
[root@master ~]# kubectl describe deployment/nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Fri, 24 Dec 2021 22:24:10 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 3
                        kubernetes.io/change-cause: kubectl create --filename=deploy.yml --record=true
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>

给一个应用扩容副本数为3

[root@master ~]# kubectl  apply -f cluster.yml 
deployment.apps/apache created

[root@master ~]# kubectl  get pods
NAME                          READY   STATUS    RESTARTS   AGE
pod/apache-599bc546b8-6tctl   1/1     Running   0          28s


[root@master ~]# kubectl scale  deployment apache --replicas 4
deployment.apps/apache scaled
[root@master ~]# kubectl  get pods
NAME                          READY   STATUS              RESTARTS   AGE
pod/apache-599bc546b8-6gx4p   0/1     ContainerCreating   0          2s
pod/apache-599bc546b8-6tctl   1/1     Running             0          2m3s
pod/apache-599bc546b8-8qzr4   0/1     ContainerCreating   0          2s
pod/apache-599bc546b8-j48v5   0/1     ContainerCreating   0          2s

创建一个pod,其中运行着nginx、redis、memcached 3个容器

[root@master ~]# vim pod.yml 
---
apiVersion: v1
kind: Pod
metadata:
  name: hellok8s
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: mynginx
    image: nginx 
    ports:
    - containerPort: 80
  - name: myredis
    image: redis
    ports:
    - containerPort: 6379
  - name: memcached
    image: memcached 

[root@master ~]# kubectl apply -f pod.yml 
pod/hellok8s created


[root@master ~]# kubectl  get pods
NAME       READY   STATUS    RESTARTS   AGE
hellok8s   3/3     Running   0          2m49s

给一个pod创建service,并可以通过ClusterlP/NodePort访问

[root@master ~]# vi nodeport.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apache
  template: 
    metadata:
      labels:
        app: apache 
    spec:
      containers:
      - image: bravealove1/apache:v1.0 
        imagePullPolicy: IfNotPresent
        name: apache

---
apiVersion: v1
kind: Service
metadata:
  name: apache
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30000   //指定对外端口
  selector:
    app: apache
  type: NodePort   #指定网络模式


[root@master ~]# kubectl  apply -f nodeport.yml 
deployment.apps/apache created
service/apache created
[root@master ~]# kubectl get pods,svc
NAME                          READY   STATUS    RESTARTS   AGE
pod/apache-599bc546b8-w6xnd   1/1     Running   0          10s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/apache       NodePort    10.96.90.92   <none>        80:30000/TCP   10s
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        4d12h
[root@master ~]# curl 192.168.47.160:30000
hello,this is a test page 1 

创建deployment和service,使用busybox容器nslookup解析service

# 创建一个pod,service
[root@master ~]# cat host.yml 
---
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: myapp-deploy 
  namespace: default 
spec: 
  replicas: 1
  selector: 
    matchLabels: 
      app: myapp 
  template:
    metadata: 
      labels: 
        app: myapp 
    spec: 
      containers: 
      - name: myapp
        image: httpd
        imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata: 
  name: myapp-externalname
  namespace: default
spec: 
  type: ExternalName 
  externalName: web.test.example.com



# 部署
[root@master ~]# kubectl apply -f host.yml 
deployment.apps/myapp-deploy created
service/apache created
[root@master ~]# kubectl  get pods
NAME                           READY   STATUS    RESTARTS   AGE
myapp-deploy-55bd85c8b-9jgf2   1/1     Running   0          107s

# 查看pods,service状态
[root@master ~]# kubectl  get pods,svc
NAME                               READY   STATUS    RESTARTS   AGE
pod/myapp-deploy-55bd85c8b-9jgf2   1/1     Running   0          18m

NAME                         TYPE           CLUSTER-IP   EXTERNAL-IP            PORT(S)   AGE
service/kubernetes           ClusterIP      10.96.0.1    <none>                 443/TCP   4d14h
service/myapp-externalname   ExternalName   <none>       web.test.example.com   <none>    3m35s


# 辨析一个busybox资源定义文件
[root@master ~]# vibusybox.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: busybox-pod
  name: test-busybox
spec:
  containers:
  - command:
    - sleep
    - "3600"
    image: busybox
    imagePullPolicy: Always
    name: test-busybox

# 部署
[root@master ~]# kubectl apply -f busybox.yaml 
pod/test-busybox created

# 查看pod状态
[root@master ~]# kubectl  get pods,svc
NAME                               READY   STATUS    RESTARTS   AGE
pod/myapp-deploy-55bd85c8b-9jgf2   1/1     Running   0          19m
pod/test-busybox                   1/1     Running   0          8m15s

NAME                         TYPE           CLUSTER-IP   EXTERNAL-IP            PORT(S)   AGE
service/kubernetes           ClusterIP      10.96.0.1    <none>                 443/TCP   4d14h
service/myapp-externalname   ExternalName   <none>       web.test.example.com   <none>    4m49s

# 使用exec -it 与busybox进行交互
[root@master ~]# kubectl exec -it test-busybox /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # nslookup myapp-externalname.default.svc.cluster.local
Server:         10.96.0.10
Address:        10.96.0.10:53

myapp-externalname.default.svc.cluster.local    canonical name = web.test.example.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值