博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
kubernetes之service深入(四)
阅读量:5884 次
发布时间:2019-06-19

本文共 17024 字,大约阅读时间需要 56 分钟。

前言

  在谈kubernetes的service之前,小编向带大家复习一下负载均衡的概念,那么何为负载均衡呢,小编举一个简单的例子,能力相同的两个人同时进入一家公司,一个人天天加班到深夜,另一个人则天天优哉游哉到点下班,但两个人的工资一样,此时那个埋头苦干的人就会抱怨了,凭什么我天天累死累活,这不公平!相对于机器而言也是一样的,一台机器一直干活,另一台机器一直空闲,总有一台干活的机器会罢工的!那么如何解决这个问题呢?小编这里举一个web集群的例子:

kubernetes之service深入(四)
  客户端访问一个虚拟的IP,通过这个虚拟的IP将请求发送给nginx的负载(主),此时主负载将接受的请求抛给后端的web服务做真正的处理,这里的负载可以是轮询也可以是根据集群的资源,指定发送到某台web服务器上。那有些读者就想问了,如何设置这个虚拟的IP,又怎么知道负载什么时候会宕机,负载又如何发现后端的web服务器的,如何获取集群资源,精确计算出哪一台web服务比较空闲等等,这一些列的问题,不要着急,小编接下来根据kubernetes的service将这其中的原理一一道来。
希望一篇文章就能写完,此时绝不说废话了,拜托拜托。

(1) service的定义和基本使用

  service是kubernetes最核心的概念,通过创建service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载发送到后端的各个容器应用上。

1) service的定义

apiVersion: v1 kind: Servicemetadata:  #元数据  name: string  #service的名称  namespace: string #service所属的命名空间  labels: #service的标签    - name: string  annotations: #service的注解    - name: string spec:  selector: []  #label选择器,将选择具有指定label标签的pod作为管理范围  type: string  #Service的类型 [clusterIP|NodePort|LoadBalancer]  clusterIP: string #虚拟服务IP地址  sessionAffinity: string #是否支持session [ClientIP|None] 表示将同一个客户端的访问请求都转发到同一个后端  ports: #service需要暴露的端口  - name: string #端口名称,区分不同的应用的端口    protocol: string #使用的协议    prot: int  #service监听的端口    targetPort: int #发送到后端的应用的端口    nodePort: int #当spec.type=NodePort时,指定映射到物理机的端口  status:  #当spec.type=LoadBalancer时,设置外部负载均衡器的地址    loadBalancer:      ingress:        ip: string  #外部负载的IP        hostname: string  #外部负载均衡的主机名

2) service的基本使用

这小编以三个案例介绍:

  • 入门案例(RC+service)
  • 多端口service
  • 外部服务service
    ① 简单案例(RC+service)

#webapp-rc.yaml

apiVersion: v1kind: ReplicationControllermetadata:  name: webappspec:  replicas: 2  template:    metadata:      name: webapp      labels:        app: webapp    spec:      containers:      - name: webapp        image: docker.io/tomcat        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080

[root@zy yaml_file]# kubectl create -f webapp-rc.yaml #创建

kubernetes之service深入(四)

[root@zy yaml_file]# kubectl get pods -l app=webapp -o yaml|grep podIP #查看pod的IP

[root@zy yaml_file]# curl 172.17.0.5:8080 #访问
kubernetes之service深入(四)

#创建service管理pod[root@zy yaml_file]# kubectl expose rc webapp

或者 yaml文件

#webapp-svc.yaml

apiVersion: v1kind: Servicemetadata:  name: webappspec:  ports:  - port: 8081    targetPort: 8080  selector:    app: webapp
[root@zy yaml_file]# kubectl get svc  #查看创建的service的IP

kubernetes之service深入(四)

[root@zy yaml_file]# curl  10.254.90.131:8081 #通过serviceIP访问pod中的应用

kubernetes之service深入(四)

② 多端口service
有时候一个容器应用也可能提供多个端口的服务,那么在service的定义中也可以相应地设置为将多个端口对应到多个应用中,有点类似于Apache的虚拟主机中的基于端口配置。

