配置验证 Webhook

Galley 配置验证确保用户授权的 Istio 配置在语法和语义上都是有效的。Galley 使用 Kubernetes ValidatingWebhookistio-galley ValidationWebhookConfiguration 有两个 webhook。

  • pilot.validation.istio.io - 服务地址路径为 /admitpilot,负责验证 Pilot 使用的配置(例如 VirtualService 、Authentication)。

  • mixer.validation.istio.io - 服务地址路径为 /admitmixer,负责验证 Mixer 使用的配置。

两个 webhook 都是在 istio-galley 服务的 443 端口上提供服务。每个 webhook 都有自己的 clientConfignamespaceSelectorrules 部分。 这两个 webhook 都适用于所有的命名空间。 namespaceSelector 应该设置为空。两个规则都适用于 Istio CRD。

看似正确的配置被拒绝

手动验证配置是否正确,必要时参考 Istio API reference

无效的配置被接受

验证 istio-galley validationwebhookconfiguration 配置存在并正确。 apiVersionapiGroupresource 无效配置的资源应会在两个 webhooks 之一的条目中被列出。

  1. $ kubectl get validatingwebhookconfiguration istio-galley -o yaml
  2. apiVersion: admissionregistration.k8s.io/v1beta1
  3. kind: ValidatingWebhookConfiguration
  4. metadata:
  5. labels:
  6. app: istio-galley
  7. name: istio-galley
  8. ownerReferences:
  9. - apiVersion: extensions/v1beta1
  10. blockOwnerDeletion: true
  11. controller: true
  12. kind: Deployment
  13. name: istio-galley
  14. uid: 5c64585d-91c6-11e8-a98a-42010a8001a8
  15. webhooks:
  16. - clientConfig:
  17. # caBundle should be non-empty. This is periodically (re)patched
  18. # every second by the webhook service using the ca-cert
  19. # from the mounted service account secret.
  20. caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1VENDQWMyZ0F3SUJBZ0lRVzVYNWpJcnJCemJmZFdLaWVoaVVSakFOQmdrcWhraUc5dzBCQVFzRkFEQWMKTVJvd0dBWURWUVFLRXhGck9ITXVZMngxYzNSbGNpNXNiMk5oYkRBZUZ3MHhPREEzTWpjeE56VTJNakJhRncweApPVEEzTWpjeE56VTJNakJhTUJ3eEdqQVlCZ05WQkFvVEVXczRjeTVqYkhWemRHVnlMbXh2WTJGc01JSUJJakFOCkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdVMi9SdWlyeTNnUzdPd2xJRCtaaGZiOEpOWnMKK05OL0dRWUsxbVozb3duaEw4dnJHdDBhenpjNXFuOXo2ZEw5Z1pPVFJXeFVCYXVJMUpOa3d0dSt2NmRjRzlkWgp0Q2JaQWloc1BLQWQ4MVRaa3RwYkNnOFdrcTRyNTh3QldRemNxMldsaFlPWHNlWGtRejdCbStOSUoyT0NRbmJwCjZYMmJ4Slc2OGdaZkg2UHlNR0libXJxaDgvZ2hISjFha3ptNGgzc0VGU1dTQ1Y2anZTZHVJL29NM2pBem5uZlUKU3JKY3VpQnBKZmJSMm1nQm4xVmFzNUJNdFpaaTBubDYxUzhyZ1ZiaHp4bWhpeFhlWU0zQzNHT3FlRUthY0N3WQo0TVczdEJFZ3NoN2ovZGM5cEt1ZG1wdFBFdit2Y2JnWjdreEhhazlOdFV2YmRGempJeTMxUS9Qd1NRSURBUUFCCm95TXdJVEFPQmdOVkhROEJBZjhFQkFNQ0FnUXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU5CZ2txaGtpRzl3MEIKQVFzRkFBT0NBUUVBTnRLSnVkQ3NtbTFzU3dlS2xKTzBIY1ZMQUFhbFk4ZERUYWVLNksyakIwRnl0MkM3ZUtGSAoya3JaOWlkbWp5Yk8xS0djMVlWQndNeWlUMGhjYWFlaTdad2g0aERRWjVRN0k3ZFFuTVMzc2taR3ByaW5idU1aCmg3Tm1WUkVnV1ZIcm9OcGZEN3pBNEVqWk9FZzkwR0J6YXUzdHNmanI4RDQ1VVRJZUw3M3hwaUxmMXhRTk10RWEKd0NSelplQ3lmSUhra2ZrTCtISVVGK0lWV1g2VWp2WTRpRDdRR0JCenpHZTluNS9KM1g5OU1Gb1F3bExjNHMrTQpnLzNQdnZCYjBwaTU5MWxveXluU3lkWDVqUG5ibDhkNEFJaGZ6OU8rUTE5UGVULy9ydXFRNENOancrZmVIbTBSCjJzYmowZDd0SjkyTzgwT2NMVDlpb05NQlFLQlk3cGlOUkE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
  21. service:
  22. # service corresponds to the Kubernetes service that implements the
  23. # webhook, e.g. istio-galley.istio-system.svc:443
  24. name: istio-galley
  25. namespace: istio-system
  26. path: /admitpilot
  27. failurePolicy: Fail
  28. name: pilot.validation.istio.io
  29. namespaceSelector: {}
  30. rules:
  31. - apiGroups:
  32. - config.istio.io
  33. apiVersions:
  34. - v1alpha2
  35. operations:
  36. - CREATE
  37. - UPDATE
  38. resources:
  39. - httpapispecs
  40. - httpapispecbindings
  41. - quotaspecs
  42. - quotaspecbindings
  43. - apiGroups:
  44. - rbac.istio.io
  45. apiVersions:
  46. - '*'
  47. operations:
  48. - CREATE
  49. - UPDATE
  50. resources:
  51. - '*'
  52. - apiGroups:
  53. - authentication.istio.io
  54. apiVersions:
  55. - '*'
  56. operations:
  57. - CREATE
  58. - UPDATE
  59. resources:
  60. - '*'
  61. - apiGroups:
  62. - networking.istio.io
  63. apiVersions:
  64. - '*'
  65. operations:
  66. - CREATE
  67. - UPDATE
  68. resources:
  69. - destinationrules
  70. - envoyfilters
  71. - gateways
  72. - virtualservices
  73. - clientConfig:
  74. # caBundle should be non-empty. This is periodically (re)patched
  75. # every second by the webhook service using the ca-cert
  76. # from the mounted service account secret.
  77. caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1VENDQWMyZ0F3SUJBZ0lRVzVYNWpJcnJCemJmZFdLaWVoaVVSakFOQmdrcWhraUc5dzBCQVFzRkFEQWMKTVJvd0dBWURWUVFLRXhGck9ITXVZMngxYzNSbGNpNXNiMk5oYkRBZUZ3MHhPREEzTWpjeE56VTJNakJhRncweApPVEEzTWpjeE56VTJNakJhTUJ3eEdqQVlCZ05WQkFvVEVXczRjeTVqYkhWemRHVnlMbXh2WTJGc01JSUJJakFOCkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdVMi9SdWlyeTNnUzdPd2xJRCtaaGZiOEpOWnMKK05OL0dRWUsxbVozb3duaEw4dnJHdDBhenpjNXFuOXo2ZEw5Z1pPVFJXeFVCYXVJMUpOa3d0dSt2NmRjRzlkWgp0Q2JaQWloc1BLQWQ4MVRaa3RwYkNnOFdrcTRyNTh3QldRemNxMldsaFlPWHNlWGtRejdCbStOSUoyT0NRbmJwCjZYMmJ4Slc2OGdaZkg2UHlNR0libXJxaDgvZ2hISjFha3ptNGgzc0VGU1dTQ1Y2anZTZHVJL29NM2pBem5uZlUKU3JKY3VpQnBKZmJSMm1nQm4xVmFzNUJNdFpaaTBubDYxUzhyZ1ZiaHp4bWhpeFhlWU0zQzNHT3FlRUthY0N3WQo0TVczdEJFZ3NoN2ovZGM5cEt1ZG1wdFBFdit2Y2JnWjdreEhhazlOdFV2YmRGempJeTMxUS9Qd1NRSURBUUFCCm95TXdJVEFPQmdOVkhROEJBZjhFQkFNQ0FnUXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU5CZ2txaGtpRzl3MEIKQVFzRkFBT0NBUUVBTnRLSnVkQ3NtbTFzU3dlS2xKTzBIY1ZMQUFhbFk4ZERUYWVLNksyakIwRnl0MkM3ZUtGSAoya3JaOWlkbWp5Yk8xS0djMVlWQndNeWlUMGhjYWFlaTdad2g0aERRWjVRN0k3ZFFuTVMzc2taR3ByaW5idU1aCmg3Tm1WUkVnV1ZIcm9OcGZEN3pBNEVqWk9FZzkwR0J6YXUzdHNmanI4RDQ1VVRJZUw3M3hwaUxmMXhRTk10RWEKd0NSelplQ3lmSUhra2ZrTCtISVVGK0lWV1g2VWp2WTRpRDdRR0JCenpHZTluNS9KM1g5OU1Gb1F3bExjNHMrTQpnLzNQdnZCYjBwaTU5MWxveXluU3lkWDVqUG5ibDhkNEFJaGZ6OU8rUTE5UGVULy9ydXFRNENOancrZmVIbTBSCjJzYmowZDd0SjkyTzgwT2NMVDlpb05NQlFLQlk3cGlOUkE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
  78. service:
  79. # service corresponds to the Kubernetes service that implements the
  80. # webhook, e.g. istio-galley.istio-system.svc:443
  81. name: istio-galley
  82. namespace: istio-system
  83. path: /admitmixer
  84. failurePolicy: Fail
  85. name: mixer.validation.istio.io
  86. namespaceSelector: {}
  87. rules:
  88. - apiGroups:
  89. - config.istio.io
  90. apiVersions:
  91. - v1alpha2
  92. operations:
  93. - CREATE
  94. - UPDATE
  95. resources:
  96. - rules
  97. - attributemanifests
  98. - circonuses
  99. - deniers
  100. - fluentds
  101. - kubernetesenvs
  102. - listcheckers
  103. - memquotas
  104. - noops
  105. - opas
  106. - prometheuses
  107. - rbacs
  108. - servicecontrols
  109. - solarwindses
  110. - stackdrivers
  111. - statsds
  112. - stdios
  113. - apikeys
  114. - authorizations
  115. - checknothings
  116. - listentries
  117. - logentries
  118. - metrics
  119. - quotas
  120. - reportnothings
  121. - servicecontrolreports
  122. - tracespans

