Kubernetes

Kubernetes Service Catalog 机制

Einic Yeo · 1月20日 · 2020年 · · ·

一、概念

Service Catalog (服务目录)是Kubernetes社区的孵化项目Kubernetes Service Catalog Project,旨在接入和管理第三方提供的Service Broker,使kubernetes上托管的应用可以使用service broker所代理的外部服务。第三方服务可以是云服务商提供的服务,例如版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!数据库,消息队列等等,但不局限于此。

通过服务目录,kubernetes用户可以直接使用第三方服务,而不需要再到云上进行操作。对于企业来说,通过服务目录可以更好的管理对第三方资源的使用。

二、架构设计

Service Catalog 项目主要的工作是,将kubernetes资源翻译为对Service Broker的OSB API调用,基于此,kubernetes的用户可以通过创建kubernetes资源的方式来使用外部服务。

它有如下几个特性:

  • 服务目录用户可以向kubernetes注册serice broker
  • 服务目录可以从服务目录获取服务和服务计划(即catalog),并提供给kubernetes的用户
  • kubernetes用户向服务目录请求一个ServiceInstance资源,从而向broker请求一个服务实例
  • kubernetes用户通过创建ServiceBinding资源,将应用与服务绑定

Service Catalog 的架构和kubernetes的架构类似,也是分为API Server和controller;其中API Server接收RESTful请求,写入etcd;而Controller监听资源,并执行实际的工作:通过OSB API调用Service Broker的服务。Service Catalog 目前是通过Aggregated API的方式,将自身的API作为API 扩展注册到了kubernetes API server。值得注意的是,Service Catalog项目计划改为基于CRD来实现。

三、应用架构

Service Catalog在kubernetes架构中的位置如下图。

四、API资源

Service Catalog通过API Server对用户暴露如下API(servicecatalog.k8s.io)资源:

资源说明
ClusterServiceBrokerService Broker在集群内部的表示,封装了该服务的连接细节
ClusterServiceClass某个 Service Broker 所管理的一种外部服务,当ClusterServiceBroker创建后,Service Catalog控制器会自动从 Service Broker 获取可用的受管服务列表,并为每个受管服务创建一个ClusterServiceClass对象(服务类型如:mysql、redis)
ClusterServicePlanClusterServiceClass的一种具体的变体,受管服务可以有不同的“计划”,例如资源规格套餐(内存、CPU、磁盘):免费版、付费版,或者高速版、低速版类似于ClusterServiceClass,当ClusterServiceBroker创建后,Service Catalog控制器也会自动创建ClusterServicePlan对象
ServiceInstance一个实际Provision的ClusterServiceClass的实例,此对象创建后,SC控制器会连接到对应的Service Broker,并指示Service Broker 提供对应的服务实例(具体服务实例如:mysql)
ServiceBinding包含访问ServiceInstance所需的凭证。如果你的集群内应用需要访问外部服务实例,则需要创建该对象ServiceBinding创建之后,SC控制器会创建包含目标服务实例的连接信息、访问凭证的Secret。此Secret应当被挂载到需要使用服务的Pod(例如:mysql的用户名、密码、IP地址、端口号)

五、部署Service Catalog

参考官网,使用helm可以很方便的部署。

部署后会在namespace catalog 下创建 catalog-catalog-apiserver 和 catalog-catalog-controller-manager两个Deployment,其中catalog-apiserver会向kubernetes apiserver注册如下api:

NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
clusterservicebrokers                          servicecatalog.k8s.io          false        ClusterServiceBroker
clusterserviceclasses                          servicecatalog.k8s.io          false        ClusterServiceClass
clusterserviceplans                            servicecatalog.k8s.io          false        ClusterServicePlan
servicebindings                                servicecatalog.k8s.io          true         ServiceBinding
servicebrokers                                 servicecatalog.k8s.io          true         ServiceBroker
serviceclasses                                 servicecatalog.k8s.io          true         ServiceClass
serviceinstances                               servicecatalog.k8s.io          true         ServiceInstance
serviceplans                                   servicecatalog.k8s.io          true         ServicePlan

kubernetes管理员通过clusterservicebrokers / clusterserviceclasses / clusterserviceplans注册第三方Service Broker服务;kubernetes用户通过serviceinstances / servicebindings 的api向k8s请求、使用第三方服务。

六、部署service broker

6.1、实战一