apiVersion: v1kind: Servicemetadata:  name: webappspec:  ports:  - port: 8081    targetPort: 8080    name: web  - port: 8005    targetPort: 8005    name: management  selector:    app: webapp

③ 外部服务service

在某些环境中,应用系统需要将一个外部数据库作为后端服务进行连接,或将另一个集群或者namespace中的服务作为服务的后端,这时可以通过创建一个无label selector的service来实现:

apiVersion: v1kind: Servicemetadata:  name: my-servicespec:  ports:  - protocol: TCP    port: 33060    targetPort: 3306

因为定义一个没有selector的service,系统不会自动创建endpoint,需要手动定义,创建一个与service同名的endpoint,用于指向实际后端访问地址。

#endpoint

kind: EndPointsapiVersion: v1metadata:  name: my-service  #与service相同subsets:- addresses:  - IP: xxx.xxx.xxx.xxx  ports:  - port: 3306

此时:

kubernetes之service深入(四)
这个service绑定的EndPoint就会连接外部的172.0.1.16:3306的服务,内部访问这个service时,路由就会转发到cluster B 的相应的服务中。
  通过上面的三个案例是不是对service有了初步的了解呢,小编在这里给大家总结一下,service的好处:
  由于pod被RC或者deploy管理,pod重启之后,pod的IP地址是改变的,如果使用podIP去访问后端的应用,每次都要查IP,但是有了service,service的虚拟IP是固定的,我们只要访问service的IP,至于service如何发现后端的重启的Pod,我们不需要关系
  Service的负载作用,如果一个service管理多个pod,而这多个pod提供的是相同的服务,那么service自身也实现了负载:
   RoundRobin(轮询):将请求发送到后端的各个pod上
   SessionAffinity:基于客户端IP地址进行会话,如果SessionAffinity=ClientIP时,同一个客户端发送请求,会被转发到后端相同的pod中。

(2) Headless Service

  在某些场景中,我们希望自己控制负载均衡的策略,不使用service提供的默认的负载,或者应用程序希望知道属于同组服务的其他实例。Kubernetes提供了Headless Service来实现这个功能,即不为service设置clusterIP,仅通过label selector将后端的pod列表返回给调用的客户端:

apiVersion: v1kind: Servicemetadata:  labels:    name: cassandra  name: cassandraspec:  ports:- port: 9042  ClusterIP: None  selector:    name: cassandra

  这样service就不在具有一个特定的clusterIP,对其进行访问将获得包含label“name: cassandra”的全部pod列表,然后客户端程序自行决定如何处理这个pod列表。

  对于去中心化类的应用集群,headless Service将非常有用。接下来我们通过搭建一个Cassandra集群来看看headless Service巧妙的使用,自动实现应用集群的创建。
  通过对headless Service的使用,实现了Cassandra各节点之间的相互查找和集群的自动搭建。
开始搭建:
#单个pod Cassandra节点: Cassandra-pod.yaml

apiVersion: v1kind: Podmetadata:  labels:    name: cassandra  name: cassandraspec:  containers:  - args:    - /run.sh    resources:      limits:        cpu: "0.5"    image: docker.io/shenshouer/cassandra:v5    imagePullPolicy: IfNotPresent    name: cassandra    ports:    - name: cql      containerPort: 9042    - name: thrift      containerPort: 9160    volumeMounts:    - name: data      mountPath: /cassandra_data    env:    - name: MAX_HEAP_SIZE      value: 512M    - name: HEAP_NEWSIZE      value: 100M    - name: POD_NAMESPACE      valueFrom:        fieldRef:          fieldPath: metadata.namespace  volumes:    - name: data

#cassandra-svc.yaml

apiVersion: v1kind: Servicemetadata:  labels:    name: cassandra  name: cassandraspec:  ports:    - port: 9042  selector:    name: cassandra

#cassandra-rc.yaml

