• FAQ微服务
  • 使用Helm Chart快速部署KubeSphere微服务治理应用

KubeSphere微服务应用介绍

KubeSphere微服务使用application CRD,将相关联的资源抽象成了一个具体的应用,使用istio application功能,实现微服务流量治理、灰度发布、Tracing等功能。

如何使用KubeSphere应用

  1. deployment有app version这两个label;service有app label;且deploy与service的app label一致,等于serviceName(istio 需要)

  2. 在一个应用内,所有资源需要有这两个标签 app.kubernetes.io/name=<applicationName>, app.kubernetes.io/version=<Version>(application需要)

  3. deployment name为 service name后面加v1;如serevice 为 nginx, deployment 为 nginx-v1 (3.1修复后无需强制规定)

  4. deployment template中有相应annotation (istio sidecar自动注入需要)

  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
  1. service/deployment有相应annotation (KubeSphere crd controller 会自动将service同步为virtualservice/destinationrules,crd controller需要)
# Service
kind: Service
metadata:
  annotations:
    servicemesh.kubesphere.io/enabled: "true"
    
# Deployment
kind: Deployment
metadata:
  annotations:
    servicemesh.kubesphere.io/enabled: "true"

console界面上提供了部署istio bookinfo 应用的Demo,可以很快的部署出来一个样例。

下面将以Bookinfo为例子,如何使用Helm Chart来部署管理微服务应用。

创建Helm Chart模板

  1. 初始化helm chart模板
$ helm create sample-bookinfo
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /Users/hugo/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /Users/hugo/.kube/config
Creating sample-bookinfo

这样就创建出了helm chart的模板目录

$ tree .
.
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml
  1. 获取BookInfo yaml
kubectl -n kubesphere-system get cm sample-bookinfo -o jsonpath='{.data.bookinfo\.yaml}'  > bookinfo.yaml
  1. 将这些资源拆散后放入helm chart templates 中
$ tree .
.
├── Chart.yaml
├── README.md
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── application.yaml
│   ├── details-v1.yaml
│   ├── details.yaml
│   ├── ingress.yaml
│   ├── productpage-v1.yaml
│   ├── productpage.yaml
│   ├── ratings-v1.yaml
│   ├── ratings.yaml
│   ├── reviews-v1.yaml
│   └── reviews.yaml
└── values.yaml

在这里,我们将共性部分提取出来做为变量,如:

$ cat values.yaml

# Default values for sample-bookinfo.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

productpage:
  name: productpage
  version: v1
  image:
    repository: kubesphere/examples-bookinfo-productpage-v1:1.13.0
    pullPolicy: IfNotPresent

reviews:
  name: reviews
  version: v2
  image:
    repository: kubesphere/examples-bookinfo-reviews-v2:1.13.0
    pullPolicy: IfNotPresent

ratings:
  name: ratings
  version: v1
  image:
    repository: kubesphere/examples-bookinfo-ratings-v1:1.13.0
    pullPolicy: IfNotPresent

details:
  name: details
  version: v1
  image:
    repository: kubesphere/examples-bookinfo-details-v1:1.13.0
    pullPolicy: IfNotPresent

ingress:
  host: productpage.servicemesh.10.160.19.23.nip.io

对于所有资源公共部分,我们把它抽象成内部变量,放在_helpers.tpl中,如:

{{- define "bookinfo.chart" -}}  # 定义 bookinfo.chart变量,它的格式为:sample-bookinfo-v1
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end -}}

{{- define "common.label" -}}    # 定义 common.label变量
helm.sh/chart: {{ include "bookinfo.chart" . }}  # 引用上面定义的变量
app.kubernetes.io/managed-by: {{ .Release.Service }} 
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/name: {{ .Chart.Name }}  # 用于描述所属具体的application
app.kubernetes.io/version: {{ .Chart.Version }} # 应用的版本
{{- end -}}

在资源定义中,我们使用上面的变量

# productpage-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kubesphere.io/isElasticReplicas: 'false'
    servicemesh.kubesphere.io/enabled: 'true'
  labels:
    app: {{ .Values.productpage.name }}  # deployment需要有app version标签
    version: {{ .Values.productpage.version }}
    {{ include "common.label" . | nindent 4 }} # 内部变量
  name: {{ .Values.productpage.name }}-{{ .Values.productpage.version }}  # deployment名为servicename名加上版本号

按照这个步骤,我们已经提供了一个样例,你可以直接下载下来部署。

  1. 创建NameSpace,创建网关,并启用微服务治理

  1. 部署