kubernetes社区提供了一个service broker的demo,叫做minibroker,这个项目管理了一些helm charts,例如mysql,redis;例如,当service catalog通过OSB API向minibroker请求创建新的mysql实例时,minibroker其实是通过helm部署了一个mysql。

当然,minibroker实现了OSB API。

minibrok版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!er本身通过helm部署。

helm repo add minibroker https://minibroker.blob.core.windows.net/charts
helm install --name minibroker --namespace minibroker minibroker/minibroker

部署后,会在namespace minibroker里创建Deployment minibroker controller。helm部署时还会向kubernetes创建如下资源:

一个clusterservicebrokers,用来将OSB API请求转发给实际的b版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!roker服务(即minibroer controller):

$ kubectl get clusterservicebrokers.servicecatalog.k8s.io
NAME         URL                                                         STATUS   AGE
minibroker   http://minibroker-minibroker.minibroker.svc.cluster.local   Ready    2d

以及注册如下几个 clusterserviceclasses:

$ kubectl get clusterserviceclasses
NAME         EXTERNAL-NAME   BROKER       AGE
mariadb      mariadb         minibroker   5m50s
mongodb      mongodb         minibroker   5m50s
mysql        mysql           minibroker   5m50s
postgresql   postgresql      minibroker   5m50s
redis        redis           minibroker   5m50s

以及若干clusterserviceplans:

$ kubectl get clusterserviceplans.servicecatalog.k8s.io
NAME                       EXTERNAL-NAME      BROKER       CLASS        AGE
mariadb-10-1-26            10-1-26            minibroker   mariadb      47h
mariadb-10-1-28            10-1-28            minibroker   mariadb      47h
mariadb-10-1-29            10-1-29            minibroker   mariadb      47h

先创建namespace test-ns,假设用户是在test-ns里。

创建一个服务实例

$ kubectl create -f https://raw.githubusercontent.com/kubernetes-sigs/service-catalog/master/contrib/examples/walkthrough/mini-instance.yaml
$ kubectl get serviceinstances.servicecatalog.k8s.io -n test-ns
NAME            CLASS                         PLAN      STATUS   AGE
mini-instance   ClusterServiceClass/mariadb   10-1-26   Ready    3d3h
$ kubectl get pods -n test-ns
NAME                                     READY   STATUS    RESTARTS   AGE
virulent-camel-mariadb-d65d9dfb4-5bp4v   1/1     Running   0          3d3h

可以看到service catalog+minibroker会在用户的namespace test-ns下创建一个mariadb的Deployment,使用的也是用户自己的资源。相对用户直接helm install,service catalog更方便一些。

绑定服务实例

$ kubectl create -f https://raw.githubusercontent.com/kubernetes-sigs/service-catalog/master/contrib/examples/walkthrough/mini-binding.yaml
$ kubectl get servicebindings.servicecatalog.k8s.io -n test-ns
NAME           SERVICE-INSTANCE   SECRET-NAME    STATUS   AGE
mini-binding   mini-instance      mini-binding   Ready    3d3h
$ svcat describe binding mini-binding
  Name:        mini-binding
  Namespace:   test-ns
  Status:      Ready - Injected bind result @ 2020-01-20 10:03:33 +0000 UTC
  Secret:      mini-binding
  Instance:    mini-instance

Parameters:
  No parameters defined

Secret Data:
  Protocol                5 bytes
  host                    48 bytes
  mariadb-password        10 bytes
  mariadb-root-password   10 bytes
  password                10 bytes
  port                    4 bytes
  uri                     77 bytes
  username                4 bytes
$ kubectl get secrets mini-binding -o yaml -n test-ns
apiVersion: v1
data:
  Protocol: bX=====
  host: dmlydW=====================================s
  mariadb-password: a0d==========
  mariadb-root-password: W==========
  password: WD========
  port: MzMwNg==
  uri: bXl=================================================Y=
  username: cm9vdA==

binding是什么意思呢?其实就是把访问服务的一些信息,通过secret提供给用户。

比如对于mariadb来说,其信息包括uri,port,用户名密码等等信息,用户可以通过这些信息来使用mar版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!iadb服务(例如将secret以volume的形式挂到Pod里)。

...
          env:
          - name: "PASSWORD"
            valueFrom:
                secretKeyRef:
                   name: mini-binding
                   key: password
版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!

6.2、实战二

可以通过Helm来部署示例项目,以体验如何K8S集群中提供、绑定外部服务。

helm install --name=broker-skeleton --namespace=kube-system charts/servicebroker