apiVersion: v1kind: ReplicationControllermetadata:  labels:    name: cassandra  name: cassandraspec:  replicas: 1  selector:    name: cassandra  template:    metadata:      labels:        name: cassandra    spec:      containers:        - command:            - /run.sh          resources:            limits:              cpu: 0.5          env:            - name: MAX_HEAP_SIZE              value: 512M            - name: HEAP_NEWSIZE              value: 100M            - name: POD_NAMESPACE              valueFrom:                fieldRef:                  fieldPath: metadata.namespace          image: docker.io/shenshouer/cassandra:v5          imagePullPolicy: IfNotPresent          name: cassandra          ports:            - containerPort: 9042              name: cql            - containerPort: 9160              name: thrift          volumeMounts:            - mountPath: /cassandra_data              name: data      volumes:        - name: data          emptyDir: {}
#依次执行一下命令[root@zy yaml_file]# kubectl  create  -f cassandra-pod.yaml[root@zy yaml_file]# kubectl  create  -f cassandra-svc.yaml[root@zy yaml_file]# kubectl  create  -f cassandra-rc.yaml

#此时我们查看pod

kubernetes之service深入(四)

[root@zy yaml_file]# kubectl get rc #查看RC

kubernetes之service深入(四)

[root@zy yaml_file]# kubectl scale rc cassandra --replicas=2 #副本扩容到2个

kubernetes之service深入(四)

[root@zy yaml_file]# kubectl exec -ti cassandra -- nodetool status #查看Cassandra Pod中运行nodetool

kubernetes之service深入(四)

看见以上的页面,表示扩容的pod已经成功加入到Cassandra集群中。
原理解释:因为service是headless Service,他会返回selector中的所有的pod,一开始集群中只有一个pod,所以返回一个,让集群中的pod变成多个时,他会将所有的pod都返回,那么Cassandra是如何处理这新的pod呢?Cassandra镜像它还给Cassandra添加一个定制的SeedProvider,在Cassandra中, SeedProvider设置一个gossip协议用来发现其它Cassandra节点。KubernetesSeedProvider使用内置的Kubernetes发现服务找到KubernetesAPI服务器,然后利用Kubernetes API发现新的节点。就这样headless Service将selector选择中的所有的endpoint,都发送给Cassandra集群,Cassandra集群根据SeedProvider,利用内置的Kubernetes发现服务找到KubernetesAPI服务器,然后利用Kubernetes API发现新的节点,并加入到集群。
kubernetes之service深入(四)
参考文档:

(3) 集群外部访问pod或者service

   由于pod和service是kubernetes集群范围内的虚拟的概念,所有集群外部的客户端无法访通过Pod的IP或者service的IP去访问到它们。为了让外部的客户端可以访问这些服务,kubernetes提供了将Pod或者service的端口号映射到物理机上,以使得客户端访问宿主机的端口从而访问到其容器中的服务。

案例1(①通过设置容器基本的hostPort,将容器应用的端口映射到物理机上)
#pod-hostport.yaml

apiVersion: v1kind: Podmetadata:  name: webapp  labels:    app: webappspec:  containers:  - name: webapp    image: docker.io/tomcat    imagePullPolicy: IfNotPresent    ports:    - containerPort: 8080      hostPort: 8070
#创建之后,访问宿主机的8070端口[root@zy yaml_file]# curl 192.168.130.130:8070

kubernetes之service深入(四)

访问浏览器:
kubernetes之service深入(四)
案例2:(使用spec.hostNetWork参数定义)
   通过设置pod级别的hostNetWork=true,该Pod中所有容器的端口号都将被直接映射到物理机上,但是需要注意的是,在容器的ports定义中,如果不指定hostPort,则默认为containerPort,如果指定了hostPort,则hostPort必须等于containerPort的值。

apiVersion: v1kind: Podmetadata:  name: webapp  labels:    app: webappspec:  hostNetwork: true  containers:  - name: webapp    image: docker.io/tomcat    imagePullPolicy: IfNotPresent    ports:    - containerPort: 8080

案例3(将service的端口号映射到物理机中)

#webapp-nodePort-svc.yaml

apiVersion: v1kind: Servicemetadata:  name: webappspec:  type: NodePort  ports:  - port: 8080    targetPort: 8080    nodePort: 30000  selector:    app: webapp

