小阿轩yx-Kubernetes服务发布基础

小阿轩yx-Kubernetes服务发布基础

前言

  • 通过 k8s 的调度,可以成功的将服务部署到 Kubernetes,应用部署后,最重要的就是对用户开放。

区别

传统的架构中

  • 用户访问公司内的服务可能通过了多层代理、网关、防火墙等。
  • 可能是通过Nginx、Haproxy、LVS、公有云的 SLB、ELB 等实现的负载均衡和域名路由。
  • 配置多个相同服务的负载均衡可能使用的是 Nginx的upstream。
  • 配置域名访问应用可能使用 Nginx 的 Server 配置。

Kubernetes 中

  • 访问 Kubernetes 中的的应用同样也会经过多层代理、网关、防火墙等。
  • 虽然也是通过诸如此类的技术实现的域名路由或者负载均衡,只不过对应的名字叫法可能有所变化,不要把这些当做-个比较新颖的东西,其实内部的实现和之前并无区别。
  • 配置多个相同服务的负载均衡可能使用Service 实现。
  • 用Ingress 实现域名路由的配置。

service 的定义

  • 用于为一组提供服务的 Pod 抽象一个稳定的网络访问地址
  • 是 k8s 实现微服务的核心概念
  • 通过定义设置的访问地址是 DNS 域名格式的服务名称,对于客户端应用来说,网络访问方式并没有改变。
  • 还提供了负载均衡器的功能,将客户端请求负载分发到后端提供具体服务的各个Pod 上。
  • 主要用于提供网络服务,通过定义,能够为客户端应用提供稳定的访问地址(域名或 IP 地址)和负载均衡功能,以及屏蔽后端 EndPoint 的变化,是 Kubernetes 实现微服务的核心资源。

总之,service 是 kubernetes 中一个非常重要的概念,service 用于将外部请求代理到内部 pod上,提供4层负载均衡和服务发现的功能,使得我们可以构建高可用和可扩展的应用程序。

Service 的概念和原理

service 基本介绍

  • 是 kubernetes 中的一种抽象
  • 用于定义一组 pod 以及访问这一组 pod 的策略
  • service 会为一组 pod 创建一个虚拟的 IP 地址,通过这个 IP 地址可以访问这组 pod 中的任意一个 pod。
  • 当客户端请求这个虚拟 IP 地址时,请求会被负载均衡到一组 pod 中的某一个 pod 上,从而完成对 pod 的访问。

作用

  • 是将一组 pod 封装为一个虚拟的服务,并提供一个统一的入口,供客户端访问。

service 支持的功能

  • 负载均衡
  • 服务发现
  • 服务暴露

kubernetes 中

  • pod的IP地址是动态变化的,因此无法直接通过pod的IP地址进行访问。service的出现正式为了解决找个问题的。

service 的实现依赖于 kube-proxy 组件和 CoreDNS组件。它们共同协作,将 service 与 pod 连接起来,实现对 pod 代理访问

总之,service 是 kubernetes 中一种非常重要的资源对象,它可以让 pod 对外提供服务,并提供负载均衡、服务发现等功能。

service 的负载均衡机制

  • 当一个 Service 对象在 Kubernetes 集群中被定义出来时,集群内的客户端应用就可以通过服务 IP访问到具体的 Pod 容器提供的服务了。
  • 从服务 IP 到后端 Pod 的负载均衡机制,则是由每个 node 上的kube-proxy 代理来负责实现的。

kubeproxy 的代理模式有

  • userspace
  • iptables
  • ipvs
  • kernelspace

userspace

  • 起初,kube-proxy进程是一个真实的TCP/UDP代理
  • 当某个 pod 以 clusterIP 方式访问某个service的时候,流量会被 pod 所在的本机的 iptables 转发到本机的 kube-proxy 进程,然后将请求转发到后端某个 pod 上。