当你部署了此示例项目,也就是创建了clusterservicebrokers.servicecatalog.k8s.io之后,Service Catalog会自动:

  1. 调用SB的ValidateBrokerAPIVersion接口确认SB支持API版本
  2. 调用SB的GetCatalog接口获取服务目录,创建clusterserviceclasses、clusterserviceplans对象
  3. 根据配置,前两个步骤可能周期性执行

ClusterServiceBroker

如果一切顺利,应该会创建出ClusterServiceBroker对象broker-skeleton:

apiVersion: servicecatalog.k8s.io/v1beta1
kind: ClusterServiceBroker
metadata:
  finalizers:
  - kubernetes-incubator/service-catalog
  labels:
    app: broker-skeleton
    chart: broker-skeleton--0.0.1
    heritage: Tiller
    release: broker-skeleton
  name: broker-skeleton
spec:
  # SC访问SB时,如何进行身份验证
  authInfo:
    # 支持basic、bearer两种身份验证方式
    bearer:
      secretRef:
        name: broker-skeleton
        namespace: kube-system
  # 是否禁用对SB服务器证书有效性的验证
  insecureSkipTLSVerify: true
  # 如何重新获取SB提供的ServiceClass列表
  # Duration 定期
  # Manual 仅当此对象的Spec变更才触发一次
  relistBehavior: Duration
  # 用户可以手工增加此字段,来触发relist
  relistRequests: 0
  # ServiceBroker的监听地址
  url: http://10.0.0.1:8001
  # 访问SB时,校验其服务器端证书的CA证书
  caBundle: PEM encoded CA bundle which will be used to validate a Broker's serving certificate
status:
  conditions:
  - lastTransitionTime: 2020-01-20T12:43:12Z
    message: Successfully fetched catalog entries from broker.
    reason: FetchedCatalog
    status: "True"
    type: Ready
  lastCatalogRetrievalTime: 2020-01-20T12:43:12Z
  reconciledGeneration: 3

ClusterServiceClass

并且随后生成一个ClusterServiceClass对象:

apiVersion: servicecatalog.k8s.io/v1beta1
kind: ClusterServiceClass
metadata:
  name: 4f6e6cf6-ffdd-425f-a2c7-3c9258ad246a
  # 所属的SB
  ownerReferences:
  - apiVersion: servicecatalog.k8s.io/v1beta1
    blockOwnerDeletion: false
    controller: true
    kind: ClusterServiceBroker
    name: broker-skeleton
spec:
  # 用户是否可以Bind到从此ClusterServiceClass提供的ServiceInstance
  bindable: true
  # 不可变的,所属的SB名称
  clusterServiceBrokerName: broker-skeleton
  description: The example service from the osb starter pack!
  # 不可变的,OSB API使用的ID
  externalID: 4f6e6cf6-ffdd-425f-a2c7-3c9258ad246a
  externalMetadata:
    displayName: Example starter pack service
    imageUrl: https://avatars2.githubusercontent.com/u/19862012?s=200&v=4
  # SB对外暴露此ClusterServiceClass的名称
  externalName: example-starter-pack-service
  # 是否允许在ServiceInstance创建之后,修改ServicePlan
  planUpdatable: true
status:
  removedFromBrokerCatalog: false

ClusterServicePlan

以及一个ClusterServicePlan对象:

apiVersion: servicecatalog.k8s.io/v1beta1
kind: ClusterServicePlan
metadata:
  name: 86064792-7ea2-467b-af93-ac9694d96d5b
  # 所属的SB
  ownerReferences:
  - apiVersion: servicecatalog.k8s.io/v1beta1
    blockOwnerDeletion: false
    controller: true
    kind: ClusterServiceBroker
    name: broker-skeleton
    uid: dc7e6ac0-91c5-11e9-b33b-0697b7c57666
spec:
  # 不可变的,所属的SB名称
  clusterServiceBrokerName: broker-skeleton
  # 所属的ClusterServiceClass
  clusterServiceClassRef:
    name: 4f6e6cf6-ffdd-425f-a2c7-3c9258ad246a
  description: The default plan for the starter pack example service
  externalID: 86064792-7ea2-467b-af93-ac9694d96d5b
  externalName: default
  # 提示此计划是否不需要付费
  free: true
  # *runtime.RawExtension
  # 创建此SP的实例时,可以提供的参数
  instanceCreateParameterSchema:
    properties:
      color:
        default: Clear
        enum:
        - Clear
        - Beige
        - Grey
        type: string
    type: object