该service将监听8080端口,并发送到后端selector选择的endpoint的8080端口,对宿主机暴露的端口为30000

[root@zy yaml_file]# curl 192.168.130.130:30000 #访问

kubernetes之service深入(四)

案例4
通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址,LoadBalancer在NodePort基础上,K8S可以请求底层云平台创建一个负载均衡器,将每个Node作为后端,进行服务分发。该模式需要底层云平台(例如GCE)支持。
小编这里以一个yaml为例:

apiVersion: v1kind: Servicemetadata:  name: my-servicespec:  selector:    app: MyApp  ports:  - protocol: TCP    port: 80    targetPort: 9376    nodePort: 30061  clusterIP: 10.0.171.12  loadBalancerIP: 78.11.42.19  type: loadBalancerstatus:  loadBalancer:    ingress:    - ip: 146.147.12.155  #这个是云服务商提供的负载IP

(4) DNS服务搭建

  这里大家要注意了,这一节非常的重要,希望大家一定细细阅读,以后在分析kubernetes核心时这一节是重中之重的基础。

  Kubernetes的服务发现一共有两种方式,1.通过环境变量的方式,2.通过集群范围内的DNS来完成服务名到clusterIP的解析。这里小编带大家了解一下如何搭建DNS服务。

1) kubernetes DNS服务的总体架构介绍

  Kubernetes提供的虚拟DNS服务名为ksydns,由4个组件组成:

    etcd:DNS存储
    kube2sky:将kubernetes master中的service注册到etcd
    skyDNS:提供DNS域名解析服务
    healthz:提供skydns服务的健康检查功能
kubernetes之service深入(四)

2) DNS服务搭建

① 编写配置文件

② 修改每台node上的kubelet启动参数
③ 创建相应的资源对象
④ 测试
这里小编就不一一介绍了,给出搭建的地址:

3) DNS服务的工作原理

  Kube2sky容器因供应用通过kubernetes master的API获取集群所有的service信息,并持续监控新service的生成,然后写入etcd中:

通过命令查看etcd中存储的service信息:

[root@zy ~]#kubectl exec kube-dns-v2-dc1s -c etcd --namespace=kube-system etcdctl ls /skydns/local/cluster/

此时看见目录结果如下:

/skydns/local/cluster/default
/skydns/local/cluster/kube-system
/skydns/local/cluster/svc
可以看见在skydns下是我们配置的cluster.local(域名后缀),之后是命名空间,svc下也通过命名空间生成子目录。
然后查看具体的内容:

[root@zy ~]# kubectl exec kube-dns-v2-dc1s -c etcd --namespace=kube-system etcdctl get /skydns/local/cluster/default/服务名  #这样就能看见相应的clusterIP和域名映射

  然后根据kubectl启动参数的设置(--cluster_dns),kubelet 会在每一个新创建的pod中设置DNS域名解析,配置文件为:/etc/resolv.conf文件,会在其中加入一条,nameserver和search配置:

nameserver DNS解析服务IPsearch default.svc.cluster.local svc.cluster.local cluster.local localdomain

  有了这些配置,应用程序就能够想访问网站域名一样,通过服务的名称访问到服务。总的来说就是,kube2sky 通过kubernetes master的API 将新增的service持续存储到etcd中,每一个新增的pod都会有一个/etc/resolv.conf文件,我们在通过服务名称访问服务时,通过skyDNS 查询etcd,获取服务的IP,然后通过服务的IP就能直接访问到服务后端的endpoint中的容器中的应用。

(5) 自定义DNS和上游DNS服务

  从kubernetes1.6开始,用户可以在kubernetes集群内部配置私有的DNS区域和外部的上游域名服务,在kubernetes的pod定义中支持两个DNS策略,Default和ClusterFirst,dnsPolicy默认是ClusterFirst,如果是Default,域名解析配置则完全从Pod的节点的/etc/resolv.conf中继承下来。

  如果dnsPolicy设置的是ClusterFirst,则DNS查询会被发送到kube-dns(skydns)服务。kube-dns服务负责以集群域名为后缀(例cluster.local)进行服务的域名解析。
  那么自定义的DNS和上游DNS又是啥呢?
