pipelinse and istio

This commit is contained in:
estom
2024-05-13 14:36:51 +08:00
parent da5e956d1e
commit decafa208b
29 changed files with 1932 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
kubectl port-forward 允许使用资源名称 (例如 Pod 名称)来选择匹配的 Pod 来进行端口转发
# 将 mongo-75f59d57f4-4nd6q 改为 Pod 的名称
kubectl port-forward mongo-75f59d57f4-4nd6q 28015:27017
这相当于
kubectl port-forward pods/mongo-75f59d57f4-4nd6q 28015:27017
或者
kubectl port-forward deployment/mongo 28015:27017
或者
kubectl port-forward replicaset/mongo-75f59d57f4 28015:27017
或者
kubectl port-forward service/mongo 28015:27017
以上所有命令都有效。输出类似于:
Forwarding from 127.0.0.1:28015 -> 27017
Forwarding from [::1]:28015 -> 27017
与本地 28015 端口建立的连接将被转发到运行 MongoDB 服务器的 Pod 的 27017 端口。 通过此连接,你可以使用本地工作站来调试在 Pod 中运行的数据库。
kubectl port-forward 仅实现了 TCP 端口 支持。 在 issue 47862 中跟踪了对 UDP 协议的支持。

326
kubenets/12 RBAC鉴权.md Normal file
View File

