使用Kubernetes和服务网格简化系统架构与提升管理能力
1. 启动Minikube并设置命名空间
首先,我们需要启动Minikube实例,并将默认命名空间设置为“hands - on”,可以使用以下命令:
minikube start
kubectl config set-context $(kubectl config current-context) --namespace=hands-on
通过成功执行这些测试,我们验证了微服务在没有Kubernetes的情况下也能正常工作。
2. Kubernetes简化微服务架构
Kubernetes的一些功能可以简化微服务架构,减少与微服务一起开发和部署的支持服务数量。具体如下:
-
替代Spring Cloud Config Server
:可以使用Kubernetes的ConfigMaps和Secrets来替代Spring Cloud Config Server。
-
替代Spring Cloud Gateway
:Kubernetes的Ingress对象可以替代Spring Cloud Gateway。
-
自动证书配置
:使用cert - manager可以为Ingress控制器暴露的HTTPS端点自动配置证书,避免了手动配置的繁琐工作。
-
跨平台验证
:为了验证微服务的源代码可以在其他平台上运行,而不局限于Kubernetes,我们使用Docker Compose部署微服务并运行测试脚本。
3. 服务网格简介
服务网格是一个基础设施层,用于控制和观察服务(如微服务)之间的通信。它具有以下能力:
-
可观测性
:可视化微服务之间的流量流动。
-
安全性
:保护服务之间的通信。
-
策略执行
:实施各种策略。
-
弹性
:确保系统在故障时的稳定性。
-
流量管理
:控制流量的路由。
服务网格的核心组件之一是轻量级代理组件,它会被注入到每个要加入服务网格的微服务中。所有进出微服务的流量都会通过其代理组件。代理组件由服务网格中的控制平面在运行时使用代理暴露的API进行配置,控制平面还会通过这些API从代理收集遥测数据,以可视化服务网格中的流量情况。
服务网格还包含数据平面,由代理组件以及处理服务网格内外流量的入口网关和出口网关组成。网关组件也通过代理组件与控制平面通信,其结构如下:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(控制平面):::process --> B(代理组件):::process
A --> C(入口网关):::process
A --> D(出口网关):::process
B <--> E(微服务1):::process
B <--> F(微服务2):::process
C <--> G(外部流量进入):::process
D <--> H(外部流量出去):::process
4. Istio简介
Istio是一个流行的开源服务网格实现,可以使用各种安装工具部署在多个Kubernetes发行版和平台上。我们将使用Istio的CLI工具istioctl在基于Minikube的单节点Kubernetes集群中安装Istio。
Istio分为控制平面和数据平面。作为操作者,我们可以通过在Kubernetes API服务器中创建Istio对象(如声明路由规则)来定义所需状态。控制平面会读取这些对象并向数据平面中的代理发送命令,以根据所需状态采取行动,例如配置路由规则。代理处理微服务之间的实际通信,并将遥测数据报告回控制平面,用于可视化服务网格中的情况。
当在Kubernetes上部署Istio时,其大多数运行时组件部署在单独的Kubernetes命名空间istio - system中,具体部署组件如下表所示:
| 组件名称 | 说明 |
| ---- | ---- |
| istiod | 运行整个控制平面的守护进程 |
| istio - ingressgateway和istio - egressgateway | 入口和出口网关组件,属于数据平面 |
| Kiali | 为服务网格提供可观测性,可视化网格中的情况 |
| Tracing(使用Jaeger) | 处理和可视化分布式跟踪信息 |
| Prometheus | 进行基于时间序列的数据摄取和存储,如性能指标 |
| Grafana | 可视化Prometheus收集的性能指标和其他时间序列相关数据 |
5. 向微服务注入Istio代理
在之前章节中,我们在Kubernetes中部署的微服务作为单个容器运行在Kubernetes Pod中。为了让微服务加入基于Istio的服务网格,需要向每个微服务注入Istio代理,这通过在运行微服务的Pod中添加一个额外的容器来实现。
Istio代理可以在创建Pod对象时自动注入,也可以使用istioctl工具手动注入:
-
自动注入
:要让Istio自动将代理注入到命名空间中的新Pod,可以为命名空间添加标签
istio - injection: enabled
。如果要排除某些Pod的自动注入,可以为其添加注解
sidecar.istio.io/inject: "false"
。
-
手动注入
:对于现有Deployment对象的Pod,可以使用以下命令手动注入Istio代理:
kubectl get deployment sample-deployment -o yaml | istioctl kube-inject -f - | kubectl apply -f -
该命令实际上由三个单独的命令组成:
1.
kubectl get deployment
:从Kubernetes API服务器获取名为sample - deployment的Deployment的当前定义,并以YAML格式返回。
2.
istioctl kube - inject
:读取
kubectl get deployment
命令的定义,并在Deployment处理的Pod中添加一个用于Istio代理的额外容器,更新Deployment对象中现有容器的配置,使进出流量通过Istio代理。
3.
kubectl apply
:读取
istioctl kube - inject
命令更新后的配置并应用该配置,启动Deployment所属Pod的升级。
在实际操作中,我们将通过应用以下hands - on命名空间的定义来自动注入Istio代理:
apiVersion: v1
kind: Namespace
metadata:
name: hands-on
labels:
istio-injection: enabled
由于在编写本文时,Istio不能完全作为MySQL、MongoDB和RabbitMQ的代理,因此我们会在它们的Helm图表的values.yaml文件中添加以下注解,将它们排除在服务网格之外:
annotations:
sidecar.istio.io/inject: "false"
6. Istio API对象
Istio带有一组Kubernetes自定义资源定义(CRDs),用于扩展Kubernetes的API。我们将使用以下Istio对象:
| 对象名称 | 说明 |
| ---- | ---- |
| Gateway | 配置如何处理进出服务网格的流量,依赖于虚拟服务将传入流量路由到Kubernetes服务。我们将使用它接受以minikube.me结尾的DNS名称的HTTPS传入流量,替代之前使用的Ingress对象。 |
| VirtualService | 定义服务网格中的路由规则,描述如何将来自Istio网关的传入流量路由到Kubernetes服务以及服务之间的路由。还可用于注入故障和延迟,测试服务网格的可靠性和弹性。 |
| DestinationRule | 定义路由到特定服务的流量的策略和规则,如设置内部HTTP流量的加密策略,定义服务子集以进行零停机(蓝绿)部署。 |
| PeerAuthentication | 控制服务网格内的服务到服务认证,Istio可以通过自动配置相互TLS(mTLS)来保护服务之间的通信。为了允许Kubernetes使用纯HTTP调用存活和就绪探针,我们将配置Istio允许mTLS和纯HTTP的混合模式(PERMISSIVE模式)。 |
| RequestAuthentication | 根据请求中提供的凭证对最终用户进行认证,支持使用JSON Web Tokens(JWTs),特别是根据OpenID Connect(OIDC)规范使用时。我们将通过指定其JWKS发现端点来配置Istio使用认证服务器对外部请求进行认证。 |
| AuthorizationPolicy | 提供Istio中的访问控制,在本文中我们不使用Istio的访问控制,而是重用产品组合微服务中现有的访问控制。因此,我们将配置一个AuthorizationPolicy对象,允许任何经过身份验证的用户(即包含有效JWT作为OIDC访问令牌的请求)访问产品组合微服务。 |
7. 简化微服务架构
Istio的一些组件在功能上与当前微服务架构中使用的组件有重叠:
-
替代Kubernetes Ingress控制器
:Istio的入口网关可以作为边缘服务器,替代Kubernetes Ingress控制器。它具有以下优点:
- 可以将流经它的流量的遥测数据报告给控制平面。
- 可用于更细粒度的路由。
- 可以在将请求路由到服务网格之前进行认证和授权。
为了利用这些优点,我们将用Istio入口网关替换Kubernetes Ingress控制器。之前使用的Ingress对象的定义已从
kubernetes/helm/environments
中的
dev - env
和
prod - env
Helm图表中移除。Istio入口网关使用不同的IP地址,因此我们还需要更新运行测试时使用的主机名
minikube.me
映射的IP地址。
-
替代Zipkin服务器
:Istio附带的Jaeger组件可以用于分布式跟踪,替代与微服务一起部署的Zipkin服务器。
综上所述,Kubernetes和服务网格(如Istio)为微服务架构的简化和管理提供了强大的功能。通过合理使用这些技术,我们可以提高微服务系统的可观测性、安全性、弹性和可管理性。
使用Kubernetes和服务网格简化系统架构与提升管理能力
8. 替换Kubernetes Ingress控制器为Istio入口网关的详细步骤
在前面提到,我们要将Kubernetes Ingress控制器替换为Istio入口网关,下面详细介绍具体步骤:
1.
移除旧的Ingress对象定义
:将之前使用的Ingress对象的定义从
kubernetes/helm/environments
中的
dev - env
和
prod - env
Helm图表中移除。
2.
创建Istio Gateway和VirtualService对象
:按照之前介绍的Istio API对象的功能,创建相应的Gateway和VirtualService对象来配置流量路由。
3.
更新IP地址映射
:由于Istio入口网关使用不同的IP地址,我们需要更新运行测试时使用的主机名
minikube.me
映射的IP地址。具体操作流程如下:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(移除旧Ingress定义):::process --> B(创建Istio对象):::process
B --> C(获取Istio入口网关IP):::process
C --> D(更新minikube.me IP映射):::process
9. 服务网格的安全性和认证配置
服务网格的安全性至关重要,Istio提供了多种认证和授权机制来保障服务间通信的安全。
-
PeerAuthentication配置
:为了保护服务之间的通信,Istio可以自动配置相互TLS(mTLS)。但为了允许Kubernetes使用纯HTTP调用存活和就绪探针,我们将配置Istio为PERMISSIVE模式,允许mTLS和纯HTTP的混合。示例配置如下:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
spec:
mtls:
mode: PERMISSIVE
- RequestAuthentication配置 :根据请求中提供的凭证对最终用户进行认证,支持使用JSON Web Tokens(JWTs)。我们通过指定其JWKS发现端点来配置Istio使用认证服务器对外部请求进行认证。示例配置如下:
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: jwt-example
spec:
selector:
matchLabels:
app: product-composite
jwtRules:
- issuer: "https://example.com"
jwksUri: "https://example.com/.well-known/jwks.json"
- AuthorizationPolicy配置 :我们不使用Istio的访问控制,而是重用产品组合微服务中现有的访问控制。配置一个AuthorizationPolicy对象,允许任何经过身份验证的用户(即包含有效JWT作为OIDC访问令牌的请求)访问产品组合微服务。示例配置如下:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-authenticated
spec:
selector:
matchLabels:
app: product-composite
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["*"]
10. 服务网格的弹性测试
为了确保服务网格的可靠性和弹性,我们可以使用VirtualService对象注入故障和延迟进行测试。
-
注入故障
:可以通过配置VirtualService对象,在请求路由时返回错误响应,模拟服务故障。示例配置如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: product-composite
spec:
hosts:
- product-composite
http:
- fault:
abort:
percent: 10
httpStatus: 500
route:
- destination:
host: product-composite
- 注入延迟 :通过配置VirtualService对象,在请求路由时添加延迟,模拟网络延迟或服务响应缓慢。示例配置如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: product-composite
spec:
hosts:
- product-composite
http:
- fault:
delay:
percent: 10
fixedDelay: 5s
route:
- destination:
host: product-composite
11. 零停机部署(蓝绿部署)
在微服务架构中,零停机部署是非常重要的,Istio的DestinationRule对象可以帮助我们实现零停机部署。
1.
定义服务子集
:在DestinationRule中定义服务的不同版本,例如旧版本(蓝色)和新版本(绿色)。示例配置如下:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: product-composite
spec:
host: product-composite
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- 配置路由规则 :通过VirtualService对象配置流量路由,开始时将所有流量导向旧版本,然后逐步将流量导向新版本。示例配置如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: product-composite
spec:
hosts:
- product-composite
http:
- route:
- destination:
host: product-composite
subset: v1
weight: 100
- destination:
host: product-composite
subset: v2
weight: 0
随着测试和验证的进行,可以逐步调整权重,将流量从旧版本转移到新版本,实现零停机部署。
12. 总结与最佳实践
通过使用Kubernetes和服务网格(如Istio),我们可以显著简化微服务架构,提高系统的可观测性、安全性、弹性和可管理性。以下是一些最佳实践总结:
-
合理使用API对象
:根据不同的需求,合理使用Istio的各种API对象,如Gateway、VirtualService、DestinationRule等,来配置流量路由、安全策略和服务治理。
-
自动化注入代理
:使用自动注入机制将Istio代理注入到微服务中,减少手动配置的工作量。
-
定期进行弹性测试
:通过注入故障和延迟,定期对服务网格进行弹性测试,确保系统在故障情况下的稳定性。
-
遵循安全配置原则
:按照最佳实践配置PeerAuthentication、RequestAuthentication和AuthorizationPolicy,保障服务间通信的安全。
通过遵循这些最佳实践,我们可以更好地利用Kubernetes和服务网格的功能,构建更加健壮和高效的微服务系统。
超级会员免费看

58

被折叠的 条评论
为什么被折叠?



