lstio 快速部署与简单使用

本篇文章将会用一个例子来展示 Istio 在流量管理方面的能力
流程如下:
1、使用官方的 istioctl 以默认配置来完成 Istio 的安装;
2、使用 Deployment 将一个应用的两个版本作为测试服务部署到网格中;
3、将一个客户端服务部署到网格中进行测试;
4、为我们的目标服务编写策略文件,对目标服务的流量进行管理

环境简介:

这里给出对 Kubernetes 环境的要求:

  • Kubernetes 1.9或以上版本;
  • 具备管理权限的 kubectl 及其配置文件,能够操作测试集群;
  • Kubernetes 集群要有获取互联网镜像的能力;
  • 要支持 lstio 的自动注入功能,需要检查 Kubernetes APIServer 的启动参数,保证其中的 admissioncontrol 部分按顺序启用 MutatingAdmissionWebhookValidatingAdmissionWebhook

我这里准备了一个版本为 v1.20.11 的 Kubernetes 集群来做测试,查看版本如下:

[root@k8s-master01 istio-yaml]# kubectl version --short
Client Version: v1.20.11
Server Version: v1.20.11

快速部署 Istio

Istio 的 Github 发布地址为:https://github.com/istio/istio/releases

其中包含各个客户端平台下的 Istio 的各个版本,以在我们常用的 Linux AMD 平台下部署为例,直接下载对应的版本的 tar 包即可:

wget https://github.com/istio/istio/releases/download/1.10.1/istioctl-1.10.1-linux-amd64.tar.gz

改 tar 包中仅包含一个 istioctl 可执行文件,我们就直接将它解压到 $PATH 包含的路径下:

tar xf istioctl-1.10.1-linux-amd64.tar.gz -C /usr/local/bin/

然后就可以直接执行 istioctl 来进行安装操作,但在这之前你要检查一下你的 Kubernetes Node 中是否安装了 socat,我这里 Node 节点的系统发行版为 CentOS 7,所以直接 yum 查看即可:

yum list installed | grep socat
socat.x86_64                            1.7.3.2-2.el7                  @base

如果没有安装,则可以使用 yum 安装:

yum install socat -y

然后我们就可以执行下面命令开始在 Kubernetes 集群中注册和安装 Istio 相关组件了:

$ istioctl install
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/v1.10/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
! values.global.jwtPolicy is deprecated; use Values.global.jwtPolicy=third-party-jwt. See http://istio.io/latest/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for more information instead
This will install the Istio 1.10.1  profile with ["Istio core" "Istiod" "Ingress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed                                                                                                                                                                                                                                          
✔ Istiod installed                                                                                                                                                                                                                                              
✔ Ingress gateways installed                                                                                                                                                                                                                                    
✔ Installation complete                                                                                                                                                                                                                                         Thank you for installing Istio 1.10.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/KjkrDnMPByq7akrYA

安装完成后可以执行下面命令来验证是否执行成功:

$ istioctl verify-install
1 Istio control planes detected, checking --revision "default" only
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/v1.10/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
! values.global.jwtPolicy is deprecated; use Values.global.jwtPolicy=third-party-jwt. See http://istio.io/latest/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for more information instead
✔ ClusterRole: istiod-istio-system.istio-system checked successfully
✔ ClusterRole: istio-reader-istio-system.istio-system checked successfully
✔ ClusterRoleBinding: istio-reader-istio-system.istio-system checked successfully
✔ ClusterRoleBinding: istiod-istio-system.istio-system checked successfully
✔ Role: istiod-istio-system.istio-system checked successfully
✔ RoleBinding: istiod-istio-system.istio-system checked successfully
✔ ServiceAccount: istio-reader-service-account.istio-system checked successfully
✔ ServiceAccount: istiod-service-account.istio-system checked successfully
✔ ValidatingWebhookConfiguration: istiod-istio-system.istio-system checked successfully
✔ CustomResourceDefinition: destinationrules.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: envoyfilters.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: gateways.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: serviceentries.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: sidecars.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: virtualservices.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: workloadentries.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: workloadgroups.networking.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: authorizationpolicies.security.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: peerauthentications.security.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: requestauthentications.security.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: telemetries.telemetry.istio.io.istio-system checked successfully
✔ CustomResourceDefinition: istiooperators.install.istio.io.istio-system checked successfully
✔ HorizontalPodAutoscaler: istiod.istio-system checked successfully
✔ ConfigMap: istio.istio-system checked successfully
✔ Deployment: istiod.istio-system checked successfully
✔ ConfigMap: istio-sidecar-injector.istio-system checked successfully
✔ MutatingWebhookConfiguration: istio-sidecar-injector.istio-system checked successfully
✔ PodDisruptionBudget: istiod.istio-system checked successfully
✔ Service: istiod.istio-system checked successfully
✔ EnvoyFilter: metadata-exchange-1.10.istio-system checked successfully
✔ EnvoyFilter: tcp-metadata-exchange-1.10.istio-system checked successfully
✔ EnvoyFilter: stats-filter-1.10.istio-system checked successfully
✔ EnvoyFilter: tcp-stats-filter-1.10.istio-system checked successfully
✔ EnvoyFilter: metadata-exchange-1.9.istio-system checked successfully
✔ EnvoyFilter: tcp-metadata-exchange-1.9.istio-system checked successfully
✔ EnvoyFilter: stats-filter-1.9.istio-system checked successfully
✔ EnvoyFilter: tcp-stats-filter-1.9.istio-system checked successfully
✔ HorizontalPodAutoscaler: istio-ingressgateway.istio-system checked successfully
✔ Deployment: istio-ingressgateway.istio-system checked successfully
✔ PodDisruptionBudget: istio-ingressgateway.istio-system checked successfully
✔ Role: istio-ingressgateway-sds.istio-system checked successfully
✔ RoleBinding: istio-ingressgateway-sds.istio-system checked successfully
✔ Service: istio-ingressgateway.istio-system checked successfully
✔ ServiceAccount: istio-ingressgateway-service-account.istio-system checked successfully
Checked 13 custom resource definitions
Checked 2 Istio Deployments
✔ Istio is installed and verified successfully

安装完成后会在 Kubernetes 集群的 istio-system 命名空间下创建如下两个 Deployment 资源:

[root@k8s-master01 istio-yaml]# kubectl get deploy -n istio-system
NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
istio-ingressgateway   1/1     1            1           3h13m
istiod                 1/1     1            1           3h13m

至此我们在 Kubernetes 集群中安装 Istio 就成功啦~

部署两个版本的服务

这里将使用一个简单的提供 HTTP 服务的程序作为服务端,以及还有一个包含 curl 命令的镜像用作客户端进行测试,相关镜像已经在 Dockerhub 公开,所以下面的 manifests 都可以直接使用。

创建两个 Deployment 将其分别命名为 app-v1app-v2,同时创建一个 Service 将其命名为 app,将下面内容保存为 app-istio.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: app
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
      version: v1
  template:
    metadata:
      labels:
        app: app
        version: v1
    spec:
      containers:
      - image: dustise/flaskapp
        name: app
        env: 
        - name: version
          value: v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
      version: v2
  template:
    metadata:
      labels:
        app: app
        version: v2
    spec:
      containers:
      - image: dustise/flaskapp
        name: app
        env:
        - name: version
          value: v2

在上面的 YAML 源码中有以下需要注意的地方。

  • 两个版本的 Deployment 的镜像是一致的,但使用了不同的 version 标签进行区分,分别是 v1v2

  • 在两个版本的 Deployment 容器中都注册了一个被命名为 version 的环境变量,取值分别为 v1v2

  • 两个 Deployment 都使用了 appversion 标签,在 Istio 网格应用中通常会使用这两个标签作为应用和版本的标识;

  • Service 中的 Selector 仅使用了一个 app 标签,这意味着该 Service 对两个 Deployment 都是有效的;

  • 将在 Service 中定义的端口根据 Istio 规范命名为 http

接下来使用 istioctl 进行注入。之后会一直用到 istioctl 命令,它的基本作用就是修改 Kubernetes Deployment,在 Pod 中注入在前面提到的 Sidecar 容器,通常为了方便,我们会使用一个管道命令,在将 YAML 文件通过 istioctl 处理之后,通过命令行管道输出给 kubectl,最终提交到 Kubernetes 集群。

命令如下:

istioctl kube-inject -f app-istio.yaml | kubectl apply -f - -n 命令空间
service/app created
deployment.apps/app-v1 created
deployment.apps/app-v2 created

查看创建出来的 Pod:

[root@k8s-master01 istio-yaml]# kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
app-v1-7bcd4ffdcb-pxnjd       2/2     Running   0          88m
app-v2-5d5d4cb79c-sxlpt       2/2     Running   0          88m

可以看到,每个 Pod 都变成了两个容器,这也就是 Istio 注入 Sidecar 的结果。

查看 Pod 的容器:

[root@k8s-master01 istio-yaml]# kubectl describe pod/app-v1-7bcd4ffdcb-pxnjd |grep -i -B2 'image'
  istio-init:
    Container ID:  docker://ea57437ba11c2a7394b419a9ea87b43f33f7b2e4049e88fa777db2448cbb57ad
    Image:         docker.io/istio/proxyv2:1.9.0
    Image ID:      docker-pullable://istio/proxyv2@sha256:286b821197d7a9233d1d889119f090cd9a9394468d3a312f66ea24f6e16b2294
--
  app:
    Container ID:   docker://cd3073485c98267fa8fad40e1ab2e088aa73dfc0abc73aaaeacbf0489a1a3a41
    Image:          dustise/flaskapp
    Image ID:       docker-pullable://dustise/flaskapp@sha256:c7177273f87e42754fe8786f839abf4ef870a697c2998c7f3ba818661cf4e960
--
  istio-proxy:
    Container ID:  docker://c1ccdfa35923fe9deec7270b879544abadd65b5a7bb05f2410b0265eb036a03e
    Image:         docker.io/istio/proxyv2:1.9.0
    Image ID:      docker-pullable://istio/proxyv2@sha256:286b821197d7a9233d1d889119f090cd9a9394468d3a312f66ea24f6e16b2294

然后,我们发现在这个 Pod 中多了一个容器,名称为 istio-proxy,这就是注入的结果。另外,前面还有一个名称为 istio-init 的初始化容器,这个容器是用于初始化劫持流量的。

部署客户端服务

客户端服务很简单,只是使用了一个已安装好各种测试工具的镜像,具体的测试可以在其内部的 Shell 中完成。同样,编写一个 YAML 文件,将其命名为 test-client.yaml

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: testclient
  name: testclient
spec:
  ports:
  - name: ssh
    port: 22
    protocol: TCP
    targetPort: 22
  selector:
    app: testclient
    version: v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: testclient
  name: testclient
spec:
  replicas: 1
  selector:
    matchLabels:
      app: testclient
      version: v1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: testclient
        version: v1
    spec:
      containers:
      - image: zze326/test-tools
        command: ['init']
        name: test-tools

可能你会注意到,这个应用并没有提供对外服务的能力,我只是给它创建了一个 Service 对象,同样是 Istio 的注入要求:没有 ServiceDeployment 是无法被 Istio 发现并进行操作的。

同样,对该文件进行注入,并提交到 Kubernetes 上运行:

istioctl kube-inject -f testclient-deploy.yaml | kubectl apply -f -
service/testclient created
deployment.apps/testclient created

等待 Pod 成功进入 Running 状态:

[root@k8s-master01 istio-yaml]# kubectl get pod -lapp=testclient 
NAME                          READY   STATUS    RESTARTS   AGE
testclient-7fbb8ddf94-qfn54   2/2     Running   0          81m

可以看到 testclient 应用的 Pod 已经开始运行

验证服务

接下来,我们可以通过 kubectl exec -it 命令进入客户端 Pod,来测试 app 服务的具体表现。

使用一个简单的 for 循环,重复获取 http://flaskapp/env/version 的内容,也就是调用 app 服务,查看其返回结果:

$ kubectl exec -it testclient-7fbb8ddf94-qfn54 -- bash
Defaulting container name to test-tools.
Use 'kubectl describe pod/testclient-7fbb8ddf94-qfn54 -n default' to see all of the containers in this pod.
bash-5.1# for i in `seq 10`;do curl http://app/env/version;echo; done;
v1
v1
v2
v2
v1
v2
v1
v1
v2
v2

从上面的运行结果中可以看到,v1v2 这两种结果随机出现,大约各占一半。这很容易理解,因为我们的 app 服务的选择器被定义为只根据 app 标签进行选择,两个版本的服务 Pod 数量相同,因此会出现轮流输出的效果。

创建目标规则和路由

接下来使用 Istio 来管理这两个服务的流量。首先创建 app 应用的目标规则,输入以下内容井将其保存为 app-destinationrule.yaml

apiVersion: networking.istio.io/v1beta1
kind:  DestinationRule
metadata: 
  name: app
spec:
  host: app
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

这里定义了一个名称为 appDestinationRule,它利用 Pod 标签把 app 服务分成两个 subset,将其分别命名为 v1v2。下面将 app-destinationrule.yaml 提交到集群上:

kubectl apply -f app-destinationrule.yaml 
destinationrule.networking.istio.io/app created

接下来就需要为 app 服务创建默认的路由规则了,不论是否进行进一步的流量控制,都建议为网格中的服务创建默认的路由规则,以防发生意料之外的访问结果。

使用下面的内容创建文本文件 app-default-vs-v2.yaml

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-default-v2
spec:
  hosts: 
  - app
  http:
  - route:
    - destination:
        host: app
        subset: v2

在该文本文件中,我们定义了一个 VirtualService 对象,将其命名为 app-default-v2,它负责接管对 app 这一主机名的访问,会将所有流量都转发到 DestinationRule 定义的 v2 subset 上。

再次执行 kubectlVirtualService 提交到集群上:

kubectl apply -f app-default-vs-v2.yaml 
virtualservice.networking.istio.io/app-default-v2 created

在创建成功后,可以再次进入客户端 Pod,看看新定义的流量管理规则是否生效:

[root@k8s-master01 istio-yaml]# kubectl exec -it testclient-7fbb8ddf94-qfn54 -- bash
Defaulting container name to test-tools.
Use 'kubectl describe pod/testclient-7fbb8ddf94-qfn54 -n default' to see all of the containers in this pod.
bash-5.1# for i in `seq 10`;do curl http://app/env/version;echo;done;
v2
v2
v2
v2
v2
v2
v2
v2
v2
v2

默认的路由已经生效,现在重复多次访问,返回的内容来自环境变量 version 被设置为 v2 的版本,也就是 v2 版本

总结一下

本篇实践了一个较为典型的 Istio 服务上线流程:注入→部署→创建目标规则→创建默认路由。绝大多数 lstio 网格应用都会遵循这一流程进行上线。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容