validatingwebhookconfiguration 不存在,则需要验证 istio-galley-configuration configmap 是否存在。istio-galley 使用此 configmap 中的数据来创建和更新 validatingwebhookconfiguration

  1. $ kubectl -n istio-system get configmap istio-galley-configuration -o jsonpath='{.data}'
  2. map[validatingwebhookconfiguration.yaml:apiVersion: admissionregistration.k8s.io/v1beta1
  3. kind: ValidatingWebhookConfiguration
  4. metadata:
  5. name: istio-galley
  6. namespace: istio-system
  7. labels:
  8. app: istio-galley
  9. chart: galley-1.0.0
  10. release: istio
  11. heritage: Tiller
  12. webhooks:
  13. - name: pilot.validation.istio.io
  14. clientConfig:
  15. service:
  16. name: istio-galley
  17. namespace: istio-system
  18. path: "/admitpilot"
  19. caBundle: ""
  20. rules:
  21. - operations:
  22. (... snip ...)

如果 istio-galley-configuration 中的 webhook 数组为空,且是使用的是 helm templatehelm install 的方式,请验证 —set galley.enabled—set global.configValidation=true 选项是否已经设置。如果并使用 helm 的方式,则需要找到生成的 YAML,其中包含填充的 webhook 数组。

istio-galley 验证配置是失效关闭(fail-close)的。如果配置存在且范围正确,则 webhook 将被调用。在资源创建/更新时,如缺少 caBundle,错误证书或网络连接问题则会导致错误产生。如果 webhook 配置正确且没有发现任何错误提示,但是 webhook 未被调用,则表明群集配置存在错误。

创建配置失败并提示 x509 证书错误

x509: certificate signed by unknown authority 相关的错误通常由 webhook 配置中 caBundle 为空引起。验证它是否为空(请参阅验证 webhook 配置)。istio-galley 部署可动态使用保存在 istio-galley-configuration configmap 中的 webhook 配置和根证书会从 istio-system 命名空间中保存的 istio.istio-galley-service-account 密钥中加载。

  • 验证 istio-galley pod 正在运行:
  1. $ kubectl -n istio-system get pod -listio=galley
  2. NAME READY STATUS RESTARTS AGE
  3. istio-galley-5dbbbdb746-d676g 1/1 Running 0 2d
  • 确认使用的是 Istio 版本 >= 1.0.0。旧版本的 Galley 不能正确地 re-patch caBundle。这种情况通常发生在重新部署 istio.yaml 时,需要覆盖之前 patch 过的 caBundle
  1. $ for pod in $(kubectl -n istio-system get pod -listio=galley -o jsonpath='{.items[*].metadata.name}'); do \
  2. kubectl -n istio-system exec ${pod} -it /usr/local/bin/galley version| grep ^Version; \
  3. done
  4. Version: 1.0.0
  • 检查 Galley pod 日志是否存在错误。Patch caBundle 失败则会打印相关错误。
  1. $ for pod in $(kubectl -n istio-system get pod -listio=galley -o jsonpath='{.items[*].metadata.name}'); do \
  2. kubectl -n istio-system logs ${pod} \
  3. done
  • 如果 patch 失败,则需验证 Galley 的 RBAC 配置:
  1. $ kubectl get clusterrole istio-galley-istio-system -o yaml
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: ClusterRole
  4. metadata:
  5. labels:
  6. app: istio-galley
  7. name: istio-galley-istio-system
  8. rules:
  9. - apiGroups:
  10. - admissionregistration.k8s.io
  11. resources:
  12. - validatingwebhookconfigurations
  13. verbs:
  14. - '*'
  15. - apiGroups:
  16. - config.istio.io
  17. resources:
  18. - '*'
  19. verbs:
  20. - get
  21. - list
  22. - watch
  23. - apiGroups:
  24. - '*'
  25. resourceNames:
  26. - istio-galley
  27. resources:
  28. - deployments
  29. verbs:
  30. - get

istio-galley 需对于 validatingwebhookconfigurations 写访问权以创建和更新 istio-galley validatingwebhook 配置。

创建配置失败,提示 no such hosts 或 no endpoints available 错误

验证是失败关闭的(fail-close)。如果 istio-galley pod 没有准备好,则无法创建和更新相关配置。这种情况下,会提示如下错误: no such host (Kubernetes 1.9) 或 no endpoints available (>=1.10)的错误。

验证 istio-galley pod 正在运行且 endpoint 已准备就绪。

  1. $ kubectl -n istio-system get pod -listio=galley
  2. NAME READY STATUS RESTARTS AGE
  3. istio-galley-5dbbbdb746-d676g 1/1 Running 0 2d
  1. $ kubectl -n istio-system get endpoints istio-galley
  2. NAME ENDPOINTS AGE
  3. istio-galley 10.48.6.108:10514,10.48.6.108:443 3d

如果 pod 或 endpoint 尚未就绪,请检查 pod 日志和状态,以获取有关 webhook pod 无法启动和提供流量的原因。

  1. $ for pod in $(kubectl -n istio-system get pod -listio=galley -o jsonpath='{.items[*].metadata.name}'); do \
  2. kubectl -n istio-system logs ${pod} \
  3. done
  1. $ for pod in $(kubectl -n istio-system get pod -listio=galley -o name); do \
  2. kubectl -n istio-system describe ${pod} \
  3. done