kubernetes之service深入(四)
  由上图所示,当dnsPolicy设置为ClusterFirst时,DNS首先会被发送到kube-dns的缓存层,从这里检查域名的后缀,如果是cluster.local,则被发送到kube-dns服务,如果是自定义的*.out.of.kubernetes,则被发送到自定义解析器,如果两者均不符合,则被发送到上游的DNS中进行解析。
域名解析顺序:kube-dns ------ > 自定义DNS -------- > 上游DNS
自定义DNS方式:
  从kubernetes1.6开始,集群管理者可以使用configMap指定自定义的存根域和上游的DNS Server。
① 安装dnsmasq作为自定义的DNS服务

#安装[root@zy ~]# yum install -y dnsmasq#生成一个自定义的DNS记录文件 /tmp/hosts[root@zy ~]# echo "192.168.130.131 server.out-of.kubernetes" > /tmp/hosts#启动DNS服务[root@zy ~]# dnsmasq -q -d -h -q -R -H /tmp/hosts#参数解释:-d:以debug模式启动,在前台运行,便于观察日志-q:输出查询记录-h:不使用/etc/hosts-R:不使用/etc/resolve.conf-H:使用自定义的文件作为DNS记录

kubernetes之service深入(四)

② 创建自定义DNS的configMap
#dns-configmap.yaml

apiVersion: v1kind: ConfigMapmetadata:  name: kube-dns  namespace: kube-systemdata:  stubDomains: |    {"out-of.kubernetes" : ["192.168.130.130"] }  #自定义DNS服务器地址  upstreamNameservers: |  #上游DNS地址    ["8.8.8.8","8.8.4.4"]注意:stubDomains:表示存根域名,自定义DNS就在这里配置,Key是DNS后缀,value是一组DNS服务IPupstreamNameservers:表示上游DNS配置,如果指定了,那么从节点/etc/resovl.conf就会被覆盖。最多指定3个IP。
[root@zy ~]# kubectl create -f dns-configmap.yaml

③ 测试

apiVersion: v1kind: Podmetadata:  name: testerspec:  dnsPolicy: ClusterFirst  containers:  - name: busybox    image: docker.io/busybox    imagePullPolicy: IfNotPresent    command: ["sleep"]    args: ["3600"]

创建一个pod,然后进入其中

[root@zy yaml_file]# kubectl exec -it tester – sh/ # ping server.out-of.kubernetes

此时就会在dnsmasq的输出日志中,看见,server.out-of.kubernetes被转发到自定义DNS服务:192.168.130.130,然后通过DNS服务器,根据/tmp/hosts域名和IP的映射找到192.168.130.131。

(6) Ingress:HTTP 7层路由机制

1) Ingerss原理:

Ingerss产生的原因:我们知道pod被deployment/RC管理的时候,pod重启之后其IP可能会改变,为了能准确的访问到pod中的服务,kubernetes使用service,而service会在宿主机上提供一个端口用于客户端访问,但是如果service很多的话其维护成本就会很高。如果可以借助于nginx的类似于虚拟主机的方式,通过不同的URL能够访问到后端的不同service,那么就少了service对宿主机的大量的端口映射,如何能做到这样呢?kubernetes1.1开始,新增了一个Ingress的资源对象,用于解决上述问题。

Ingerss介绍:Ingress 包含两大组件:Ingress Controller 和 Ingress。
原理图:
kubernetes之service深入(四)
Ingress Controller作用:由于我们是使用nginx的方式实现,那么每一次有新的service或者新的Ingress规则时,就要修改一次nginx.conf文件,这样实在太麻烦,所以Ingress Controller 就是专门解决这个问题,通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下。
Ingress Controller-service:为了让Ingress Controller可以对外提供服务,这里需要一个service,而service监听的端口就是80(http)|443(https)上图所示,该service映射到物理机的端口是30080和30443。
通过Ingress访问后端应用服务的过程(以web服务为例):首先定义一个deployment维持三个web服务的副本,然后给其web服务定义一个名为myapp的service,此时编写Ingress的规则通过host:myapp.zzy.com,并绑定了名为myapp的service,即当客户端访问myapp.zzy.com:30080时,会被转发到Ingress Controller-service的80端口上,根据Ingress Controller更新的Ingress规则,会将请求转发到
myapp:80,然后就能直接访问后端的pod中的容器,最后容器将请求响应会客户端。
注意:Ingress Controller将基于Ingress规则将客户端请求直接转发到service对应的后端的endpoint。