具体过程

  • kube-proxy 为每个 service 在 node 上打开一个随机端口作为代理端口
  • 建立 iptables 规则,将 clusterip 的请求重定向到代理端口(用户空间)
  • 到达代理端口的请求再由 kubeproxy 转发到后端

clusterip 重定向到 kube-proxy 服务的过程存在内核态到用户态的切换

开销很大,因此有了iptables 模式,而 userspace 模式也被废弃了。

iptabels

  • kubernets 从1.2版本开始将iptabels模式作为默认模式,这种模式下kube-proxy不再起到proxy的作用。

核心功能

  • 通过 API Server 的 Watch 接口实时跟踪 Service 和 Endpoint 的变更信息,并更新对应的 iptables 规则,Client 的请求流量通过 iptables 的 NAT 机制“直接路由”到目标 Pod

不同于 userspace

iptables 的模式中

  • kube-proxy不再负责转发数据包,kube-proxy 主要完成对 iptables 策略的动态管理。
  • 数据包的走向完全由 iptables 规则决定,这样的过程不存在内核态到用户态的切换,效率明显会高很多。
  • 随着 service的增加,iptables 规则会不断增加,导致内核十分繁忙(等于在读一张很大的没建索引的表)。

ipvs

  • 从 kubernetes 1.8版本开始引入第三代的 IPVS 模式
  • 它也是基于 netfilter 实现的

定位不同

  • iptables 是为防火墙设计的
  • IPVS 则专门用于高性能负载均衡,并使用高效的数据结构 Hash 表,允许几乎无限的规模扩张。

ipvs 为负载均衡提供了更多的算法

  • rr:轮训
  • lc:最小连接数
  • df:目标哈希
  • sh:源哈希
  • sed:预计延迟最短
  • nq:从不排队

  • ipvs 使用 ipset 存储 iptables 规则,在査找时类似 hash 表査找,时间复杂度为 0(1)
  • 而 iptables 时间复杂度则为 0(n)
  • 可以将 ipset 简单理解为 ip 集合
  • 集合的内容可以是 IP 地址、IP 网段、端口等,iptabels可以直接添加规则对这个可变集合进行操作,这样做的好处可以大大减少 iptables 规则的数量,从而减少性能损耗。

査看系统是否开启了 ipvs 模块,可以使用命令

lsmod | grep ip_vs
  • 时间复杂度用字母 0 表示

kernelspace

  • Windows server 上的代理模式

service 的4种类型

ClusterIP
  • 这是最常用的 Service 类型
  • 它为 Pod 提供了一个虚拟的 IP 地址。
  • 当其他 Pod 需要访问该 Service 时,它们只需要使用该虚拟 IP 地址即可。
  • Kubernetes 会自动将请求路由到相应的 Pod 上

NodePort
  • 将 Pod 公开为集群中所有节点上的某个端口。
  • 当外部请求到达任何一个节点上的该端口时,Kubernetes 会将请求路由到相应的 Pod 上。

LoadBalancer Service
  • 使用云提供商的负载均衡器将请求路由到后端 PodKubernetes 会自动创建和配置负载均衡器,并将其绑定到 Service 上。

externalName Service
  • 允许你将 Service 映射到集群外部的某个名称。
  • 当 Pod需要访问该 service 时,它们将使用该名称来解析出相应的 IP 地址。

将 images 镜像文件通过 Xftp 上传至 master、node01、node02(101、102、103)

将资源清单单独上传至 master 主节点(101)

三台主机导入镜像

主机一

[root@k8s-master ~]# cd images/
[root@k8s-master images]# bash imp_docker_img.sh 

主机二

[root@k8s-node01 ~]# cd images/
[root@k8s-node01 images]# bash imp_docker_img.sh 

主机三

[root@k8s-node02 ~]# cd images/
[root@k8s-node02 images]# bash imp_docker_img.sh 

生成用于测试 service 的 Deployment

  • 编写 Deployment,用于各种 service 的验证
  • 应用 Service 概念之前,先创建一个提供 web 服务的 Pod 集合,有两个 Tomcat 容器副本组成,每个容器提供的服务端口都为 8080

