Kubernetes系列(二)Service

作者: LemonNan
原文地址: https://juejin.im/post/6863704173931593736

Service

Kubernetes 的 Service 可以为一组具有相同功能的容器应用(Pod)提供一个统一的入口地址, 然后将请求负载的分发到后端的各个容器组(Pod)上, 本篇将对 Kubernetes 的 Service 的使用做个简单介绍.


操作的基础

最近的文章都是基于 minikube 进行的操作, 所以时不时的需要进入到 minikube 里面进行一些操作的验证, 所以把进入 minikube 的操作记录在这.

# minikube 默认用户名:docker 密码:tcuser , 我的地址是 192.168.99.100
ssh docker@192.168.99.100

发布服务类型

说到服务, 自然是需要对外提供的, Kubernetes 中有几种不同的服务类型, ClusterIP, NodePort, LoadBalancer, 不同的服务类型对应的不同的系统结构及访问方式, 所以在介绍 Service 之前简单介绍一下它的服务类型.

ClusterIP

集群内部容器访问地址,会生成一个只能在集群内部访问的集群内部IP , 这也是 Service 默认的类型(也是本篇使用的类型).

NodePort

通过每个 Node(物理节点) 上的 IP 和静态端口(NodePort)向外暴露服务, 最终通过 {NodeIP : NodePort} 进行对应服务的访问.

LoadBalancer

使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务, 比如阿里云的 SLB。


创建 Service

配置文件 yaml

pod

由于要区分一些东西, 所以对系列一的 nginx.yaml 进行了一些修改, 最终结果如下:

# nginx.yaml
apiVersion: v1          
kind: Pod               # 创建的是Pod类型
metadata:               # 元数据, 一些基础信息
  name: pod-nginx       # 名称
  labels:
    name: label-pod-nginx # 标签
spec:
  containers:
  - name: pod-nginx     # 容器名称
    image: nginx:latest # 使用的镜像
    ports:
    - containerPort: 80 # 容器监听的端口号

接着执行 kubectl create -f nginx.yaml 进行 pod 创建


service

接下来是 service 的yaml, service 需要设置管理的对应label, 才能将pod纳入管理范围, 最终配置文件如下:

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
  namespace: default      # 命名空间,不填默认为 default
  labels:
    name: label-svc-nginx # service 的标签
  annotations:
    name: anno-nginx
spec:
  selector: 
    name : label-pod-nginx  # 管理具有 nginx 标签的 Pod 
  type: ClusterIP   # 不填默认 ClusterIP, 用于集群内部 Pod 访问, 在 Node 上 kube-proxy 通过设置的规则进行转发
  # clusterIP: 172.18.0.1 # 虚拟IP, type = ClusterIP 时, 可以不指定,不指定系统自动分发;
                        # type=LoadBalancer 时, 必须指定
  sessionAffinity:  ClientIP # 是否支持 session, 默认为空, 可选 ClientIP, 表示将同一个客户端(根据客户端IP决定)请求到一个 Pod 上
  ports:
  - name: p80      # 端口名称 
    protocol: TCP   # 协议
    port: 8080      # service 对外暴露的端口
    targetPort: 80  # 后端 Pod 端口
    # nodePort: 80    # 当上面的 type = NodePort 的时候, 指定宿主主机的端口
  # status:           # 当 type=LoadBalancer 的时候, 设置外部负载均衡的信息, 比如阿里云的 SLB 
  #   loadBalancer:
  #     ingress:
  #       ip: xxx   # 外部负载均衡地址
  #       hostname: xxx # 名称

接着执行 kubectl create -f service.yaml 进行 svc 创建


访问服务

现在测试一下, pod 和 svc 是不是已经关联上.

先分别拿到它们的 ip

pod的ip为: 172.17.0.6
svc的ip为: 10.110.146.133

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200822152631590.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpc3Zpc21pc3M=,size_16,color_FFFFFF,t_70#pic_center)

先测试pod是否正常

curl 172.17.0.6

能正常访问到
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200822152418272.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpc3Zpc21pc3M=,size_16,color_FFFFFF,t_70#pic_center)

接着试下访问 svc, 也能正常访问

# 这里是8080, service 的 yaml 里面设置的端口
curl 10.110.146.133:8080

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200822152449739.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpc3Zpc21pc3M=,size_16,color_FFFFFF,t_70#pic_center)


快速创建

Kubernetes 除了通过 yaml 文件来进行 service 的创建, 还提供了一种更加快速的创建方法 kubectl expose.

kubectl expose 的意思是将资源暴露为新的 Kubernetes Service 以创建新的 Service, 所需端口号不指定的话将从 Pod 中复制而来.

下面试试它的功能

# 根据名字为 pod-nginx 的 pod 创建 svc
kubectl expose pod pod-nginx --port=9090 --target-port=80 --name=svc-expose-nginx

创建成功, 拿到它的 ip, 进入到 minikube 里面进行测试

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200822152503162.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpc3Zpc21pc3M=,size_16,color_FFFFFF,t_70#pic_center)

在 minikube 里面进行 curl 测试, 能访问后端的 nginx 服务, 证明关联成功了

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200822152518931.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpc3Zpc21pc3M=,size_16,color_FFFFFF,t_70#pic_center)


外部服务 Service

有时候, 业务系统需要将一个外部数据库作为后端进行连接, 或者将另一个集群或 Namespace 中的服务作为 Service, 下面是具体操作步骤:

  • 创建无 Label Selector 的 Service
  • 创建一个和 Service 同名的 Endpoint, 用于指向世纪的后端访问地址

创建无 Label Selector 的 Service

yaml 文件内容

# 无 label service
apiVersion: v1
kind: Service
metadata:
  name: custiom-service
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

创建 Endpoint

yaml 文件内容

apiVersion: v1
kind: Endpoints
metadata:
  name: custiom-service  # 名字跟 service 相同
subsets:
- addresses:
  - ip: 14.215.177.xx # 某度地址
  ports:
  - port: 80

这两个都创建了之后, 外部系统访问这个 Service 的 80 端口, 请求将会被路由到外部的 14.215.177.xx 地址.
实际操作结果

创建 svc 后获取到它的ip: 10.107.234.212

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20200822152559474.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpc3Zpc21pc3M=,size_16,color_FFFFFF,t_70#pic_center)

进入到 minikube 执行命令进行查看

curl 10.107.234.212

结果很多, 选了一个比较象征性的某度关键字截图, 到此 通过 svc 访问外部服务 也成功了.

![在这里插入图片描述]( https://img-blog.csdnimg.cn/2020082215405022.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpc3Zpc21pc3M=,size_16,color_FFFFFF,t_70#pic_center)


最后

本篇介绍了 Kubernetes 向外部暴露服务的方法以及几种创建 Service 的方式, 看着似乎是一路畅通无阻就搞定了, 但是别忘了 Kubernetes 是一个全自动化应用部署平台, 根据上面情况, 如果后端 Pod 宕机了, 并且此时对应的服务只由一个 Pod 提供, 则此时服务对外是不可用的, 并且不会做到开启新的 Pod 来继续提供服务, 无法恢复可用, 完全体现不出来自动化运维的特点.
so, 这也是下一篇将要介绍的 Deployment, 它能监控到对应服务下面有多少个应用(Pod)可用, 并且可以保证可用 Pod 的数量及水平扩容等其它很多的功能.

posted @ 2020-08-24 00:28  柠檬楠  阅读(265)  评论(0)    收藏  举报