Kubernetes 的服务发现与负载均衡(Service)

Kubernetes 的服务发现与负载均衡(service)

Service 的作用

  • 服务发现:由于 Kubernetes 的调度机制,在 Kubernetes 中,Pod 的 IP 不是固定的。如果其它程序需要访问这个 Pod,要怎么知道这个 Pod 的 IP 呢?
  • 负载均衡:由于 Deployment 管理着多个 Pod 的副本,如果其它程序需要访问这些 Pod,显然需要一个 proxy 为这些 Pod 做负载均衡。
  • 外部路由:如果应用程序运行在 Kubernetes 外部,如何访问 Kubernetes 内部的 Pod 呢? Kubernetes 提供了 Service 功能,用来解决这些问题。

服务发现与负载均衡

Service通常会和Deployment结合在一起使用,首先通过Deployment部署应用程序,然后再使用 Service 为应用程序提供服务发现、负载均衡和外部路由的功能。

在TKE中通过应用创建服务,默认也是一个Deployment一个Service

举例,我通过应用从ui中导入服务,确认后将生成以下yaml文件

# 这个yaml文件不可直接引用
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  creationTimestamp: null
  name: nginx-service
  namespace: '{{.NAMESPACE}}'
spec:
  replicas: 2
  revisionHistoryLimit: 5
  selector: {}
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
    spec:
      containers:
      - image: nginx:latest
        imagePullPolicy: Always
        name: nginx-service
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 250m
            memory: 256Mi
        securityContext:
          privileged: false
      serviceAccountName: ""
      volumes: null
status: {}

---
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.kubernetes.io/qcloud-loadbalancer-internet-charge-type: BANDWIDTH_POSTPAID_BY_HOUR
    service.kubernetes.io/qcloud-loadbalancer-internet-max-bandwidth-out: "1"
  creationTimestamp: null
  name: nginx-service
  namespace: '{{.NAMESPACE}}'
spec:
  ports:
  - name: tcp-80-80-chjh2
    nodePort: 0
    port: 80
    protocol: TCP
    targetPort: 80
  selector: {}
  type: LoadBalancer
status:
  loadBalancer: {}

这里我们创建了一个名为nginx-serviceService,它监听的端口是80,同时它会把全部的流量都转发给它代理的所有 Pod(这些 Pod 都必须拥有nginx-server这个标签)。

Service提供了两种服务发现的方式,第一种是环境变量,第二种是 DNS。先说第一种,上面我们创建了nginx-service这个 Service,接着如果我们再创建另外一个 Pod,那么在这个 Pod 中,可以通过环境变量知道nginx-service的地址。

首先,创建一个新的 Pod(这个 Pod 已经安装好了curl工具):

#可直接引用创建
$ cat curl-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: curl
spec:
  containers:
  - name: curl
    image: tutum/curl
    command:
      - sleep
      - "3600"
    ports:
    - containerPort: 80
$ kubectl apply -f curl-pod.yaml

接着,进入这个 Pod,可以查看它的环境变量。可以看到,当 Kubernetes 创建这个 Pod 时,会自动注入这些环境变量:

# kubectl exec -it curl bash
root@curl:/# env | grep NGINX
NGINX_SERVICE_PORT_80_TCP_PORT=80
NGINX_SERVICE_PORT_80_TCP_PROTO=tcp
NGINX_SERVICE_SERVICE_PORT_TCP_80_80_CHJH2=80
NGINX_SERVICE_SERVICE_HOST=192.168.255.152
NGINX_SERVICE_PORT=tcp://192.168.255.152:80
NGINX_SERVICE_PORT_80_TCP=tcp://192.168.255.152:80
NGINX_SERVICE_SERVICE_PORT=80
NGINX_SERVICE_PORT_80_TCP_ADDR=192.168.255.152

  因此,在curl这个 Pod 中,可以通过访问这些环境变量,从而访问nginx-service。


另一种服务发现的方式是 DNS 解析。例如,我们进入 curl Pod 里面,可以通过 DNS 解析,访问nginx-service:

root@curl:/# curl http://nginx-service.default:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

由于nginx-service的 namespace 是default,因此它的 DNS 域名是nginx-service.default。


再说说负载均衡,我们上面创建了nginx-service,这个 Service 会自动将接收到的流量转发给它代理的两个 Nginx Pod。

外部路由

  默认情况下,通过TKE创建的应用Service 的类型是 LoadBalancer(提供公网访问)如果选仅在集群内访问TYPE将为ClusterIP

# kubectl get services nginx-service
NAME            TYPE           CLUSTER-IP        EXTERNAL-IP      PORT(S)        AGE
nginx-service   LoadBalancer   192.168.255.152   111.230.191.96   80:31437/TCP   19m
nginx           ClusterIP      192.168.255.193   <none>            80/TCP          31s

可以看到,nginx-service的 Cluster-IP(集群IP) 是192.168.255.152,这个 IP 只能从 Kubernetes 内部才能访问。当然,除了 ClusterIP 之外还有Exteranl-IP(外部IP)111.230.191.96,这个就是公网IP提供访问的,Service 还可以是其它类型:NodePort、LoadBalancer 和 ExternalName。

参考资料

Docker——容器与容器云(第2版)

Service

服务发现与负载均衡

知识点补充

Service有三种类型:

ClusterIP:默认类型,自动分配一个仅cluster内部可以访问的虚拟IP

NodePort:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过<NodeIP>:NodePort来访问该服务

LoadBalancer:在NodePort的基础上,借助cloud provider创建一个外部的负载均衡器,并将请求转发到<NodeIP>:NodePort

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏蓝天

Kafka C++客户端库librdkafka笔记

librdkafka提供的异步的生产接口,异步的消费接口和同步的消息接口,没有同步的生产接口。

4311
来自专栏从零开始的linux

安装单机hbase

安装jdk 下载hbase wget http://archive.apache.org/dist/hbase/hbase-1.0.0/hbase-1.0.0-...

4185
来自专栏云计算

如何在Ubuntu上使用Jenkins自动构建

Jenkins是一个开源自动化服务器,允许您构建管道以自动化构建,测试和部署应用程序的过程。在本指南中,您将实施基本工作流程,以加快持续集成和持续交付(CI /...

3001
来自专栏一只程序汪的自我修养

每周开源项目分享-年轻人的第一个OAuth2.0 Server:hydra

文档地址:https://www.ory.sh/docs/guides/master/hydra/

2802
来自专栏从零开始的linux

分布式文件系统 fastdfs

fastdfs FastDFS是一款开源的轻量级分布式文件系统纯C实现,支持Linux、FreeBSD等UNIX系统类google FS,不是通用的文件系统,只...

6365
来自专栏王磊的博客

Spring Boot (八)MyBatis + Docker + MongoDB 4.x

MongoDB是一个强大、灵活,且易于扩展的通用型数据库。MongoDB是C++编写的文档型数据库,有着丰富的关系型数据库的功能,并在4.0之后添加了事务支持。

1752
来自专栏拂晓风起

xp 真正解决PowerPoint 2007 无法输入中文问题(如果启动“高级文字服务”也无效,修改注册表)

1245
来自专栏坚毅的PHP

python日志按时间切分-----TimedRotatingFileHandler

原生loggging类+ TimedRotatingFileHandler类 实现按day hour second 切分 原生loggging类+ Timed...

4936
来自专栏云知识学习

TKE容器服务​创建ingress

ingress:通俗的理解是:通过7层负载均衡转发对应url到对应的path中,实现准确转发流量目的。

3162
来自专栏JadePeng的技术博客

jenkins X实践系列(1) —— 背景知识

Jenkins X 是一个高度集成化的CI/CD平台,基于Jenkins和Kubernetes实现,旨在解决微服务体系架构下的云原生应用的持续交付的问题,简化整...

7012

扫码关注云+社区

领取腾讯云代金券