ICA 模拟考 A
这是 ICA 模拟考试 A。限时 120 分钟,共 17 道题,合格线为 68%。 采用部分计分制,因此遇到卡住的题目,最好先跳过,稍后再回来处理。
这是模拟考试,请不要查看提示和答案,先独立完成全部题目。 因为时间不足而没做完,与因为不会而没做完,是两类不同的问题;只有区分两者, 才能决定下一步该学习什么。请完成并评分后再展开提示。
真实考试环境
考试期间可以查看 istio.io/docs、istio.io/blog、kubernetes.io/docs。
允许通过 istio.io/search/ 在文档站内搜索,但不能点击外部搜索结果。
k 别名、bash 自动补全以及 istioctl 自动补全都已配置。每道题需要通过 ssh
连接到指定主机操作,不支持嵌套 ssh。终端复制使用 Ctrl+Shift+C,
粘贴使用 Ctrl+Shift+V。
本模拟考试环境
直接在 Pod 内的单人集群中操作(不需要 ssh)。kube-apiserver 是真实的,因此错误清单 会被实际拒绝,但 Sidecar 不会启动,也不会有真实流量。评分器会重新读取你留在集群中的配置。
第 1 题是后续大多数题目的前提。在 Istio 资源类型注册之前,kubectl apply 不会接受
VirtualService。请先完成它。
1. 生成默认 profile 的 Istio 安装清单,保存到 /root/ica/install/manifest.yaml。
然后只筛选清单中的 CustomResourceDefinition 并注册到集群。本环境不会启动 istiod Pod,
因此只需要 API 类型。
2. 创建三个命名空间并添加 Sidecar 注入标签。
- 为
ica-shop添加istio-injection=enabled - 为
ica-legacy添加istio-injection=disabled - 为
ica-rev添加istio.io/rev=1-24。该命名空间中不要保留istio-injection标签。
3. 在 Pod 级别反转命名空间的决定。两个 Deployment 均为 1 个副本,镜像为 nginx:1.27-alpine。
ica-shop中的batch-runner:Pod 模板标签为sidecar.istio.io/inject: "false"ica-legacy中的legacy-api:Pod 模板标签为app: legacy-api和sidecar.istio.io/inject: "true"
4. 在 ica-shop 中部署三个版本的 reviews 服务并定义 subset。
- Deployment
reviews-v1、reviews-v2、reviews-v3各 1 个副本。Pod 标签为app=reviews和version=v1/v2/v3。镜像为nginx:1.27-alpine,容器端口为 9080。 - Service
reviews:端口 9080,端口名称http。selector 只保留app=reviews。 - DestinationRule
reviews:spec.host为reviews.ica-shop.svc.cluster.local。分别定义 subsetv1、v2、v3,各自使用对应的version标签,并将trafficPolicy.loadBalancer.simple设为LEAST_REQUEST。
5. 在 ica-shop 中创建 VirtualService reviews。host 为
reviews.ica-shop.svc.cluster.local,使用一条无条件规则,将 80 分配给 subset v1,
20 分配给 subset v2。
6. 在第 5 题的 VirtualService reviews 前面再添加两条规则,共三条。
顺序属于评分内容。
- 请求头
end-user精确等于tester时路由到 subsetv3 uri前缀为/api/v2且方法同时为GET时路由到 subsetv2- 第 5 题的加权规则作为最后一条无条件规则保留
7. 为同一个 VirtualService reviews 的最后一条(无条件)规则添加弹性配置。
总超时为 2s,重试 3 次,每次尝试超时 500ms,重试条件为
5xx、reset、connect-failure。
8. 为 DestinationRule reviews 的 trafficPolicy 添加上限和异常检测。
connectionPool.tcp.maxConnections为 100connectionPool.http.http1MaxPendingRequests为 10connectionPool.http.maxRequestsPerConnection为 1outlierDetection中consecutive5xxErrors为 5、interval为10s、baseEjectionTime为30s、maxEjectionPercent为 50
9. 在 ica-shop 中建立入口。
- Gateway
shop-gateway:selector 为istio: ingressgateway。80 端口(名称http、协议 HTTP)接收 hostshop.example.com并重定向到 HTTPS。443 端口(名称https、协议 HTTPS)以SIMPLE模式终止同一 host,证书 Secret 名称为shop-cert。 - VirtualService
shop-edge:host 为shop.example.com,绑定 Gatewayshop-gateway,把uri前缀/reviews发送到reviews.ica-shop.svc.cluster.local的 9080 端口。
10. 在整个服务网格中强制 mTLS,但为旧命名空间设置例外。
- 创建
istio-system命名空间,并在其中创建 PeerAuthenticationdefault,模式为STRICT。不要添加 selector。 - 在
ica-legacy中创建 PeerAuthenticationdefault,模式为PERMISSIVE。同样不要添加 selector。
11. 只把 ica-legacy 的 legacy-api 工作负载升级为 STRICT,但为 8080 端口设置例外。
PeerAuthentication 名称为 legacy-api,selector 为 app: legacy-api,mtls.mode 为 STRICT,
portLevelMtls 的 8080 为 DISABLE。
12. 在 ica-shop 中创建两条授权策略。两者的 selector 都是 app: reviews。
reviews-allow:ALLOW。来源 principal 为cluster.local/ns/ica-shop/sa/productpage,允许的方法为GET,路径为/reviews*。reviews-deny-admin:DENY。阻止路径/admin*。
13. 为 ica-shop 中的 app: reviews 工作负载添加 JWT 验证。
- RequestAuthentication
shop-jwt:issuer 为https://auth.shop.example.com,jwksUri 为https://auth.shop.example.com/.well-known/jwks.json - AuthorizationPolicy
require-jwt:ALLOW。requestPrincipals 为https://auth.shop.example.com/*
14. 某团队准备在 ica-fix 命名空间中使用下面的 VirtualService,但目前执行
istioctl analyze 会报错。诊断并补齐缺失内容,使 istioctl analyze -n ica-fix
不再产生任何 Error。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: payments
namespace: ica-fix
spec:
hosts:
- payments.ica-fix.svc.cluster.local
http:
- route:
- destination:
host: payments.ica-fix.svc.cluster.local
subset: stable
需要补充的规格如下。Deployment payments 的 Pod 标签为 app=payments 和 version=v1;
Service payments 的端口为 9090,端口名称为 http;DestinationRule payments 以上述
FQDN 作为 host,并将 subset stable 定义为 version: v1。不要在该命名空间中留下
与题目无关的资源,否则 analyze 也会将其报告出来。
15. 在 ica-triage 命名空间应用下面的 VirtualService 后,即使添加
x-beta: true 请求头,也总是路由到 stable。请诊断原因并应用修复,仍然保留两条规则。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: checkout
namespace: ica-triage
spec:
hosts:
- checkout.ica-triage.svc.cluster.local
http:
- route:
- destination:
host: checkout.ica-triage.svc.cluster.local
subset: stable
- match:
- headers:
x-beta:
exact: "true"
route:
- destination:
host: checkout.ica-triage.svc.cluster.local
subset: beta
16. 应用下面的策略后,ica-triage 中的 payments 工作负载拒绝了所有请求。
诊断原因并修复,使其只允许 cluster.local/ns/ica-triage/sa/frontend 通过 POST
访问 /pay*。
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: payments-allow
namespace: ica-triage
spec:
selector:
matchLabels:
app: payments
action: ALLOW
rules: []
17. 在 ica-triage 中放置下面两个资源后,所有调用 orders 的客户端都失败。
保持服务器端要求不变,只修复客户端设置。
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: ica-triage
spec:
mtls:
mode: STRICT
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: orders
namespace: ica-triage
spec:
host: orders.ica-triage.svc.cluster.local
trafficPolicy:
tls:
mode: DISABLE
第 15~17 题无需在 ica-triage 中创建工作负载,需要修复的是配置。
在集群中注册服务网格 API 类型
istioctl manifest generate 把 Chart 内置在二进制文件中,因此无需互联网也能运行。输出还包含 istiod 和 Service,但本环境只需要 CRD,请按 kind 过滤。应用时使用 --server-side。Istio CRD 的注解很大,会超过普通 apply 的 last-applied-configuration 上限(262144 字节)。
按命名空间设置 Sidecar 注入标签
revision 标签与 istio-injection 标签同时存在时,istio-injection 优先。因此迁移 revision 时若不删除旧标签,新 revision 会被静默忽略。删除时在标签名称后加减号。
在 Pod 级别反转注入决定
sidecar.istio.io/inject 应放在 Pod 模板标签中,不是 Deployment 自身的标签或注解。值必须是带引号的字符串。Kubernetes 标签值只接受字符串,不加引号会被 apiserver 拒绝。
创建各版本工作负载与 subset
如果 Service selector 包含 version,就只会选中一个版本,无法进行加权分流。区分版本由 DestinationRule 的 subset 完成。subset 的 labels 必须与 Pod 标签逐字一致,而不是 subset 名称;spec.host 请使用 FQDN 而非短名称。Service 端口名称是 Istio 判断协议的依据。
按权重进行 80 比 20 分流
权重放在 route 数组各 destination 上,总和必须为 100。该规则不要设置 match。后续题目会把条件规则放在它前面,无条件规则必须始终位于最后。
把具体规则放在 catch-all 前面
规则自上而下评估,第一个匹配获胜。无条件规则位于最前时,后续规则永远不会被评估。要把两个条件按 AND 组合,必须并列写在同一个 match 块中;拆成两个块就会成为 OR。
协调超时与重试的关系
timeout 是包含重试的总截止时间。perTryTimeout 乘以尝试次数超过 timeout 时,最后一次尝试尚未开始就会被截断。此处 500ms × 3 为 1.5 秒,可容纳在 2 秒内。retryOn 是逗号连接的字符串,留空就没有定义针对哪些失败重试。
设置连接池上限与异常检测
两者都位于同一个 trafficPolicy 中,但作用不同。connectionPool 限制本端发出的负载,outlierDetection 在对端实例持续返回 5xx 时暂时将其移除。未写 maxEjectionPercent 时该字段不会保存,因此请显式指定。注意不要删除前题创建的 loadBalancer。
建立入口网关
Gateway 只开放端口,不负责路由。若未在 VirtualService 的 spec.gateways 中写入名称进行绑定,该规则只作用于服务网格内部,外部请求会收到 404。httpsRedirect 放在 80 端口 server 的 tls 下。证书由网关 Pod 在其命名空间中通过 credentialName 查找。
服务网格全局 STRICT 与命名空间例外
PeerAuthentication 有三个作用层级。无 selector 且位于根命名空间(istio-system)时作用于整个服务网格;无 selector 但位于其他命名空间时作用于整个命名空间;有 selector 时作用于工作负载。范围更窄的策略优先。给全局策略添加 selector 后,它就不再是全局策略。
为工作负载 STRICT 设置端口例外
portLevelMtls 只在具有 selector 的工作负载策略中生效。没有 selector 时 apiserver 会拒绝。这里填写的是 Pod 容器端口,而不是 Service 端口。填写 Service 端口会导致例外完全不生效,而且不会产生任何错误。
分别编写 ALLOW 与 DENY 策略
DENY 先于 ALLOW 评估,只要命中就立即结束。评估顺序是 CUSTOM、DENY、ALLOW。principal 是服务账号的 SPIFFE 身份,格式为 cluster.local/ns/<네임스페이스>/sa/<서비스계정>。路径末尾的星号表示前缀匹配。
同时设置 JWT 验证与令牌要求
RequestAuthentication 只会在存在令牌时验证,没有令牌的请求会直接通过。若要强制令牌,必须同时设置使用 requestPrincipals 的 AuthorizationPolicy。requestPrincipals 由 issuer 与 subject 以斜杠连接;只限制签发者时,将后半部分设为星号。
补齐 analyze 发现的缺失项
先运行 istioctl analyze -n ica-fix,阅读它找不到什么。IST0101 表示无法找到所引用的 host,或 host 与 subset 的组合。Service 不存在与 DestinationRule 缺少 subset 都会产生同一代码。逐项补齐并重新运行,可看到剩余问题逐步减少。
恢复无法到达的规则
规则自上而下评估,第一个匹配获胜。无条件规则匹配所有请求,因此位于最前时,后续规则永远不会被评估。该配置不会报错且仍然有效,只能靠人工查看发现。
修复阻止所有请求的空 ALLOW 策略
只要某工作负载匹配任意 AuthorizationPolicy,它就会切换为默认拒绝。在这种状态下,ALLOW 规则为空意味着没有请求可以匹配规则,因此全部被拒绝。没有策略与存在空策略会产生完全相反的结果。
修复与服务器要求不一致的客户端 TLS
PeerAuthentication 决定服务器接受什么,DestinationRule 的 trafficPolicy.tls 决定客户端如何连接。服务器为 STRICT 而客户端为 DISABLE 时,客户端会使用明文连接并被断开。两者本身都是有效配置,不会产生错误,这正是故障难排查的原因。请选择由 Sidecar 代管证书的模式。