Kubernetes暴露端口与代理方式

暴露端口的方式

clusterIP
此类型会提供一个集群内部的虚拟IP(与pod不在同一网段),以供集群内部的pod之间通信使用。clusterIP也是kubernetes service的默认类型
主要需要以下几个组件的协同工作
apiservice:在创建service时,apiserver接收到请求以后将数据存储到etcd中。
kube-proxy:k8s的每个节点中都有该进程,负责实现service功能,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables中
iptables:使用NAT等技术奖virtuallp的流量转至endpoint中

NodePort
NodePort模式除了使用cluster ip外,也将service的port映射到每个node的一个指定内部的port上,映射的每个node的内部port都一样。为每个节点暴露一个端口,通过nodeIP+nodeport可以访问你这个服务,同时服务依然会有cluster类型的ip+port。内部通过clusterip方式访问,外部通过nodeport方式访问

loadbalancer
loadbalancer在nodeport基础上,k8s可以请求底层云平台创建一个负载均衡器,将每个node作为后端,进行服务分发,该模式需要底层云平台(例如GCE)支持

lngress
lngress,是一种http方式的路由转发机制由lngress controller和http代理服务器组合而成,lngress controller实例监控kubernetes api,实时更新http代理服务器的转发规则。http代理服务器有GCE load-balancer、haproxy、nginx等开源方案

​ service是一个抽象概念,定义了一个服务的多个pod逻辑合集和访问pod的策略,一般把service称为微服务.举个例子一个a服务运行3个pod,b服务怎么访问a服务的pod,pod的ip都不是持久化的重启之后就会有变化。这时候b服务可以访问跟a服务绑定的service,service信息是固定的提前告诉b就行了,service通过Label Selector跟a服务的pod绑定,无论a的pod如何变化对b来说都是透明的.

代理方式

​ k8s群集中的每个节点都运行一个kube-proxy的组件,kube-proxy其实是一个代理层负责实现service.kube-proxy代理模式有两种:

代理模式:userspace
​ 客户端访问ServiceIP(clusterIP)请求会先从用户空间到内核中的iptables,然后回到用户空间kube-proxy,kube-proxy负责代理工作。具体细节:
​ 每个service都会由kube-proxy在node节点上起一个随机的代理端口,iptables会捕捉clusterIP上的端口(targetPort)流量重定向代理端口,访问代理端口的任何连接都会被代理到service后端的某一个pod,默认情况下对
在这里插入图片描述
代理模式:iptables
​ 客户端访问ServiceIP(clusterIP)请求会由iptables直接重定向到后端,具体细节:每个service都会由kube-proxy生成一组iptables规则,iptables会捕捉clusterIP上的端口(targetPort)流量重定向后端某一个pod,默认对pod的选择是随机的

Kubernetes v1.2之前默认是userspace之后是iptables模式,iptables模式性能和可靠性更好,但是iptables模式依赖健康检查,在没有健康检查的情况下如果一个pod不响应,iptables模式不会切换另一个pod上.
在这里插入图片描述
IPVS 代理模式
在 ipvs 模式下,kube-proxy监视Kubernetes服务(Service)和端点(Endpoints),调用 netlink 接口相应地建立 IPVS 规则, 并按期将 IPVS 规则与 Kubernetes服务(Service)和端点(Endpoints)同步。该控制循环可确保 IPVS 状态与所需状态匹配。访问服务(Service)时,IPVS 将流量定向到后端Pod之一。

IPVS代理模式基于相似于 iptables 模式的 netfilter 挂钩函数,可是使用哈希表做为基础数据结构,而且在内核空间中工做。 这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通讯的延迟要短,而且在同步代理规则时具备更好的性能。与其余代理模式相比,IPVS 模式还支持更高的网络流量吞吐量。

IPVS提供了更多选项来平衡后端Pod的流量。分别是:

rr: round-robin
lc: least connection (smallest number of open connections)
dh: destination hashing
sh: source hashing
sed: shortest expected delay
nq: never queue

注意:要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 以前使 IPVS Linux 在节点上可用。 当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 若是未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
在这里插入图片描述

Service服务类型

  • ClusterIP:默认类型,自动分配一个仅Cluster内部能够访问的虚拟IP
  • NodePort:经过每一个 Node 上的 IP 和静态端口(NodePort)暴露服务。以ClusterIP为基础,NodePort 服务会路由到 ClusterIP 服务。经过请求 :,能够从集群的外部访问一个集群内部的 NodePort 服务。
  • LoadBalancer:使用云提供商的负载均衡器,能够向外部暴露服务。外部的负载均衡器能够路由到 NodePort 服务和 ClusterIP 服务。
  • ExternalName:经过返回 CNAME 和它的值,能够将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。没有任何类型代理被建立。

注意:Service 可以将一个接收 port 映射到任意的 targetPort。默认状况下,targetPort 将被设置为与 port 字段相同的值。

示例

  1. 创建一个deployment副本数3,然后滚动更新镜像版本,并记录这个更新记录,最后再回滚到上一个版本
[root@master ~]# vi test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test01
  name: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test01
  template:
    metadata:
      labels:
        app: test01
    spec:
      containers:
      - image: httpd
        name: test

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

[root@master ~]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
test-d9b87b475-946kv     1/1     Running   0          6m39s
test-d9b87b475-j2lml     1/1     Running   0          6m39s
test-d9b87b475-lqp2b     1/1     Running   0          6m39s

[root@master ~]# kubectl set image deploy/test test=nginx:v0.1
deployment.apps/test image updated

[root@master ~]# kubectl get pod
NAME                    READY   STATUS              RESTARTS   AGE
test-5cfd585974-z958p   1/1     Running             0          6s
test-d9b87b475-946kv    1/1     Running             0          21m
test-d9b87b475-j2lml    1/1     Running             0          21m
test-d9b87b475-lqp2b    1/1     Running             0          21m

[root@master ~]# kubectl get deployment
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
test   3/3     1            3           22m

[root@master ~]# kubectl rollout history deployment test
deployment.apps/test 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

[root@master ~]# kubectl rollout history deployment test --revision=2
deployment.apps/test with revision #2
Pod Template:
  Labels:       app=test01
        pod-template-hash=5cfd585974
  Containers:
   test:
    Image:      nginx:v0.1
    Port:       <none>
    Host Port:  <none>
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

[root@master ~]# kubectl rollout undo deployment test --to-revision=1
deployment.apps/test rolled back
[root@master ~]# kubectl rollout history deployment test
deployment.apps/test 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>
  1. 给一个应用扩容副本数为3
[root@master ~]# kubectl scale deploy/test --replicas=3
deployment.apps/test scaled
[root@master ~]# kubectl get pod
NAME                   READY   STATUS        RESTARTS   AGE
test-d9b87b475-946kv   1/1     Running       0          28m
test-d9b87b475-j2lml   1/1     Running       0          28m
test-d9b87b475-lqp2b   1/1     Running       0          28m
test-c9dcccb69-l6wg5   1/1     Terminating   0          119s
test-c9dcccb69-wqjfk   1/1     Terminating   0          119s
  1. 创建一个pod,其中运行着nginx、redis、memcached 3个容器
[root@master ~]# vi test1.yml
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app: test01
spec:
  containers:
  - image: nginx
    name: nginx
  - image: redis
    name: redis
  - image: memcached
    name: memcached

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

[root@master ~]# kubectl get pod
NAME   READY   STATUS    RESTARTS   AGE
test   3/3     Running   0          2m43s
  1. 给一个pod创建service,并可以通过ClusterlP/NodePort访问
[root@master ~]# vim test2.yml 
---
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app: test01
spec:
  containers:
  - image: nginx
    name: nginx

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: test01
  type: NodePort
  
[root@master kubenetres]# kubectl apply -f test.yml 
pod/test created
service/nginx created
[root@master kubenetres]# kubectl get pod,svc
NAME       READY   STATUS    RESTARTS   AGE
pod/test   1/1     Running   0          16s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/nginx        NodePort    10.103.146.35   <none>        80:31654/TCP   16s

#ClusterIP访问
[root@master kubenetres]# curl 10.103.146.35
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
......略

#NodePort访问
[root@master kubenetres]# curl 192.168.111.151:30416
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
......略
  1. 创建deployment和service,使用busybox容器nslookup解析service
[root@master kubenetres]# kubectl run test1  --image=busybox:1.28.4 -- sleep 24h
pod/test1 created
[root@master kubenetres]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
test    1/1     Running   0          10m

[root@master kubenetres]# kubectl exec -it test1 -- /bin/sh
/ # nslookup kubernetes
Server:    10.96.0.19
Address 1: 10.96.0.19 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local

[root@master kubenetres]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        3d21h

版权声明:本文为bzdmz_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。