status:
  removedFromBrokerCatalog: false

ServiceInstance

当你创建一个ServiceInstance之后,Service Catalog会自动:

  1. 调用SB的Provision接口,进行服务的Provisioning
  2. 更新ServiceInstance.Status字段

# kubectl get serviceinstances.servicecatalog.k8s.io example-instance -o yaml
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
  finalizers:
  - kubernetes-incubator/service-catalog
  name: example-instance
  namespace: default
spec:
  # 所属的ServiceClass和ServicePlan
  clusterServiceClassExternalName: example-starter-pack-service
  clusterServiceClassRef:
    name: 4f6e6cf6-ffdd-425f-a2c7-3c9258ad246a
  clusterServicePlanExternalName: default
  clusterServicePlanRef:
    name: 86064792-7ea2-467b-af93-ac9694d96d5b
  externalID: 37b83e95-9271-11e9-b33b-0697b7c57666
  # 发起Provision请求时提供的参数
  parameters:
    color: Clear
  updateRequests: 0
  # 最后修改此对象的用户的信息
  userInfo:
    groups:
    - system:serviceaccounts
    - system:serviceaccounts:kube-system
    - system:authenticated
    uid: ""
    username: system:serviceaccount:kube-system:admin
status:
  # 如果当前正有一个针对此实例的异步操作在进行中,设置为true
  asyncOpInProgress: false
  conditions:
  # 状态转换历史记录
  - lastTransitionTime: 2020-01-20T09:18:38Z
    message: The instance was provisioned successfully
    reason: ProvisionedSuccessfully
    status: "True"
    type: Ready
  - lastTransitionTime: 2020-01-20T09:05:19Z
    message: "Communication with the ClusterServiceBroker timed out; operation will  be retried ... "
    reason: ErrorCallingProvision
    status: "True"
    type: OrphanMitigation
  # 当前正在此实例上进行的操作
  currentOperation: Provision
  deprovisionStatus: Required
  inProgressProperties:
    clusterServicePlanExternalID: 86064792-7ea2-467b-af93-ac9694d96d5b
    clusterServicePlanExternalName: default
    parameterChecksum: 5e69f3b690c6b40999c37fda091459d89d48f6c51ce176a99d7c38010209d140
    parameters:
      color: Clear
    userInfo:
      groups:
      - system:serviceaccounts
      - system:serviceaccounts:kube-system
      - system:authenticated
      uid: ""
      username: system:serviceaccount:kube-system:admin
  observedGeneration: 1
  operationStartTime: 2020-01-20T09:04:19Z
  orphanMitigationInProgress: true
  provisionStatus: ""
  reconciledGeneration: 0

ServiceBinding

当你创建一个ServiceBinding之后,Service Catalog会自动:

  1. 调用SB的Bind接口,进行服务绑定操作,获得访问服务实例所需要的凭证等信息
  2. 将凭证信息保存到ServiceBinding指定的Secrets中

应用程序通过挂载上述Secret即可获取访问服务示例的凭证信息。

当你删除一个ServiceBinding之后,Service Catalog会自动:

  1. 调用SB的Unbind接口

# kubectl get servicebindings.servicecatalog.k8s.io example-instance-binding -o yaml
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
  finalizers:
  - kubernetes-incubator/service-catalog
  name: example-instance-binding
  namespace: default
spec:
  externalID: 4023295f-9278-11e9-b33b-0697b7c57666
  instanceRef:
    name: example-instance
  # 传递给SB的绑定参数
  parameters: {}
  # 当前命名空间中,存放此Binding的凭证信息的保密字典
  secretName: example-instance-binding
  # 最后一次修改此绑定对象的用户信息
  userInfo:
    groups:
    - system:serviceaccounts
    - system:serviceaccounts:kube-system
    - system:authenticated
    uid: ""
    username: system:serviceaccount:kube-system:admin
status:
  asyncOpInProgress: false
  conditions:
  # 状态转换历史记录
  - lastTransitionTime: 2020-01-20T09:54:38Z
    # 这个是正常状态
    message: Injected bind result
    reason: InjectedBindResult
    status: "True"
    type: Ready
  externalProperties:
    userInfo:
      groups:
      - system:serviceaccounts
      - system:serviceaccounts:kube-system
      - system:authenticated
      uid: ""
      username: system:serviceaccount:kube-system:admin
  orphanMitigationInProgress: false
  reconciledGeneration: 1
  unbindStatus: Required

参考文献

0 条回应