Istio 的配置分析
- Istio 的配置分析
- Analyzer 的訊息格式
- ConflictingMeshGatewayVirtualServiceHosts
- ConflictingSidecarWorkloadSelectors
- GatewayPortNotOnWorkload
- InternalError
- IstioProxyImageMismatch
- JwtFailureDueToInvalidServicePortPrefix
- MisplacedAnnotation
- MTLSPolicyConflict
- MultipleSidecarsWithoutWorkloadSelectors
- NamespaceNotInjected
- SchemaValidationError
- VirtualServiceDestinationPortSelectorRequired
- UnknownAnnotation
- ReferencedResourceNotFound
- PortNameIsNotUnderNamingConvention
- PodMissingProxy
Analyzer 的訊息格式
istioctl analyze
命令提供瞭如下訊息格式:
<level> [<code>] (<affected-resource>) <message-details>
<resource-kind> <resource-name>.<resource-namespace>
例如:
Error [IST0101] (VirtualService httpbin.default) Referenced gateway not found: "httpbin-gateway-bogus"
<message-details>
欄位包含關於解決問題的詳細資訊。當對於叢集範圍的資源(如namespace
)時,會忽略namespace字首。
ConflictingMeshGatewayVirtualServiceHosts
Message Name | ConflictingMeshGatewayVirtualServiceHosts |
---|---|
Message Code | IST0109 |
Description | Conflicting hosts on VirtualServices associated with mesh gateway |
Level | Error |
當Istio檢測到virtual service資源之間存在重疊導致的衝突時,會出現該訊息。例如,定義了多個使用相同的主機名的virtual service,並將其附加到網格閘道器上,這樣就會產生上述錯誤。注意,Istio支援合併附加到ingress閘道器的virtual services。
問題解決
可以使用如下動作來解決該問題:
- 將多個衝突的virtual service合併為一個
- 將附加到一個網格閘道器的多個virtual service的主機名配置為唯一的
- 通過
exportTo
欄位將資源指定到某個指定的名稱空間中
舉例
例如,team1
名稱空間中的 productpage
virtual service 與team2
名稱空間中的custom
virtual service因為同時設定瞭如下條件導致了衝突:
- 都附加到了預設的
mesh
閘道器上(沒有指定使用者閘道器) - 定義了相同的host
productpage.default.svc.cluster.local
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
namespace: team-1
spec:
hosts:
- productpage.default.svc.cluster.local
http:
- route:
- destination:
host: productpage
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: custom
namespace: team-2
spec:
hosts:
- productpage.default.svc.cluster.local
http:
- route:
- destination:
host: productpage.team-2.svc.cluster.local
---
可以通過設定exportTo欄位來解決該問題,這樣,virtual service的範圍就限制於其所在的名稱空間。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
namespace: team-1
spec:
exportTo:
- "." #當前名稱空間
hosts:
- productpage.default.svc.cluster.local
http:
- route:
- destination:
host: productpage
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: custom
namespace: team-2
spec:
exportTo:
- "." #當前名稱空間
hosts:
- productpage.default.svc.cluster.local
http:
- route:
- destination:
host: productpage.team-2.svc.cluster.local
---
ConflictingSidecarWorkloadSelectors
Message Name | ConflictingSidecarWorkloadSelectors |
---|---|
Message Code | IST0110 |
Description | A Sidecar resource selects the same workloads as another Sidecar resource |
Level | Error |
當一個名稱空間中的多個sidecar選擇相同的負載例項時會出現該訊息,可能導致不可預知的行為。更多資訊參見Sidecar資源。
為了解決該問題,需要一個名稱空間中的Sidecar負載選擇器(workloadSelector
)選擇的負載例項不會出現重疊。
GatewayPortNotOnWorkload
Message Name | GatewayPortNotOnWorkload |
---|---|
Message Code | IST0104 |
Description | Unhandled gateway port |
Level | Warning |
當一個閘道器(通常是istio-ingressgateway
)提供的埠並不在閘道器選擇的kubernetes service負載上時會出現該訊息。
例如,Istio的配置包含如下值:
# Gateway with bogus port
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
- port:
number: 8004
name: http2
protocol: HTTP
hosts:
- "*"
在上面例子中會出現GatewayPortNotOnWorkload
訊息,因為一個預設的IngressGateway僅會開啟埠 80, 443, 31400, 和15443,並不包括8004。使用istioctl analyze分析的結果如下:
# istioctl analyze
Warn [IST0104] (Gateway httpbin-gateway.default) The gateway refers to a port that is not exposed on the workload (pod selector istio=ingressgateway; port 8004)
Info [IST0118] (Service mutatepodimages.default) Port name (port: 443, targetPort: 8443) doesn't follow the naming convention of Istio port.
Error: Analyzers found issues when analyzing namespace: default.
為了解決該問題,可以修改閘道器的配置,使用一個有效的負載埠,並重新部署即可。
InternalError
Message Name | InternalError |
---|---|
Message Code | IST0001 |
Description | There was an internal error in the toolchain. This is almost always a bug in the implementation. |
Level | Error |
極有可能是因為Istio的內部錯誤造成的。可以參見Istio的issue頁面來了解會提交問題。
IstioProxyImageMismatch
Message Name | IstioProxyImageMismatch |
---|---|
Message Code | IST0105 |
Description | The image of the Istio proxy running on the pod does not match the image defined in the injection configuration. |
Level | Warning |
當一個Pod出現如下條件時會發生該問題:
- 啟用sidecar自動注入(預設是啟用的,除非在安裝時禁用)
- pod執行在一個啟用sidecar注入的名稱空間中(給名稱空間打上標籤
istio-injection=enabled
) - 執行在sidecar中的代理版本與自動注入的版本不匹配
該問題通常會發生在更新Istio的控制面之後,在升級Istio後,所有帶Istio sidecar執行的負載必須重啟來注入新版本的sidecar。
為了解決該問題,可以通過滾動策略來重新部署應用的sidecar。對於kubernetes的deployment:
- 如果使用kubernetes 1.15或更高版本,可以執行
kubectl rollout restart <my-deployment>
來觸發滾動 - 或者,可以修改deployment的
template
欄位來強制觸發滾動。這通常是通過在模板的pod定義中新增諸如force-redeploy = <current-timestamp>
之類的標籤來觸發deployment滾動的。
JwtFailureDueToInvalidServicePortPrefix
Message Name | JwtFailureDueToInvalidServicePortPrefix |
---|---|
Message Code | IST0119 |
Description | Authentication policy with JWT targets Service with invalid port specification. |
Level | Warning |
當一個認證策略使用JWT認證時,而目標kubernetes service配置不正確時會出現該訊息。正確的kubernetes service要求port使用http|http2|https作為字首來命名(參見Protocol Selection),並且協議為TCP。預設的協議為TCP。
舉例
當叢集中存在如下策略時:
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: secure-httpbin
namespace: default
spec:
targets:
- name: httpbin
origins:
- jwt:
issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio-1.4/security/tools/jwt/samples/jwks.json"
target的service配置如下:
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: default
labels:
app: httpbin
spec:
ports:
- name: svc-8080
port: 8080
targetPort: 80
protocol: TCP
selector:
app: httpbin
在上面例子中,port svc-8080
並沒有遵守語法: name: <http|https|http2>[-<suffix>]
。將會接收到如下訊息:
Warn [IST0119] (Policy secure-httpbin.default) Authentication policy with JWT targets Service with invalid port specification (port: 8080, name: svc-8080, protocol: TCP, targetPort: 80).
JWT認證僅支援http,https或http2,修改Service 埠名,使其遵守 <http|https|http2>[-<suffix>]
即可。
MisplacedAnnotation
Message Name | MisplacedAnnotation |
---|---|
Message Code | IST0107 |
Description | An Istio annotation is applied to the wrong kind of resource. |
Level | Warning |
當Istio的annotation附加到一個無效的資源或錯誤的位置上時會出現該訊息。例如,如果建立一個deployment,然後將annotation附加到該deployment,而不是pods上時就會出現該錯誤提示。
將annotation放到正確的位置即可修改該問題。
MTLSPolicyConflict
Message Name | MTLSPolicyConflict |
---|---|
Message Code | IST0113 |
Description | A DestinationRule and Policy are in conflict with regards to mTLS. |
Level | Error |
當一個destination rule資源和一個策略資源因為mutual TLS衝突時會出現該訊息。當兩個資源選擇的TLS模式不匹配時就會出現這種情況。該衝突意味著,匹配到destination rule的流量將會被拒絕。
該訊息已經被廢棄,僅在使用alpha認證策略的服務網格中使用。(瞭解該問題仍然可以避免配置錯誤)
哪些destination rules和策略與服務相關
為了有效解決mutual TLS的衝突,需要同時瞭解destination rule和策略是如何影響到一個服務的流量的。考慮一個my-namespace
名稱空間中的名為my-service
的服務。為了確定應用到my-service
上的是哪個策略物件,按順序匹配以下資源:
my-namespace
名稱空間中的策略資源包含一個target
,指定了my-service
my-namespace
名稱空間中的一個名為default
的策略資源不包含一個target
,意味著該策略適用於整個名稱空間。- 名為
default
的網格策略資源
為了確定哪個destination rule應用到到達my-service
的流量,首先要知道流量來自哪個名稱空間。本例中,假設名稱空間為other-namespace
。destination rule按照如下方式進行匹配:
-
other-namespace
名稱空間中的destination rule會指定一個host來匹配my-service.my-namespace.svc.cluster.local
(可能會通過完整匹配或萬用字元匹配)。注意exportTo
欄位,該欄位控制了配置資源的可見性,當目標資源與源服務在相同的名稱空間時會被忽略(相同名稱空間下的服務總是可見的)。 -
my-namespace
名稱空間中的destination rule會指定一個host來匹配my-service.my-namespace.svc.cluster.local
(可能會通過完整匹配或萬用字元匹配)。注意為了進行匹配,exportTo
欄位必須將該資源指定為公共的(即,值為*
或不指定)。 -
根名稱空間(預設為
istio-system
)中的destination rule會匹配my-service.my-namespace.svc.cluster.local
。MeshConfig
資源中的rootNamespace
屬性會控制根名稱空間。注意為了進行匹配,exportTo
欄位必須將該資源指定為公共的(即,值為*
或不指定)。對rootNamespace
的描述如下The namespace to treat as the administrative root namespace for Istio configuration. When processing a leaf namespace Istio will search for declarations in that namespace first and if none are found it will search in the root namespace. Any matching declaration found in the root namespace is processed as if it were declared in the leaf namespace.
最後,注意在遵循這些規則時,Istio不會應用任何繼承概念,它將使用符合指定條件的第一個資源。
問題解決
檢視如下輸出:
Error [IST0113] (DestinationRule default-rule.istio-system) A DestinationRule
and Policy are in conflict with regards to mTLS for host
myhost.my-namespace.svc.cluster.local:8080. The DestinationRule
"istio-system/default-rule" specifies that mTLS must be true but the Policy
object "my-namespace/my-policy" specifies Plaintext.
可以看出兩個資源是衝突的:
- 策略資源
my-namespace/my-policy
使用Plaintext
來支援mutual TLS模式 - destination rule資源
istio-system/default-rule
,指定傳送到hostmyhost.my-namespace.svc.cluster.local:8080
的流量需要啟用mutual TLS
可以使用下面的方式之一來修復該問題:
- 修改策略資源
my-namespace/my-policy
來啟用mutual TLS作為認證模式。 - 修改destination rule
istio-system/default-rule
,通過移除ISTIO_MUTUAL
來禁用mutual TLS。注意default-rule
位於istio-system
名稱空間,即預設的根名稱空間中,意味著該destination rule會影響到網格中過的所有其他服務。 - 在與服務相同的名稱空間(
my-namespace
)中新增一個新的destination rule,該destination rule不指定流量策略mutual TLS。由於該規則位於與服務相同的名稱空間中,它不會覆蓋全域性destination ruleistio-system/default-rule
.
MultipleSidecarsWithoutWorkloadSelectors
Message Name | MultipleSidecarsWithoutWorkloadSelectors |
---|---|
Message Code | IST0111 |
Description | More than one sidecar resource in a namespace has no workload selector |
Level | Error |
當一個名稱空間中的多個sidecar資源沒有定義任何負載選擇器時會出現該訊息,導致不可預知的行為。更多參見Sidecar。
一個名稱空間僅允許一個sidecar資源不指定負載選擇器。
NamespaceNotInjected
Message Name | NamespaceNotInjected |
---|---|
Message Code | IST0102 |
Description | A namespace is not enabled for Istio injection. |
Level | Warning |
當一個名稱空間沒有annotation(如sidecar.istio.io/inject
.)指明該名稱空間是否需要自動注入sidecar時會出現該提示。錯誤資訊如下:
Warn [IST0102] (Namespace default) The namespace is not enabled for Istio
injection. Run 'kubectl label namespace default istio-injection=enabled' to
enable it, or 'kubectl label namespace default istio-injection=disabled' to
explicitly mark it as not needing injection Error: Analyzer found issues.
可以通過給名稱空間打標籤來解決該問題,明確宣告是否需要啟用sidecar自動注入:
$ kubectl label namespace <namespace-name> istio-injection=enabled
強烈建議明確指定sidecar注入行為。忘記註釋名稱空間是導致錯誤的常見原因。
SchemaValidationError
Message Name | SchemaValidationError |
---|---|
Message Code | IST0106 |
Description | The resource has a schema validation error. |
Level | Error |
當Istio的配置沒有通過模式驗證時會出現該錯誤。如:
Error [IST0106] (VirtualService ratings-bogus-weight-default.default) Schema validation error: percentage 888 is not in range 0..100
Istio配置為:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-bogus-weight-default
namespace: default
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
weight: 999
- destination:
host: ratings
subset: v2
weight: 888
本例中可以看到weight
元素為一個無效的值。可以通過訊息的details欄位來檢查哪個元素或值沒有符合模式要求,然後進行修正。
VirtualServiceDestinationPortSelectorRequired
Message Name | VirtualServiceDestinationPortSelectorRequired |
---|---|
Message Code | IST0112 |
Description | A VirtualService routes to a service with more than one port exposed, but does not specify which to use. |
Level | Error |
當一個virtual service路由到暴露多個port的服務,且沒有指定使用哪個埠時會出現該錯誤。這種模糊性可能導致不確定的行為。
可以在virtual service Destination中增加port欄位來解決該問題。
UnknownAnnotation
Message Name | UnknownAnnotation |
---|---|
Message Code | IST0108 |
Description | An Istio annotation is not recognized for any kind of resource |
Level | Warning |
當將格式為*.istio.io
的無法識別的註釋附加到名稱空間時,會出現此訊息。Istio僅能識別特定的annotation名稱。
ReferencedResourceNotFound
Message Name | ReferencedResourceNotFound |
---|---|
Message Code | IST0101 |
Description | A resource being referenced does not exist. |
Level | Error |
當Istio資源相關的資源不存在時會出現該錯誤。當Istio嘗試查詢引用的資源但無法找到時,將導致錯誤。錯誤資訊如:
Error [IST0101] (VirtualService httpbin.default) Referenced gateway not found: "httpbin-gateway-bogus"
本例中,VirtualService引用了一個不存在的閘道器。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http2
protocol: HTTP2
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "*"
gateways:
- httpbin-gateway-bogus # Should have been "httpbin-gateway"
http:
- route:
- destination:
host: httpbin-gateway
為了解決該問題,檢視detaild錯誤訊息中的資源型別,然後修正Istio配置即可。
PortNameIsNotUnderNamingConvention
Message Name | PortNameIsNotUnderNamingConvention |
---|---|
Message Code | IST0118 |
Description | Port name is not under naming convention. Protocol detection is applied to the port. |
Level | Info |
當埠不遵守Istio服務埠命名規範或埠未命名時會出現該錯誤。錯誤資訊如:
Info [IST0118] (Service httpbin.default) Port name foo-http (port: 80, targetPort: 80) doesn't follow the naming convention of Istio port.
對應的Service為:
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: foo-http
port: 8000
targetPort: 80
selector:
app: httpbin
可以通過將port foo-http
按照語法name: <protocol>[-<suffix>]
修改即可。
問題解決
- 如果知道服務埠的協議,使用
<protocol>[-<suffix>]
格式重新命名即可 - 如果不知道服務埠的協議,則需要從Prometheus請求metrics來獲取
- 執行請求
istio_requests_total
- 如果有輸出,可以在metrics的
request_protocol
欄位中看到使用的協議 - 如果沒有輸出,則可以保留埠不變。
- 執行請求
PodMissingProxy
Message Name | PodMissingProxy |
---|---|
Message Code | IST0103 |
Description | A pod is missing the Istio proxy. |
Level | Warning |
當沒有sidecar或sidecar不正常時會出現該錯誤。
通常是因為啟用了自動注入,但後續沒有重啟pod導致sidecar不存在。
可以使用如下命令修復:
$ kubectl rollout restart deployment