2) Ingress的定义策略:

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: mywebsite-ingressspec:  rules:  - host: mywebsite.com    http:      paths:      - path: /demo        backend:          serviceName: webapp          servicePort: 8080

rules:用于定义当前Ingress资源的转发规则列表;由rules定义规则,或没有匹配到规则时,所有的流量会转发到由backend定义的默认后端。

backend:默认的后端用于服务那些没有匹配到任何规则的请求;定义Ingress资源时,必须要定义backend或rules两者之一,该字段用于让负载均衡器指定一个全局默认的后端。backend对象的定义由2个必要的字段组成:serviceNameservicePort,分别用于指定流量转发的后端目标Service资源名称和端口。
host:包含 于 使用 的 TLS 证书 之内 的 主机 名称 字符串 列表

3) Ingress的部署:

部署步骤

  • 安装部署ingress controller Pod
  • 部署后端服务
  • 部署ingress-nginx service
  • 编写ingress规则

部署方法小编已经在下面给出:自己动手也是成长的一部分嘛!

小编也从网上了找了许多的ingress 部署博客,好像基本上都是wget一些yaml文件,但是给出的地址好像都不能访问了,所以还是老老实实的看文档搭建吧,加油加油!

4) Ingress常见配置策略:

① 转发到单个后端服务上

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: test-ingressspec:  backend:    serviceName: myweb    servicePort: 8080

上面的配置对Ingress Controller的访问请求都将被转发到“myweb:8080”这个服务上。

② 同一域名下,不同的URL路径被转发到不同的服务上

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: test-ingressspec:  rules:  - host: mywebsite.com    http:      paths:      - path: /web        backend:          serviceName: web-service          servicePort: 80      - path: /api        backend:          serviceName: api-service          servicePort: 8081

以上配置当访问:

mywebsite.com/web:80 ------转发到------ web-service:80
mywebsite.com/api:80 ------转发到------ api-service:8081
③ 不同域名被转发到不同的服务

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: testspec:  rules:  - host: foo.bar.com    http:      paths:      - backend:          serviceName: service1          servicePort: 80  - host:bar.foo.com    http:      paths:      - backend:          serviceName: service2          servicePort: 80

访问foo.bar.com-- service1:80 访问bar.foo.com -- service2:80

④ 不使用域名的转发规则

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: test-ingressspec:  rules:  - http:    paths:    - path: /demo      backend:        serviceName: webapp        servicePort: 8080

这种配置,通过任意一条运行的ingress-controller 的node都能访问到后端的服务。

注意:这种方式默认是不能使用https访问的,如果想使用https访问,需要在编写Ingress规则的时候,加入一个annotation ”ingress.kubernetes.io/ssl-redirect=false” 来关闭强制启用HTTPS的设置。

错误解决

1 .搭建Cassandra问题

由于小编之前用的是单机版的kubernetes集群,之前遇到过一些问题导致pod无法启动,然后就修改了apiservice的配置:

kubernetes之service深入(四)
就将这个两个配置删除了。
然后创建Cassandra 的pod的时候就报错:
kubernetes之service深入(四)
然后查看:[root@zy yaml_file]# kubectl get serviceaccount
kubernetes之service深入(四)
解决:
在/etc/kubernetes/apiserver 中的--admission_control加入ServiceAccount:
kubernetes之service深入(四)
然后在/etc/kubernetes/controller-manager配置:
--service_account_private_key_file=/var/run/kubernetes/apiserver.key
kubernetes之service深入(四)
之后重启这两个服务:
再执行命令

[root@zy yaml_file]# kubectl get serviceaccount

kubernetes之service深入(四)