@@ -0,0 +1,326 @@
## 鉴权说明
### 简介
启用RBAC需要在 apiserver 中添加参数--authorization-mode=RBAC
API Server目前支持以下几种授权策略
* AlwaysDeny表示拒绝所有请求一般用于测试。
* AlwaysAllow允许接收所有请求。
* 如果集群不需要授权流程则可以采用该策略这也是Kubernetes的默认配置。
* ABACAttribute-Based Access Control基于属性的访问控制。
* 表示使用用户配置的授权规则对用户请求进行匹配和控制。
* Webhook通过调用外部REST服务对用户进行授权。
* RBACRole-Based Access Control基于角色的访问控制本章讲解
* Node是一种专用模式用于对kubelet发出的请求进行访问控制。
### 概念
K8s的用户分两种一种是普通用户一种是ServiceAccount服务账户
普通用户
普通用户是假定被外部或独立服务管理的。管理员分配私钥。平时常用的kubectl命令都是普通用户执行的。
如果是用户需求权限则将Role与User(或Group)绑定(这需要创建User/Group),是给用户使用的。
ServiceAccount服务账户
ServiceAccount服务帐户是由Kubernetes API管理的用户。它们绑定到特定的命名空间并由API服务器自动创建或通过API调用手动创建。服务帐户与存储为Secrets的一组证书相关联这些凭据被挂载到pod中以便集群进程与Kubernetes API通信。
如果是程序需求权限将Role与ServiceAccount指定(这需要创建ServiceAccount并且在deployment中指定ServiceAccount),是给程序使用的。
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/153b25a1b8eb42d08aec5f2dd4dec54e~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp)
## 操作步骤
### 步骤
在RABC API中通过如下的步骤进行授权
1. **定义角色** :在定义角色时会指定此角色对于资源的访问控制的规则。
2. **绑定角色** :将主体与角色进行绑定,对用户进行访问授权。
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23d5ec88321243e1b7546d6736736fd3~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp)
**角色**
* Role授权特定命名空间的访问权限
* ClusterRole授权所有命名空间的访问权限
**角色绑定**
* RoleBinding将角色绑定到主体即subject
* ClusterRoleBinding将集群角色绑定到主体
**主体subject**
* User用户
* Group用户组
* ServiceAccount服务账号
### 核心资源
#### Role
1. Role关联资源、操作的权限
```
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-role
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
```
2. clusterRole关联集群资源的资源、操作权限
```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-clusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
```
常用的资源类型有
```
"services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"
```
常用的操作语义有
```
"get", "list", "watch", "create", "update", "patch", "delete", "exec"
```
#### 角色绑定
RoleBinding
```
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rb
namespace: default
subjects:
- kind: ServiceAccount
name: zhangsan
namespace: default
roleRef:
kind: Role
name: pod-role
apiGroup: rbac.authorization.k8s.io
```
ClusterRoleBinding
```
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: crb
subjects:
- kind: ServiceAccount
name: mark
namespace: default
roleRef:
kind: ClusterRole
name: pod-clusterrole
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: mark
namespace: default
```
### User&Group
```
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: dev
name: devuser-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding 绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: devuser-rolebinding
namespace: dev
subjects:
- kind: User
name: devuser
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: devuser-role
apiGroup: rbac.authorization.k8s.io
```
## 3 具体实例
### 创建用户
1. 创建k8s用户首先使用ssl生成本地证书的私钥*.key和整数签名请求*.csr
```
# 创建私钥
$ openssl genrsa -out devuser.key 2048
# 用此私钥创建一个csr(证书签名请求)文件
$ openssl req -new -key devuser.key -subj "/CN=devuser" -out devuser.csr
```
2. 然后使用k8s的证书ca.crt和私钥ca.key对客户端的证书签名请求*.csr进行签名颁发客户端证书*.crt
```
# 拿着私钥和请求文件生成证书
$ openssl x509 -req -in devuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out devuser.crt -days 365
```
3. 生成账号
```
$ kubectl config set-credentials devuser --client-certificate=./devuser.crt --client-key=./devuser.key --embed-certs=true
```
4. 设置用户的上下文参数
```
# # 设置上下文, 默认会保存在 $HOME/.kube/config
$ kubectl config set-context devuser@kubernetes --cluster=kubernetes --user=devuser --namespace=dev
# 查看
$ kubectl config get-contexts
```
5. 切换用户上下文。可以看到新建的用户还没有授权访问nodes资源鉴权失败。
```
$ kubectl config use-context devuser@kubernetes
# 查看
$ kubectl config get-contexts
$ kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "devuser" cannot list resource "nodes" in API group "" at the cluster scope
```
#### 对用户授权
1. 接下来就是对账号进行授权。这里需要先把用切回来,要不然就无法进行下一步授权了。
```
$ kubectl config use-context kubernetes-admin@kubernetes
$ kubectl get nodes
```
2. 部署下列文件。创建一个角色devuser-role具有dev命名空间的pods的所有权限。并绑定devuser用户。
```
kind: Role # 角色
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: dev
name: devuser-role
rules:
- apiGroups: [""] # ""代表核心api组
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding # 角色绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: devuser-rolebinding
namespace: dev
subjects:
- kind: User
name: devuser # 目标用户
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: devuser-role # 角色信息
apiGroup: rbac.authorization.k8s.io
```
3. 进行验证。用devuser已经可以管理dev命名空间下的pod资源了也只能管理dev命名空间下的pod资源无法管理dev以外的资源类型验证ok。ClusterRoleBinding绑定类似这里就不重复了。有兴趣的小伙伴可以试试。
```
$ kubectl apply -f devuser-role-bind
$ kubectl config use-context devuser@kubernetes
$ kubectl get pods # 不带命名空间这里默认dev也只能查看dev上面限制的命名空间的pods资源从而也验证了role是针对命名空间的权限限制
#查看其它命名空间的资源
$ kubectl get pods -n default
$ kubectl get pods -n kube-system
$ kubectl get nodes
```
#### 为ServiceAccount授权
1. 创建serviceAccount并绑定到ClusterRole
```
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: sa001
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa001
namespace: kube-system
```
2. 创建授权后就可以通过k8s的serviceAccount的token访问集群了。
```
$ kubectl -n kube-system get secret|grep sa001
$ kubectl -n kube-system describe secret sa001-token-c2klg
# 也可以使用 jsonpath 的方式直接获取 token 的值,如:
$ kubectl -n kube-system get secret sa001-token-c2klg -o jsonpath={.data.token}|base64 -d
```
## 总结
**RoleBinding 和 ClusterRoleBinding** :角色绑定和集群角色绑定,简单来说就是把声明的 Subject 和我们的 Role 进行绑定的过程(给某个用户绑定上操作的权限)二者的区别也是作用范围的区别RoleBinding 只会影响到当前namespace 下面的资源操作权限,而 ClusterRoleBinding 会影响到所有的namespace。
* **Rule** :规则,规则是一组属于不同 API Group 资源上的一组操作的集合
* **Role 和 ClusterRole** :角色和集群角色,这两个对象都包含上面的 Rules 元素,二者的区别在于,在 Role 中定义的规则只适用于单个命名空间也就是和namespace 关联的,而 ClusterRole 是集群范围内的,因此定义的规则不受命名空间的约束。另外 Role 和 ClusterRole 在Kubernetes中都被定义为集群内部的 API 资源,和我们前面学习过的 Pod、ConfigMap 这些类似都是我们集群的资源对象所以同样的可以使用我们前面的kubectl相关的命令来进行操作
* **Subject** 主题对应在集群中尝试操作的对象集群中定义了3种类型的主题资源
1. **User** :用户,这是有外部独立服务进行管理的,管理员进行私钥的分配,用户可以使用 KeyStone或者 Goolge 帐号,甚至一个用户名和密码的文件列表也可以。对于用户的管理集群内部没有一个关联的资源对象,所以用户不能通过集群内部的 API 来进行管理
2. **Group** 这是用来关联多个账户的集群中有一些默认创建的组比如cluster-admin
3. **ServiceAccount** 服务帐号通过Kubernetes API 来管理的一些用户帐号和namespace 进行关联的,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到 ServiceAccount这也是我们这节课的重点