部署有两种方式,将该应用上传到KubeSphere的应用中心,然后通过模版部署

5.1 上传Heml chart至应用中心

首先打包应用:

$ helm package sample-bookinfo sample-bookinfo


将应用上传到部署中心后,可以直接在应用页面通过模板部署。

5.2 使用helm安装

$ helm install sample-bookinfo sample-bookinfo
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /Users/hugo/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /Users/hugo/.kube/config
NAME: sample-bookinfo
LAST DEPLOYED: Mon Nov 23 15:37:22 2020
NAMESPACE: ns4
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Install Application Successfully.

此时已经部署完成

$ helm ls
NAME           	NAMESPACE	REVISION	UPDATED                             	STATUS  	CHART             	APP VERSION
sample-bookinfo	ns4      	1       	2020-11-23 15:37:22.025719 +0800 CST	deployed	sample-bookinfo-v1	1.16.0

页面检查所有的部署正常

也可以直接命令行直接查看应用状况

$ kubectl get app
NAME              TYPE   VERSION   OWNER   READY   AGE
sample-bookinfo                    true    9/9     2m19s

然后请求这个Ingress的url,引入流量

watch 'curl productpage.servicemesh.10.160.19.23.nip.io:31426/productpage'

此时可以看到服务治理正常:

至此,已成功使用Helm Chart包部署出了微服务应用,并已经启用微服务治理功能。

总结

如果开发者要使用helm chart,来启用KubeSphere微服务,注意以下关键步骤即可:

  1. 创建的Namespace需要启用网关Gateway及微服务治理功能,页面上手动开启。

这样的做的目的是在kubesphere-controls-system下,会创建ingress对应的controller,启用微服务治理,就是给该Pod注入sidecar,这样流量就会被打上TracingID,可以被追踪;而且KubeSphere中,只有当这个Pod被注入sidecar后,灰度发布功能才会允许操作。

$ kubectl -n kubesphere-controls-system get po kubesphere-router-ns4-6d4c9fb7fc-v9xjj
NAME                                     READY   STATUS    RESTARTS   AGE
kubesphere-router-ns4-6d4c9fb7fc-v9xjj   2/2     Running   0          158m
  1. Helm Chart中,templates/deployment需要在template中手动打上annotation,如:
$ cat helm-charts/sample-bookinfo/templates/productpage-v1.yaml
...
  template:
      annotations:
        sidecar.istio.io/inject: 'true'
  1. 资源的Labels需要同时满足application及istio的要求,如:
$cat helm-charts/sample-bookinfo/template/productpage.yaml
...
metadata:
  labels:
    app: {{ .Values.productpage.name }}
    {{ include "common.label" . | nindent 4 }}
  1. 关于ingress需要注意的地方

如果Ingress中没有upstream的annotation,第一个应用会没有流量图,需要手动加上annotation,如:

$ kubectl get ingress -n ns4
NAME               CLASS    HOSTS                                         ADDRESS        PORTS   AGE
bookinfo-ingress   <none>   productpage.servicemesh.10.160.19.23.nip.io   10.160.19.23   80      40m

找到对应的ingress后,加上upstream anntation后,由于Nginx采用lua模块,会动态加载配置(nginx reload)。

# 注意替换成您自己的Namespace
kubectl -n ns4 annotate ingress bookinfo-ingress nginx.ingress.kubernetes.io/upstream-vhost=productpage.ns4.svc.cluster.local  

最后,如果你要使用自己的资源,你可以使用上面示例中的helm chart来对照改。示例中的关键变量理解清楚的基础上,再抽象出自己环境的变量即可。

扩展 :部署在线购物网站 online boutique微服务

参考:kubesphere/helm-charts#140/files

界面:

部署也很简单,把这个helm chart下载到本地后,helm install 就能安装成功。

helm install online-boutique online-boutique

程序内部会有个loadgenerator的工作负载,会一直请求frontend页面。

如果是自己的访问网站,可以直接访问frontend service。

    不错。最好把如何改造 helm chart 使其支持 KubeSphere ServiceMesh 写得更详细;或者给出在 KubeSphere 上使用 Chart 对接流量治理的规范,让这个规范给开发者提供通用的参考价值

    3 个月 后

    感谢大佬,强烈建议大佬将这篇文章放到文档中去,找了好几个小时才找到~

    6 天 后
    7 个月 后


    构建的自制应用使用金丝雀发布,不管怎么调节流量比例,依旧是 50:50,用示例应用却没问题。
    zackzhang 大佬可以提示下排查范围吗