小编本来以为这样问题就解决了,结果查询Cassandra 的pod的日志发现:
kubernetes之service深入(四)
小编初步推断可能是集群没有搭建DNS:因为在查看SeedProvider 源码时:
kubernetes之service深入(四)
后期会慢慢排查,将问题解决!

2. 外部集群不能通过service访问其对应的服务

  在service暴露端口时,发现外部访问时,之后 可以使用IP访问,其他主机或者浏览器访问不到Kubernetes是1.5.2版本,这里小编设置了service的type为NodePort,并且nodePort设置了一个值,最终pod和service都启动正常,使用clusterIP和本机IP都可以访问,但是外部集群无法访问。

原因
kubernetes之service深入(四)
使用service+NodePort时,其中的网络是上图所示,客户端访问时,需要通过kube-proxy这个服务,但是在1.2以上这个kube-proxy服务在启动时需要添加参数:
KUBE_PROXY_ARGS=”“改为KUBE_PROXY_ARGS=”–proxy-mode=userspace”

解决:

修改master的/etc/kubernetes/proxy
将其中的启动命令的参数添加:
KUBE_PROXY_ARGS="--proxy-mode=userspace"
kubernetes之service深入(四)
重启kube-proxy服务:

[root@zy yaml_file]# systemctl restart kube-proxy

然后在启动相应的pod和service,之后浏览器访问:

OK:
kubernetes之service深入(四)
或者:
在默认的iptables mode下,修改(vim /etc/sysctl.conf)文件,加入:net.ipv4.ip_forward=1重启主机,然后在通过service访问即可。

到这里可能大家还是不太明白为什么service不能外部访问,需要修改kube-proxy的配置,这里小编就给大家介绍一下kube-proxy与service的关系:

  kube-proxy其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。kube-proxy管理sevice的Endpoints,该service对外暴露一个Virtual IP,也成为Cluster IP, 集群内通过访问这个Cluster IP:Port就能访问到集群内对应的serivce下的Pod。service是通过Selector选择的一组Pods的服务抽象,其实就是一个微服务,提供了服务的LB和反向代理的能力,而kube-proxy的主要作用就是负责service的实现。

  而kube-proxy内部原理:kube-proxy当前实现了两种proxyMode:userspace和iptables。其中userspace mode是v1.0及之前版本的默认模式,从v1.1版本中开始增加了iptables mode,在v1.2版本中正式替代userspace模式成为默认模式。小编的集群是1.5.2的默认的是iptables,所以需要做一些配置,因此我们改为了userspace,就可以让外部通过service暴露的端口映射到宿主机上来访问服务啦。

Userspace:userspace是在用户空间,通过kube-proxy来实现service的代理服务。
kubernetes之service深入(四)
Iptables:它完全利用Linux内核iptables来实现service的代理和LB
kubernetes之service深入(四)

转载于:https://blog.51cto.com/14048416/2401291

你可能感兴趣的文章
贪食蛇
查看>>
201521123009 《Java程序设计》第11周学习总结
查看>>
Python3之多线程学习
查看>>
MVC和MTV结构分析
查看>>
(转)微信网页扫码登录的实现
查看>>
mariadb启动报错:[ERROR] Can't start server : Bind on unix socket: Permission denied
查看>>
nginx的信号量
查看>>
云im php,网易云IM
查看>>
河南农业大学c语言平时作业答案,河南农业大学2004-2005学年第二学期《C语言程序设计》期末考试试卷(2份,有答案)...
查看>>
c语言打开alist文件,C语言 文件的打开与关闭详解及示例代码
查看>>
c语言 中的共用体和结构体如何联合定义,结构体(Struct)、联合体(Union)和位域
查看>>
SDL如何嵌入到QT中?!
查看>>
P1026 统计单词个数
查看>>
[js高手之路] html5 canvas系列教程 - 状态详解(save与restore)
查看>>
poi excel 常用api
查看>>
AD提高动态的方法(附SNR计算)
查看>>
[转]轻松实现可伸缩性,容错性,和负载平衡的大规模多人在线系统
查看>>
五 数组
查看>>
也谈跨域数据交互解决方案
查看>>
EntityFramework中使用Include可能带来的问题
查看>>