View File

@@ -0,0 +1,244 @@
## 1 简介
### 服务网格
如果用一句话来解释什么是服务网格,可以将它比作是应用程序或者说微服务间的 TCP/IP负责服务之间的网络调用、限流、熔断和监控。对于编写应用程序来说一般无须关心 TCP/IP 这一层(比如通过 HTTP 协议的 RESTful 应用),同样使用服务网格也就无须关系服务之间的那些原来是通过应用程序或者其他框架实现的事情,比如 Spring Cloud、OSS现在只要交给服务网格就可以了。
服务网格中分为控制平面和数据平面,当前流行的两款开源的服务网格 Istio 和 Linkerd 实际上都是这种构造,只不过 Istio 的划分更清晰,而且部署更零散,很多组件都被拆分,控制平面中包括 MixerIstio 1.5 之前版本、Pilot、Citadel数据平面默认是用 Envoy而 Linkerd 中只分为 Linkerd 做数据平面namerd 作为控制平面。
控制平面的特点:
* 不直接解析数据包
* 与控制平面中的代理通信,下发策略和配置
* 负责网络行为的可视化
* 通常提供 API 或者命令行工具可用于配置版本化管理,便于持续集成和部署
数据平面的特点:
* 通常是按照无状态目标设计的,但实际上为了提高流量转发性能,需要缓存一些数据,因此无状态也是有争议的
* 直接处理入站和出站数据包,转发、路由、健康检查、负载均衡、认证、鉴权、产生监控数据等
* 对应用来说透明,即可以做到无感知部署
![1714031946432](image/01Istio快速开始/1714031946432.png)
服务网格是七层网络架构中的第五层
![1714032043713](image/01Istio快速开始/1714032043713.png)
### Istio
实际上Istio 就是 Service Mesh 架构的一种实现,服务之间的通信(比如这里的 Service A 访问 Service B会通过代理默认是 Envoy来进行。将微服务下沉到了云原生的层面。
> 发现上层应用的一系列技术都在向云原生的方式靠拢即k8s定义的一套部署运维机制。曾经服务的发布和订阅还是通过专门的中间件注册中心来实现的现在k8s提供了云原生的方式进行服务的发布和订阅。服务治理曾经是中间件的能力现在也下沉到了云原生的方式通过istio来实现容器切面进行服务治理
控制平面做了进一步的细分,分成了 Pilot、Citadel 和 Galley它们的各自功能如下
* Pilot为 Envoy 提供了服务发现流量管理和智能路由AB 测试、金丝雀发布等),以及错误处理(超时、重试、熔断)功能。
* Citadel为服务之间提供认证和证书管理可以让服务自动升级成 TLS 协议。
* GalleyGalley 是 Istio 的配置验证、提取、处理和分发组件。它负责将其余的 Istio 组件与从底层平台(例如 Kubernetes获取用户配置的细节隔离开来。
![file](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ee749e401dc44627af29d8d9d339e133~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp)
### 优势
通过负载均衡、服务间的身份验证、监控等方法Istio 可以轻松地创建一个已经部署了服务的网络,而服务的代码只需很少更改甚至无需更改。通过在整个环境中部署一个特殊的 sidecar 代理为服务添加 Istio 的支持,而代理会拦截微服务之间的所有网络通信,然后使用其控制平面的功能来配置和管理 Istio这包括
* 为 HTTP、gRPC、WebSocket 和 TCP 流量自动负载均衡。
* 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制。
* 可插拔的策略层和配置 API支持访问控制、速率限制和配额。
* 集群内(包括集群的入口和出口)所有流量的自动化度量、日志记录和追踪。
* 在具有强大的基于身份验证和授权的集群中实现安全的服务间通信。
### 能力
![1714028930185](image/04Istio/1714028930185.png)
#### 流量管理
Istio 简单的规则配置和流量路由允许您控制服务之间的流量和 API 调用过程。
Istio 简化了服务级属性(如熔断器、超时和重试)的配置,并且让它轻而易举的执行重要的任务(如 A/B 测试、金丝雀发布和按流量百分比划分的分阶段发布)。
有了更好的对流量的可视性和开箱即用的故障恢复特性,就可以在问题产生之前捕获它们,无论面对什么情况都可以使调用更可靠,网络更健壮。
#### 安全
Istio 的安全特性解放了开发人员,使其只需要专注于应用程序级别的安全。
Istio 提供了底层的安全通信通道,并为大规模的服务通信管理认证、授权和加密。有了 Istio服务通信在默认情况下就是受保护的可以让您在跨不同协议和运行时的情况下实施一致的策略——而所有这些都只需要很少甚至不需要修改应用程序。
Istio 是独立于平台的,可以与 Kubernetes或基础设施的网络策略一起使用。但它更强大能够在网络和应用层面保护pod到 pod 或者服务到服务之间的通信。
#### 可观察性
Istio 健壮的追踪、监控和日志特性让您能够深入的了解服务网格部署。
通过 Istio 的监控能力,可以真正的了解到服务的性能是如何影响上游和下游的;而它的定制 Dashboard 提供了对所有服务性能的可视化能力,并让您看到它如何影响其他进程。
Istio 的 Mixer 组件负责策略控制和遥测数据收集。它提供了后端抽象和中介,将一部分 Istio 与后端的基础设施实现细节隔离开来,并为运维人员提供了对网格与后端基础实施之间交互的细粒度控制。
所有这些特性都使您能够更有效地设置、监控和加强服务的 SLO。当然底线是您可以快速有效地检测到并修复出现的问题。
## 2 最佳实践
### 应用需要改造
服务通信和治理相关的功能迁移到 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 进程中后, 应用中的 SDK 通常需要作出一些对应的改变。
比如 SDK 需要关闭一些功能例如重试。一个典型的场景是SDK 重试 m 次,[sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 重试 n 次,这会导致 m * n 的重试风暴,从而引发风险。
此外,诸如 trace header 的透传,也需要 SDK 进行升级改造。如果你的 SDK 中还有其它特殊逻辑和功能,这些可能都需要小心处理才能和 Isito [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 完美配合。
## 只有 HTTP 协议是一等公民
> 这也是Istio在落地过程中一个重要的改造点。将企业内部的私有通信协议适配到自身的sidecar上。
Istio 原生对 HTTP 协议提供了完善的全功能支持,但在真实的业务场景中,私有化协议却非常普遍,而 Istio 却并未提供原生支持。
这导致使用私有协议的一些服务可能只能被迫使用 TCP 协议来进行基本的请求路由,这会导致很多功能的缺失,这其中包括 Istio 非常强大的基于内容的消息路由,如基于 header、 path 等进行权重路由。
## Istio 在集群规模较大时的性能问题
> 这一世istio的优势之一不依赖单独集中式的注册中心而是从k8s的etcd注册中心订阅全量的服务。而不是等待访问发生时进行订阅和路由。
Istio 默认的工作模式下,每个 [sidecar]() 都会收到全集群所有服务的信息。如果你部署过 Istio 官方的 Bookinfo 示例应用,并使用 Envoy 的 config dump 接口进行观察你会发现仅仅几个服务Envoy 所收到的配置信息就有将近 20w 行。
可以想象在稍大一些的集群规模Envoy 的内存开销、Istio 的 CPU 开销、XDS 的下发时效性等问题,一定会变得尤为突出。
Istio 这么做一是考虑这样可以开箱即用,用户不用进行过多的配置,另外在一些场景,可能也无法梳理出准确的服务之间的调用关系,因此直接给每个 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 下发了全量的服务配置,即使这个 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 只会访问其中很小一部分服务。
当然这个问题也有解法,你可以通过 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") [CRD](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#crd "CRD全称 Custom Resource Definition自定义资源定义是默认的 Kubernetes API 扩展。") 来显示定义服务调用关系,使 Envoy 只得到他需要的服务信息,从而大幅降低 Envoy 的资源开销,但前提是在你的业务线中能梳理出这些调用关系。
## XDS 分发没有分级发布机制
当你对一个服务的策略配置进行变更的时候XDS 不具备分级发布的能力,所有访问这个服务的 Envoy 都会立即收到变更后的最新配置。这在一些对变更敏感的严苛生产环境,可能是有很高风险甚至不被允许的。
如果你的生产环境严格要求任何变更都必须有分级发布流程,那你可能需要考虑自己实现一套这样的机制
## Istio 组件故障时是否有退路?
以 Istio 为代表的 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 架构的特殊性在于,[sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 直接承接了业务流量,而不像一些其他的基础设施那样,只是整个系统的**旁路组件**(比如 Kubernetes
因此在 Isito 落地初期,你必须考虑,如果 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 进程挂掉,服务怎么办?是否有退路?是否能 fallback 到直连模式?
在 Istio 落地过程中,是否能无损 fallback通常决定了核心业务能否接入服务网格。
## Istio 目前解决的问题域还很有限
> Sidecar是一种设计模型能够将应用和基础架构解耦。Istio只是使用这种模式实现服务发布和订阅时Sidecar设计模式的一种应用场景。
Istio 目前主要解决的是分布式系统之间服务调用的问题,但还有一些分布式系统的复杂语义和功能并未纳入到 Istio 的 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 运行时之中,比如消息发布和订阅、状态管理、资源绑定等等。
云原生应用将会朝着多 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 运行时或将更多分布式能力纳入单 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 运行时的方向继续发展,以使服务本身变得更为轻量,**让应用和基础架构彻底解耦**。
如果你的生产环境中业务系统对接了非常多和复杂的分布式系系统中间件Istio 目前可能并不能完全解决你的应用的云原生化诉求。
## 3 实践
### 安装
1. 下载istioctl工具https://gcsweb.istio.io/gcs/istio-release/releases/1.21.2/ 下载对应操作系统的版本。
```
wget https://github.com/istio/istio/releases/download/1.18.1/istio-1.18.1-linux-amd64.tar.gz
tar -zxvf istio-1.18.1-linux-amd64.tar.gz
cp /bin/istioctl /usr/bin/ctl
```
2. 将istio安装到环境中。安装后会出现以下资源。
```shell
➜ istio-1.21.2 istioctl install --set profile=demo -y
WARNING: Istio is being upgraded from 1.18.0 to 1.21.2.
Running this command will overwrite it; use revisions to upgrade alongside the existing version.
Before upgrading, you may wish to use 'istioctl x precheck' to check for upgrade warnings.
This installation will make default injection and validation pointing to the default revision, and originally it was pointing to the revisioned one.
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete Made this installation the default for injection and validation.
➜ istio-1.21.2 cd ..
➜ kubetest kubectl get all -n istio-system
NAME READY STATUS RESTARTS AGE
pod/istio-egressgateway-8c547cdc-27s94 1/1 Running 0 73s
pod/istio-ingressgateway-cd9c7b79-2gsr5 1/1 Running 0 73s
pod/istiod-868c79fcc6-tl9g7 1/1 Running 0 89s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-egressgateway ClusterIP 192.168.241.8 <none> 80/TCP,443/TCP 73s
service/istio-ingressgateway LoadBalancer 192.168.23.245 123.57.172.74 15021:30965/TCP,80:32501/TCP,443:30930/TCP,31400:31622/TCP,15443:32480/TCP 73s
service/istiod ClusterIP 192.168.35.184 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 15d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/istio-egressgateway 1/1 1 1 73s
deployment.apps/istio-ingressgateway 1/1 1 1 73s
deployment.apps/istiod 1/1 1 1 15d
NAME DESIRED CURRENT READY AGE
replicaset.apps/istio-egressgateway-8c547cdc 1 1 1 74s
replicaset.apps/istio-ingressgateway-cd9c7b79 1 1 1 74s
replicaset.apps/istiod-6b56fd6ddd 0 0 0 15d
replicaset.apps/istiod-868c79fcc6 1 1 1 90s
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/istiod Deployment/istiod 10%/80% 1 5 1 15d
NAME AGE
containernetworkfilesystem.storage.alibabacloud.com/cnfs-nas-c3225ec7463fe4ba9816186be4d2eb7f7 16d
```
3. 给制定明敏个空间开启istio注入。
```shell
kubectl label namespace bookinfo istio-injection=enabled
```
```shell
[root@vela istio-1.18.1]# kubectl get crds |grep istio
authorizationpolicies.security.istio.io 2023-07-23T04:42:38Z
destinationrules.networking.istio.io 2023-07-23T04:42:38Z
envoyfilters.networking.istio.io 2023-07-23T04:42:38Z
gateways.networking.istio.io 2023-07-23T04:42:38Z
istiooperators.install.istio.io 2023-07-23T04:42:39Z
peerauthentications.security.istio.io 2023-07-23T04:42:39Z
proxyconfigs.networking.istio.io 2023-07-23T04:42:39Z
requestauthentications.security.istio.io 2023-07-23T04:42:39Z
serviceentries.networking.istio.io 2023-07-23T04:42:39Z
sidecars.networking.istio.io 2023-07-23T04:42:39Z
telemetries.telemetry.istio.io 2023-07-23T04:42:39Z
virtualservices.networking.istio.io 2023-07-23T04:42:39Z
wasmplugins.extensions.istio.io 2023-07-23T04:42:40Z
workloadentries.networking.istio.io 2023-07-23T04:42:40Z
workloadgroups.networking.istio.io 2023-07-23T04:42:40Z
```
4. 部署测试应用
```shell
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo
istio-1.21.2 kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
```
5. 测试引用是否启动成功
```shell
kubectl exec -n bookinfo "$(kubectl get -n bookinfo pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
```

View File

@@ -0,0 +1,20 @@
## 简介
### Sidecar模式
将应用程序的功能划分为单独的进程运行在同一个最小调度单元中(例如 Kubernetes 中的 Pod可以被视为 sidecar 模式。如下图所示sidecar 模式允许您在应用程序旁边添加更多功能,而无需额外第三方组件配置或修改应用程序代码。
就像连接了 [Sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 的三轮摩托车一样,在软件架构中, [Sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 连接到父应用并且为其添加扩展或者增强功能。[Sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 应用与主应用程序松散耦合。它可以屏蔽不同编程语言的差异,统一实现微服务的可观察性、监控、日志记录、配置、断路器等功能。
![1714030026950](image/02Sidecar/1714030026950.png)
### 使用 Sidecar 模式的优势
使用 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 模式部署服务网格时,无需在节点上运行代理,但是集群中将运行多个相同的 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 副本。在 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 部署方式中,每个应用的容器旁都会部署一个伴生容器,这个容器称之为 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 容器。[Sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 接管进出应用容器的所有流量。在 Kubernetes 的 Pod 中,在原有的应用容器旁边注入一个 [Sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 容器,两个容器共享存储、网络等资源,可以广义的将这个包含了 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 容器的 Pod 理解为一台主机,两个容器共享主机资源。
因其独特的部署结构,使得 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 模式具有以下优势:
* 将与应用业务逻辑无关的功能抽象到共同基础设施,降低了微服务代码的复杂度。
* 因为不再需要编写相同的第三方组件配置文件和代码,所以能够降低微服务架构中的代码重复度。
* [Sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 可独立升级,降低应用程序代码和底层平台的耦合度。

View File

@@ -0,0 +1,136 @@
## 规范
### Pod Spec 中需满足的条件
为了成为 服务网格中的一部分Kubernetes 集群中的每个 Pod 都必须满足如下条件,这些规范不是由 Istio 自动注入的,而需要 生成 Kubernetes 应用部署的 YAML 文件时需要遵守的:
Service 关联:每个 pod 都必须只属于某一个 Kubernetes Service (当前不支持一个 pod 同时属于多个 service
命名的端口Service 的端口必须命名。端口的名字必须遵循如下格式 `<protocol>`[-`<suffix>`],可以是 http、http2、 grpc、 mongo、 或者 redis 作为 `<protocol>` ,这样才能使用 Istio 的路由功能。例如 name: http2-foo 和 name: http 都是有效的端口名称,而 name: http2foo 不是。如果端口的名称是不可识别的前缀或者未命名,那么该端口上的流量就会作为普通的 TCP 流量来处理(除非使用 Protocol: UDP 明确声明使用 UDP 端口)。
带有 app label 的 Deployment我们建议 Kubernetes 的Deploymenet 资源的配置文件中为 Pod 明确指定 applabel。每个 Deployment 的配置中都需要有个与其他 Deployment 不同的含有意义的 app label。app label 用于在分布式追踪中添加上下文信息。
Mesh 中的每个 pod 里都有一个 Sidecar最后网格中的每个 pod 都必须运行与 Istio 兼容的 sidecar。以下部分介绍了将 sidecar 注入到 pod 中的两种方法使用istioctl 命令行工具手动注入,或者使用 Istio Initializer 自动注入。注意 sidecar 不涉及到流量,因为它们与容器位于同一个 pod 中。
## 原理
### 注入方式
1. istioctl手动注入
2. 自动注入
Sidecar 容器注入的流程,每个注入了 Sidecar 的 Pod 中除了原先应用的应用本身的容器外,都会多出来这样两个容器:
* istio-init用于给 Sidecar 容器即 Envoy 代理做初始化,设置 iptables 端口转发
* istio-proxyEnvoy 代理容器,运行 Envoy 代理
### Init容器
一个 Pod 中可以指定多个 Init 容器,如果指定了多个,那么 Init 容器将会按顺序依次运行。只有当前面的 Init 容器必须运行成功后,才可以运行下一个 Init 容器。当所有的 Init 容器运行完成后Kubernetes 才初始化 Pod 和运行应用容器。
Init 容器使用 Linux Namespace所以相对应用程序容器来说具有不同的文件系统视图。因此它们能够具有访问 Secret 的权限,而应用程序容器则不能。
Istio 在 Pod 中注入的 Init 容器名为 istio-init如果你查看 reviews Deployment 配置,你将看到其中 initContaienrs 的启动参数:
```
initContainers:
- name: istio-init
image: docker.io/istio/proxyv2:1.13.1
args:
- istio-iptables
- '-p'
- '15001'
- '-z'
- '15006'
- '-u'
- '1337'
- '-m'
- REDIRECT
- '-i'
- '*'
- '-x'
- ''
- '-b'
- '*'
- '-d'
- 15090,15021,15020
```
参数解释
```
$ istio-iptables -p PORT -u UID -g GID [-m mode] [-b ports] [-d ports] [-i CIDR] [-x CIDR] [-h]
-p: 指定重定向所有 TCP 流量的 Envoy 端口(默认为 $ENVOY_PORT = 15001
-u: 指定未应用重定向的用户的 UID。通常这是代理容器的 UID默认为 $ENVOY_USER 的 uidistio_proxy 的 uid 或 1337
-g: 指定未应用重定向的用户的 GID。与 -u param 相同的默认值)
-m: 指定入站连接重定向到 Envoy 的模式“REDIRECT” 或 “TPROXY”默认为 $ISTIO_INBOUND_INTERCEPTION_MODE)
-b: 逗号分隔的入站端口列表,其流量将重定向到 Envoy可选。使用通配符 “*” 表示重定向所有端口。为空时表示禁用所有入站重定向(默认为 $ISTIO_INBOUND_PORTS
-d: 指定要从重定向到 Envoy 中排除(可选)的入站端口列表,以逗号格式分隔。使用通配符“*” 表示重定向所有入站流量(默认为 $ISTIO_LOCAL_EXCLUDE_PORTS
-i: 指定重定向到 Envoy可选的 IP 地址范围,以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量。空列表将禁用所有出站重定向(默认为 $ISTIO_SERVICE_CIDR
-x: 指定将从重定向中排除的 IP 地址范围,以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量(默认为 $ISTIO_SERVICE_EXCLUDE_CIDR
-z: 所有入站 TCP 流量重定向端口(默认为 $INBOUND_CAPTURE_PORT 15006
```
这条启动命令的作用是:
* 将应用容器的所有流量都转发到 Envoy 的 15006 端口。
* 使用 istio-proxy 用户身份运行, UID 为 1337即 Envoy 所处的用户空间,这也是 istio-proxy 容器默认使用的用户,见 YAML 配置中的 runAsUser 字段。
* 使用默认的 REDIRECT 模式来重定向流量。
* 将所有出站流量都重定向到 Envoy 代理。
* 将除了 15090、15201、15020 端口以外的所有端口的流量重定向到 Envoy 代理。
该容器存在的意义就是让 Envoy 代理可以拦截所有的进出 Pod 的流量,即将入站流量重定向到 Sidecar再拦截应用容器的出站流量经过 Sidecar 处理后再出站
## 3 流量路由
本文以 Istio 官方的 bookinfo 示例来讲解在进入 Pod 的流量被 iptables 转交给 Envoy [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 后Envoy 是如何做路由转发的,详述了 Inbound 和 Outbound 处理过程。
![1714031349157](image/03Istio注入原理/1714031349157.png)
### Envoy的架构
![1714032179003](image/03Istio注入原理/1714032179003.png)
每个 host 上都可能运行多个 serviceEnvoy 中也可能有多个 Listener每个 Listener 中可能会有多个 filter 组成了 chain。
**Host** :能够进行网络通信的实体(在手机或服务器等上的应用程序)。在 Envoy 中主机是指逻辑网络应用程序。只要每台主机都可以独立寻址,一块物理硬件上就运行多个主机。
**Downstream** 下游downstream主机连接到 Envoy发送请求并或获得响应。
**Upstream** 上游upstream主机获取来自 Envoy 的链接请求和响应。
**Cluster** : 集群cluster是 Envoy 连接到的一组逻辑上相似的上游主机。Envoy 通过服务发现发现集群中的成员。Envoy 可以通过主动运行状况检查来确定集群成员的健康状况。Envoy 如何将请求路由到集群成员由负载均衡策略确定。
**Mesh** 一组互相协调以提供一致网络拓扑的主机。Envoy mesh 是指一组 Envoy 代理,它们构成了由多种不同服务和应用程序平台组成的分布式系统的消息传递基础。
**运行时配置** :与 Envoy 一起部署的带外实时配置系统。可以在无需重启 Envoy 或 更改 Envoy 主配置的情况下,通过更改设置来影响操作。
**Listener** : 侦听器listener是可以由下游客户端连接的命名网络位置例如端口、unix域套接字等。Envoy 公开一个或多个下游主机连接的侦听器。一般是每台主机运行一个 Envoy使用单进程运行但是每个进程中可以启动任意数量的 Listener监听器目前只监听 TCP每个监听器都独立配置一定数量的L3/L4网络过滤器。Listenter 也可以通过 Listener Discovery Service **LDS** )动态获取。
**Listener filter** Listener 使用 listener filter监听器过滤器来操作链接的元数据。它的作用是在不更改 Envoy 的核心功能的情况下添加更多的集成功能。Listener filter 的 API 相对简单因为这些过滤器最终是在新接受的套接字上运行。在链中可以互相衔接以支持更复杂的场景例如调用速率限制。Envoy 已经包含了多个监听器过滤器。
**Http Route Table** HTTP 的路由规则例如请求的域名Path 符合什么规则,转发给哪个 Cluster。
**Health checking** 健康检查会与SDS服务发现配合使用。但是即使使用其他服务发现方式也有相应需要进行主动健康检查的情况。
## xDS
xDS 是一个关键概念,它是一类发现服务的统称,其包括如下几类:
* CDSCluster Discovery Service
* EDSEndpoint Discovery Service
* SDSService Discovery Service
* RDSRoute Discovery Service
* LDSListener Discovery Service
正是通过对 xDS 的请求来动态更新 Envoy 配置。
## Envoy Mesh
Envoy Mesh 指的是由 envoy 做负载均衡和代理的 mesh。该 Mesh 中会包含两类 envoy
* Edge envoy即流量进出 mesh 时候的 envoy相当于 kubernetes 中的 ingress。
* Service envoy服务 envoy 是跟每个 serivce 实例一起运行的,应用程序无感知的进程外工具,在 kubernetes 中会与应用容器以 [sidecar](https://jimmysong.io/kubernetes-handbook/GLOSSARY.html#sidecar "Sidecar全称 Sidecar proxy为在应用程序旁运行的单独的进程它可以为应用程序添加许多功能而无需在应用程序中添加额外的第三方组件或修改应用程序的代码或配置。") 形式运行在同一个 pod 中。
Envoy 即可以单独作为 edge envoy也可以仅做 service envoy 使用也可以两者同时使用。Mesh 中的所有 envoy 会共享路由信息。

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB