kubernetes之service深入(四)

前言

  在谈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: Service
metadata:  #元数据
  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: v1
kind: ReplicationController
metadata:
  name: webapp
spec:
  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: v1
kind: Service
metadata:
  name: webapp
spec:
  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: v1
kind: Service
metadata:
  name: webapp
spec:
  ports:
  - port: 8081
    targetPort: 8080
    name: web
  - port: 8005
    targetPort: 8005
    name: management
  selector:
    app: webapp

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

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
  - protocol: TCP
    port: 33060
    targetPort: 3306

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

kind: EndPoints
apiVersion: v1
metadata:
  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: v1
kind: Service
metadata:
  labels:
    name: cassandra
  name: cassandra
spec:
  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: v1
kind: Pod
metadata:
  labels:
    name: cassandra
  name: cassandra
spec:
  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: v1
kind: Service
metadata:
  labels:
    name: cassandra
  name: cassandra
spec:
  ports:
    - port: 9042
  selector:
    name: cassandra

#cassandra-rc.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    name: cassandra
  name: cassandra
spec:
  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深入(四)
参考文档:https://www.kubernetes.org.cn/doc-36

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

   由于pod和service是kubernetes集群范围内的虚拟的概念,所有集群外部的客户端无法访通过Pod的IP或者service的IP去访问到它们。为了让外部的客户端可以访问这些服务,kubernetes提供了将Pod或者service的端口号映射到物理机上,以使得客户端访问宿主机的端口从而访问到其容器中的服务。
案例1(①通过设置容器基本的hostPort,将容器应用的端口映射到物理机上)
#pod-hostport.yaml

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

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  hostNetwork: true
  containers:
  - name: webapp
    image: docker.io/tomcat
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080

案例3(将service的端口号映射到物理机中)
#webapp-nodePort-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  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: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
    nodePort: 30061
  clusterIP: 10.0.171.12
  loadBalancerIP: 78.11.42.19
  type: loadBalancer
status:
  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启动参数
③ 创建相应的资源对象
④ 测试
这里小编就不一一介绍了,给出搭建的地址:https://www.cnblogs.com/yujinyu/p/6112233.html

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解析服务IP
search 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: v1
kind: ConfigMap
metadata:
  name: kube-dns
  namespace: kube-system
data:
  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服务IP
upstreamNameservers:表示上游DNS配置,如果指定了,那么从节点/etc/resovl.conf就会被覆盖。最多指定3个IP。
[root@zy ~]# kubectl create -f dns-configmap.yaml

③ 测试

apiVersion: v1
kind: Pod
metadata:
  name: tester
spec:
  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/v1beta1
kind: Ingress
metadata:
  name: mywebsite-ingress
spec:
  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文件,但是给出的地址好像都不能访问了,所以还是老老实实的看文档搭建吧,加油加油!
https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md

4) Ingress常见配置策略:

① 转发到单个后端服务上

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  backend:
    serviceName: myweb
    servicePort: 8080

上面的配置对Ingress Controller的访问请求都将被转发到“myweb:8080”这个服务上。
② 同一域名下,不同的URL路径被转发到不同的服务上

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  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/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  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/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  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,之后浏览器访问:
http://192.168.130.130:30000/
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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值