编辑 deployment

[root@k8s-master ~]# cat webapp-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  #pod 的副本数
  replicas:2
  #目标 Pod 的标签选择器
  selector:
    #需要匹配的标签
    matchLabels:
      #对应了目标 pod 的标签名称
      app: webapp
  #自动创建新的 pod 副本的模板
  template:
    metadata:
      #定义 pod 的标签
      labels:
        #标签值为 app:webapp
        app: webapp
    spec:
      containers:
      - name: webapp
        image: kubeguide/tomcat-app:v1
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP

selector(选择器)

  • 主要用于资源的匹配,只有符合条件的资源才会被调用或使用,可以使用该方式对集群中的各类资源进行分配。
  • Kubernetes 和核心资源 Deployment、statefulset 管理的 Pod 是通过选择器字段决定的,通过 Service 访问这些后端 Pod 也是通过选择器字段决定的。

label(标签)

  • 可以对 Kubernetes 的其他资源进行配置,当Kubernetes 对系统的任何 API 对象如Pod 进行分组时,会对其添加标签,用以精准的选择对应的API对象。

创建该 Deployment

[root@k8s-master ~]# kubectl create-f webapp-deployment.yaml

查看 pod 创建情况

[root@k8s-master ~l# kubectl get pod
NAME                       READY       STATUS      RESTARTS   AGE
webapp-8554f77548-9xwmm    1/1         Running     0          93s
webapp-8554f77548-jrw7f    1/1         Running     0          93s

查看各个 pod 的 IP 地址

[root@k8s-master ~]# kubectl get pods -l app=webapp -o wide
NAME                    READY    STATUS     RESTARTS    AGE        IP            NODE    NOMINATED NODE    READINESS GATES
webapp-8554f77548-9xwmm 1/1      Running    0            2mss5    172.17.125.3   k8snode01    <none>        <none>
webapp-8554f77548-jrw7f 1/1      Running。  0            2m55s    172.27.14.195  k8s-node02    <none>        <none>

访问这两个地址

[root@k8s-master ~]# curl 172.17.125.3:8080
[root@k8s-master ~l# curl 172.27.14.195:8080

service 的创建

创建一个ClusterIP类型 service

描述

  • ClusterIP 是默认的 Service 类型。
  • 它将创建一个虚拟的 clusterIp 地址,用于在集群内部访问 Service。

使用场景

  • 适用于集群内部的服务通信,例如将前端服务和后端服务连接起来,供内部其他服务使用。
通过 expose 命令创建 clusterIP 类型的 service
  • 为了让客户端应用能够访问到前面创建的两个 Tomcat Pod 实例,需要创建一个 Service 来提供服务。

k8s 提供了一种快速的方法

  • 即通过 kubectl expose 命令来创建 Service。

执行 expose 命令暴露端口

[root@k8s-master ~l# kubectl expose deployment webapp

查看创建的 Service

[root@k8s-master ~]# kubectl get svc
NAME        TYPE         CLUSTER-IP        EXTERNAL-IP   PORT(S)    AGE
kubernetes  ClusterIP    10.96.0.1         <none>        443/TCP    9d
webapp      Cluster      10.104.162.209    <none>        8080/TCP   32d
  • 可以看到,系统为他分配了一个虚拟 IP 地址,Service 的端口号,从 pod 中复制而来。我们就可以通过这个虚拟 IP 地址,和端口号来访问这个 Service 了。

访问测试

[root@k8s-master ~]# curl 10.104.162.209:8080
  • 客户端对 Service 的访问被自动负载分发到了后端的两个 pod 之一。
  • Kubernetes 自动完成将客户端请求转发到后端多个 EndPoint 的负载分发的工作。
  • 通过负载均衡机制,Kubernetes 实现了一种分布式应用的统一入口,免去了客户端应用获知后端服务实例列表和变化的复杂度。

删除此 Service

[root@k8s-master ~]# kubectl delete service webapp
使用 yaml 文件创建 Service
  • 除了使用 expose 的命令创建 Service,更便于管理的方式是 yaml 文件来创建 Service。

编辑 service 文件

root@k8s-master ~]# cat webapp-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
  selector:
    app: webapp
  • 案例中的 ports 定义的是 Service 本身的端口号 8080(用于提供给外部用户访问的端口)targetPort 则用来指定后端 Pod 的容器端口号,selector 定义的是后端 Pod 所拥有的 label

利用 yaml 创建此服务

[root@k8s-master ~]# kubectl create -f webapp--service.yaml

查看创建的 Service

[root@k8s-master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP    POET(S)    AGE
kubernetes   ClusterIP   10.96.0.1     <none>         443/TCP    9d
webapp       ClusterIP   10.108.79.50  <none>         8080/TCP   9s

访问测试

[root@k8s-master ~]# curl 10.108.79.50:8080

查看 EndPoint 列表

  • 一个 Service 对应的后端由 Pod 的 IP 地址何容器的端口号组成,即一个完成的 IP:Port 访问地址。
  • 这在 k8s 中叫做 EndPoint。
  • 通过査看 Service 的详细信息,可以看到其后端的 EndPoint 列表
[root@k8s-master ~]# kubectl describe svc webapp
Name:                webapp
Namespace:           default
Labels:              <none>
Annotations:         <none>
Selector:            app=webapp
Type:                ClusterIP
IP Family Policy:    SingleStack
IP Families:         IPv4
IP:                  10.108.79.50
IPs:                 10.108.79.50
POrt:                <unset> 8080/TCP
TargetPort:          8080/TCP
Endpoints:           172.17.125.4:8080,172.27.14.196:8080
Session Affinity:    None
Events:              <none>

查看 EndPoint 资源对象

  • 实际上,k8s 自动创建了与 Service 关联的 EndPoint 资源对象,这可以通过 EndPoint 对象进行查看
[root@k8s-master ~]# kubectl get endpoints
NAME          ENDPOINTS                                AGE
kubernetes    192.168.10.101:6443                      9d
webapp        172.17.125.4:8080,172.27.14.196:8080     6m19s

删除这个 Service

[root@k8s-master ~]# kubectl delete -f webapp-service.yaml
或
[root@k8s-master ~]# kubectl delete service webapp
创建 NodePort 类型的 service
描述
  • NodePort 将在每个节点上公开一个端口,并将流量转发到 Service。它会创建一个ClusterIP,并将指定的端口映射到每个节点上的相同端口。
使用场景
  • 适用于需要从外部访问集群中的服务时,可以通过节点的 IP 地址和映射的端口进行访问。
  • 这对于开发和测试环境非常有用。

创建 Service 文件

  • 设置 Service 类型为 NodePort,并设置具体的 nodePort 端口号位30008
[root@k8s-master ~]# cat webapp-svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30008
    selector:
    app: webapp
  • nodePort 端口的范围在 1.23.6 的版本中为 30000-32767

创建此 Service

  • 继续使用刚才的 webapp 的 Deployment,为此 Deployment 创建一个 NodePort 类型的 service
[root@k8s-master ~]# kubectl create -f webapp-svc-nodeport.yaml

查看创建的 Service

[root@k8s-master ~]# kubectl get svc
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP    PORT(S)           AGE
kubernetes    ClusterIP   10.96.0.1       <none>         443/TCP           9d
webapp        NodePOrt    10.98.184.252   <none>         8080:30008/TCP    119s

用浏览器访问地址

  • 192.168.10.101:30008

  • 因为 NodePort 的方式可以在每个 Node 节点创建出这个端口,所以在任何一个节点使用 netstat -anptgrep 30008 命令查询,都可以看到此端口,在访问的时候,IP 地址可以使用任何一个主机的 IP 地址

删除该 Service

[root@k8s-master ~]# kubectl delete -f webapp-svc-nodeport.yaml
创建 LoadBalancer 类型的 service

公有云的环境中会使用 LoadBalancer 的类型

  • 可以将 Service 映射到公有云提供的某个负载均衡器的 IP 地址上,客户端通过负载均衡器的 IP 和 Service 的端口号就可以访问到具体的服务。

描述

  • LoadBalancer 为 Service 创建一个外部负载均衡器,并分配一个外部 IP 地址。
  • 它通常由云提供商的负载均衡服务实现。

使用场景

  • 适用于需要将流量从外部负载均衡器分发到集群内部的服务

编写 LoadBalancer 类型的 Service 文件

[root@k8s-master ~]# cat webapp-svc-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
  name:webapp
  namespace: default
  labels:
    app: webapp
spec:
  type: LoadBalancer
  ports:
  - port: 8080
    targetPort: http
    protocol: TCP
    name: http
    #没有此参数,系统会自动指定一个随机端口
    nodePort: 31771
  selector:
    app: webapp
  • Service 创建好后,云服务商会在 Service 定义中补充 LoadBalancer 的 IP 地址,之后就可以在客户端访问该 Service 了。
  • nodePort 的端口范围在 30000-32767 之间。

创建此 Service

[root@k8s-master ~]# kubectl create -f webapp-svc-loadbalancer.yaml

查看创建结果

[root@k8s-master ~]# kubectl get svc
NAME          TYPE            CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
kubernetes    ClusterIP       10.96.0.1        10.96.0.1      <none>         9d
webapp        LoadBalancer    10.111.51.212    <pending>      8080:31458     2m56s

用浏览器访问

  • 192.168.10.101:31458

删除 Service

[root@k8s-master ~]# kubectl delete -f webapp-svc-loadbalancer.yaml
创建 ExternalName 类型的 service
描述
  • ExternalName 允许 Service 通过返回CNAME记录来引用集群外部的服务。
  • 它没有ClusterIP、NodePort 或 LoadBalancer。
使用场景
  • 适用于需要将K8s内部的服务与集群外的现有服务进行关联

ExternalName 类型是 Service 的特例

  • 用于将集群外的服务定义为 Kubernetes 的集群 Service,并通过 ExternalName 字段指定外部服务的地址,可以使用域名或 IP 格式。
  • 集群内客户端应用通过访问这个 Service 就能访问外部服务了。
  • 他没有选择器,没有定义任何端口和 EndPoint,他通过返回该外部服务的别名来提供服务。
  • 也可以用于两个不同的 namespace 之间的不同 pod 可以通过 name 的形式访问。

两个不同的命名空间中的 pod,可以直接使用他们的 IP 地址进行通信,但是 pod 的 IP 地址是随机分配的,重建 pod 后其 IP 地址就改变了,因此我们要用 pod 对应的 service 名称进行通信。

但是跨命名空间是不能解析其他命名空间中创建的 service 名称的。

这个时候就可以使用 ExternalName 实现两个不同命名空间中的各个 pod 间的通信。

创建案例所需的两个命名空间

[root@k8s-master ~]# kubectl create namespace test01
[root@k8s-master ~]# kubectl create namespace test02

第一个 Pod

编写 myapp01.yaml 文件

[root@k8s-master ~]# cat myapp01.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp01
  namespace: test01
spec:
  replicas: 1
  #标签选择器
  selector:
    #匹配的标签为
    matchLabels:
      app:myapp01
      release: canary
    template:
      metadata:
        labels:
          app:myapp01#和上面的 myapp 要匹配
          release: canary
      spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
          ports:
          - name: http01
            containerPort: 80

创建命名空间位 test01 的 Pod

[root@k8s-master ~]# kubectl create -f myapp01.yaml

创建一个无头(headless)Service

[root@k8s-master ~]# cat myapp-svc-headless01.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc01
  namespace: test01
spec:
  selector:
    #挑选的 pod 还是 myapp01。一个 pod 可以有多个 service
    app:myapp01 
    release: canary
  #None 表示是无头 service
  clusterIp: None
  ports:
  #service ip 中的端口
  - port: 39320
    #容器 ip 中的端口
    targetPort:80
  • (Headless Service)无头 Service:这种服务没有入口地址(没有clusterIP),kube-proxy 也不会为其创建负载转发的规则,服务名的解析机制取决于这个无头 Service 是否设置了标签选择器。
  • 无头服务创建出来之后,对于其他外部的 pod 来讲,该 pod 对应的名字就确定了下来,其固定的格式:无头服务名,命名空间,svc.cluster.local

创建 myapp-svc-headless01.yaml 文件

[root@k8s-master ~]# kubectl create -f myapp-svc-headless01.yaml

创建 extername

[root@k8s-master ~]# cat myapp-svc-extername01.yaml
kind: service
apiVersion: v1
metadata:
  name: myapp-svcname02
  namespace: test01
spec:
  type: ExternalName
  externalName: myapp-svc02.test02.svc.cluster.local
  • name:myapp-svcname02:指的是外部的服务名称
  • myapp-svc02.test02.svc.cluster.local:对方无头服务的名字
  • svc.cluster.local:对方命名空间的名字

创建 myapp-svc-extername01.yaml 文件

[root@k8s-master ~]# kubectl create -f myapp-svc-extername01.yaml

创建第二个 Pod

查看命名空间位 test02 的 Pod

[root@k8s-master ~]# cat myapp02.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp02
  namespace: test02
spec:
  replicas: 1
  #标签选择器
  selector:
  #匹配的标签为
  matchLabels:
    app: myapp02
    release:canary
template:
  metadata:
    labels :
      #和上面的 myapp 要匹配
      app: myapp02
      release:canary
  spec:
    containers:
    - name: myapp02
      image: ikubernetes/myapp:v1
      ports:
      - name: http02
        containerPort:80

创建 myapp02.yaml 文件

[root@k8s-master ~]# kubectl create -f myapp02.yaml

创建一个无头(headless)Service

[root@k8s-master ~]# cat myapp-svc-headless02.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc02
  namespace: test02
spec:
  selector:
    #挑选的 pod 还是 myapp。一个 pod 可以有多个 service
    app: myapp02
    release: canary
  #None 表示是无头service
  clusterIP: None
  ports:
  #service ip 中的端口
  - port:39320
    #容器 ip 中的端口
    targetPort:80

创建 myapp-svc-headless02.yaml 文件

[root@k8s-master ~]# kubectl create -f myapp-svc-headless02.yaml

创建 extername

[root@k8s-master ~]# cat myapp-svc-extername02.yaml
kind: Service
apiVersion: v1
metadata:
  name: myapp-svcname01
  namespace: test02
spec:
  type: ExternalName
  externalName:myapp-svc01.test01.svc.cluster.local
  • name: myapp-svcname01:指的是外部的服务名称

创建 myapp-svc-extername02.yaml 文件

[root@k8s-master ~]# kubectl create -f myapp-svc-extername02.yaml

验证 Pod 间的通信

查看命名空间为 test01 的 Pod

[root@k8s-master ~]# kubectl get pods -n test01
NAME                        READY   STATUS      RESTARTS    AGE
myapp01-696c886d6b-tq7vv    1/1     Running     0           54s    

登录文件

[root@k8s-master ~]# kubectl exec -it myapp01-696c886d6b-tq7vv -n test01 -- /bin/sh
/ # nslookup myapp-svcname02
/ # ping myapp-svcname02
PING myapp-svcname01 (172.17.125.3): 56 data bytes
64 bytes from 172.17.125.3: seq=0 ttl=62 time=0.903 ms
64 bytes from 172.17.125.3: seq=1 ttl=62 time=3.139 ms

/ # nslookup myapp-svc02.test02.svc.cluster.local
/ # ping myapp-svc02.test02.svc.cluster.local
PING myapp-svc02.test02.svc.cluster.local (172.17.125.3): 56 data bytes
64 bytes from 172.17.125.3: seq=0 ttl=62 time=0.903 ms
64 bytes from 172.17.125.3: seq=1 ttl=62 time=3.139 ms

获取文件详细信息

[root@k8s-master ~]# kubectl get pods -n test02 -o wide
NAME                      READY    STATUS    RESTARTS  AGE      IP              NODE        NOMINATED NODE    READINESS GATES
myapp-6bb4786bcd-hsr28    1/1      Running    0        7m31s    172.17.125.3    k8s-node01   <none>          <none>
[root@k8s-master ~]# kubectl get pods -n test02 -o wide
NAME                      READY    STATUS    RESTARTS  AGE      IP              NODE        NOMINATED NODE    READINESS GATES
myapp-696c886d6b-tndns    1/1      Running    0        9m30s    172.25.244.197    k8s-master01   <none>          <none>

查看命名空间为 test02 的 Pod

[root@k8s-master ~]# kubectl get pods -n test02 -o wide
NAME             TYPE            CLYSTER-IP    EXTERNAL-IP                          PORT(S)        AGE      SELECTOR
myapp-svc        ClusterIP       None          <none>                              39320/TCP      7m25s    app=myapp,release=canary
myapp-svcname    ExternalName    <none>        myapp-svc.test02.svc.cluster.local    <none>        6m45s    <none>

查看命名空间为 test01 的 Pod

[root@k8s-master ~]# kubectl get pods -n test01 -o wide
NAME             TYPE            CLYSTER-IP    EXTERNAL-IP                          PORT(S)        AGE    SELECTOR
myapp-svc        ClusterIP       None          <none>                              39320/TCP       10     app=myapp,release=canary
myapp-svcname    ExternalName    <none>        myapp-svc.test02.svc.cluster.local    <none>        9m59s    <none>
service 的其它应用
Service 的多端口设置
  • 一个容器应用可以提供多个端口的服务,在 Service 的定义中也可以相应的设置多个端口号

创建 service 文件

[root@k8s-master ~]# cat service-multiple-ports.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: web
    protocol: TCP
    - port: 8005
      targetPort: 8005
      name: management
      protocol: TCP
    selector:
      app: webapp
  • selector 中的 app: webapp 的标签对应的是 webapp-deployment.yaml 中的 pod 的标签

创建 service

[root@k8s-master ~]# kubectl create -f service-multiple-ports.yaml

查看 EndPoint 列表

[root@k8s-master ~]# kubectl describe svc webapp

查看创建的 Service

[root@k8s-master ~]# kubectl get svc webapp

删除这个 Service

[root@k8s-master ~]# kubectl delete -f webapp-service.yaml
或
[root@k8s-master ~]# kubectl delete service webapp

Kubernetes 服务发现

  • 服务发现机制是指客户端如何在一个 kubernetes 集群中获知后端服务的访问地址。

Kubernetes 服务发现有两种方式

  • 环境变量
  • DNS

基于环境变量的服务发现

  • 当 Pod 部署到一个 node 节点后,该 node 节点上的 kubelet 会在该 pod 内部设置一组环境变量,这些环境变量是根据活跃的 Service 生成的,所以,要使用基于环境变量的服务发现,需要先创建对应的Service 后再创建所需的 Pod。

先创建出之前用的 service

[root@k8s-master ~]# kubectl create -f service-multiple-ports.yaml
[root@k8s-master ~]# kubectl create -f webapp-deployment.yaml

获取 Pod 状态

[root@k8s-master ~]# kubectl get pod
NAME                        READY     STATUS      RESTARTS    AGE
webapp-86b5d9fc88-cv6qq     1/1       Running     0           82s
webapp-86b5d9fc88-s4smp     1/1       Running     0           82s
  • 任意的 Pod 都会根据这些 service 创建一组变量用于服务发现。

登录文件

[root@k8s-master ~]# kubectl exec -it webapp-86b5d9fc88-cv6qq -- enV
PATH=/usr/local/tomcat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=webapp-86b5d9fc88-cv6qqTERM=xterm
KUBERNETES PORT 443 TCP=tcp://10.96.0.1:443
MYNGINX SERVICE PORT HTTP=80
MYNGINX PORT 80 TCP PORT=80
MYNGINX PORT 80 TCP ADDR=10.109.164.93
KUBERNETES PORT 443 TCP PORT=443
MYNGINX SERVICE PORT=80
MYNGINX PORT 80 TCP=tcp://10.109.164.93:80
KUBERNETES PORT 443 TCP PROTO=tCP
KUBERNETES PORT 443 TCP ADDR=10.96.0.1
KUBERNETES SERVICE HOST=10.96.0.1
KUBERNETES SERVICE PORT=443
KUBERNETES SERVICE PORT HTTPS=443
MYNGINX PORT 80 TCP PROTO=tcp
KUBERNETES PORT=tcp://10.96.0.1:443
MYNGINX SERVICE HOST=10.109.164.93
MYNGINX PORT=tcp://10.109.164.93:80
LANG=C.UTF-8
JAVA HOME=/usr/lib/jvm/java-7-openjdk-amd64/jre
JAVA_VERSION=7u101

基于 DNS 的服务发现

  • Kubernetes 进行服务发现的另一种方式是基于 Kubernetes 内部的 DNS 记录
  • 新版的 Kubernetes默认使用 CoreDNS 作为集群的内部 DNS,一般 coreDNs 的 Service 地址为 Service 网段的低 10 个地址,比如 10.96.0.10,端口为 53,集群内的 Pod 可以通过该地址和端口进行 Kubernetes 内部的服务解析。
  • DNS 服务器监听 Kubernetes 创建的 Service,然后给每个 Service 添加一组 DNS 记录,集群中的 Pod就能通过 Kubernetes 内部的 DNS 解析到 Service 的 IP,也就是 Service 的 ClusterIP。

创建一个含有 nslookup 命令的容器

[root@k8s-master ~]# kubectl run redis --image=redis:3.2.10-alpine

测试解析 kube-dns 的 Service

[root@k8s-master ~]# kubectl exec -it redis -- nslookup redis
nslookup: can't resolve '(null)': Name does not resolve
Name :    redis
Address 1: 10.244.85.204 redis
[root@k8s-master ~]# kubectl exec -it redis -- nslookup kube-dns.kube-system
nslookup: can't resolve '(null)': Name does not resolve
Name :    kube-dns.kube-system
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

删除资源

  • kubectl delete -f myappe1.yamL
  • kubectl delete -f myapp-svc-headlesse1.yamlkubectl delete -f myapp-svc-extername01.yaml
  • kubectl delete -f myapp02.yaml
  • kubectl delete -f myapp-svc-headless02.yaml
  • kubectl delete -f myapp-svc-extername02.yaml

将 Service 和 Deployment 整合的案例

案例一

查看 nginx-service.yaml 文件

[root@k8s-master ~]# cat nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mynginx
  namespace: default
  labels:
    app: mynginx
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
    selector:
      app: mynginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mynginx-deployment
  namespace: default
  labels:
     app: mynginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      containers:
      - name: mynginx
        image: nginx:1.7.9
        ports:
          - name: http
            containerPort: 80
            protocol: TCP

app: mynginx

  • 红色部分的标签名称需要一致。

案例二

[root@k8s-master ~]# cat tomcat-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp
  namespace: default
  labels:
    app: mynginx
spec:
  type: NodePort
  ports:
    - port: 8080
      targetPort: 8080
      nodePort: 30008
      name: http
    selector:
      app: webapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  namespace: default
  labels:
     app: mynginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: kubeguide/tomcat-app:v1
        ports:
          - name: http
            containerPort: 8080
            protocol: TCP

小阿轩yx-Kubernetes服务发布基础

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值