为了方便用户安装istio和操作相应的manifest,社区将原本的纯helm安装模式演变成如今的cli和operator模式(https://docs.google.com/docum...)。同时为了保证后向兼容和良好的代码复用,cli复用operator提供的命令行api,operator命令行基于helm的chart渲染进行实现。基本的模式结构如下图所示:
整体结构如下图所示:
接下来,以istioctl install --set installPackagePath=/istio/manifests --set profile=empty -f test0.yaml -f test1.yaml
为例,分析各个函数。其中test0.yaml和test1.yaml的内容如下图所示。
我们先来解释一下这个命令的含义:
--set installPackagePath=/istio/manifests
这个选项用于设置Istio安装包的路径,即指定存储Istio清单文件的目录
--set profile=empty
这个选项用于设置Istio的配置文件(profile),指定安装的Istio配置文件的配置模式。在这里选择了一个名为empty的配置模式,这可能是一种精简的配置,适用于特定的使用场景。
-f test0.yaml -f test1.yaml
这两个选项用于加载额外的配置文件。-f
后面跟着的是YAML格式的配置文件路径。这些配置文件可以用于进一步自定义Istio的安装。覆盖默认的配置选项。
# test0.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: profile: minimal hub: docker.io/istio tag: 1.1.4 components: pilot: enabled: true
# test1.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: hub: docker.io/istio tag: 1.1.5 components: pilot: enabled: true
这个函数从左到右读取并且覆盖-f标志所传入的IstioOperator.yaml,并且提取出其中的profile字段。因此提取出的profile为minimal,test0.yaml和test1.yaml的初步处理结构temp0.yaml如下所示:
# temp0.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: profile: minimal hub: docker.io/istio tag: 1.1.5 components: pilot: enabled: true
ReadYamlProfile根据--set profile=empty对ParseYAMLFiles返回的profile结果进行覆盖,因此最终的profile为empty。
这个函数从--set installPackagePath=/istio/manifests
指定的目录读取empty yaml,因为istio所提供的所有内置profile都是基于default profile,因此利用empty yaml去覆盖default profile最终得到temp1.yaml。
#empty yaml # The empty profile has everything disabled # This is useful as a base for custom user configuration apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: components: base: enabled: false pilot: enabled: false ingressGateways: - name: istio-ingressgateway enabled: false
#default yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: namespace: istio-system spec: hub: gcr.io/istio-testing tag: latest # You may override parts of meshconfig by uncommenting the following lines. meshConfig: defaultConfig: proxyMetadata: {} enablePrometheusMerge: true # Opt-out of global http2 upgrades. # Destination rule is used to opt-in. # h2_upgrade_policy: DO_NOT_UPGRADE # Traffic management feature components: base: enabled: true pilot: enabled: true # Istio Gateway feature ingressGateways: - name: istio-ingressgateway enabled: true egressGateways: - name: istio-egressgateway enabled: false # Istio CNI feature cni: enabled: false # Remote and config cluster configuration for an external istiod istiodRemote: enabled: false # Global values passed through to helm global.yaml. # Please keep this in sync with manifests/charts/global.yaml values: defaultRevision: "" global: istioNamespace: istio-system istiod: enableAnalysis: false logging: level: "default:info" logAsJson: false pilotCertProvider: istiod jwtPolicy: third-party-jwt proxy: image: proxyv2 clusterDomain: "cluster.local" resources: requests: cpu: 100m memory: 128Mi limits: cpu: 2000m memory: 1024Mi logLevel: warning componentLogLevel: "misc:error" privileged: false enableCoreDump: false statusPort: 15020 readinessInitialDelaySeconds: 1 readinessPeriodSeconds: 2 readinessFailureThreshold: 30 includeIPRanges: "*" excludeIPRanges: "" excludeOutboundPorts: "" excludeInboundPorts: "" autoInject: enabled tracer: "zipkin" proxy_init: image: proxyv2 resources: limits: cpu: 2000m memory: 1024Mi requests: cpu: 10m memory: 10Mi # Specify image pull policy if default behavior isn't desired. # Default behavior: latest images will be Always else IfNotPresent. imagePullPolicy: "" operatorManageWebhooks: false tracer: lightstep: {} zipkin: {} datadog: {} stackdriver: {} imagePullSecrets: [] oneNamespace: false defaultNodeSelector: {} configValidation: true multiCluster: enabled: false clusterName: "" omitSidecarInjectorConfigMap: false network: "" defaultResources: requests: cpu: 10m defaultPodDisruptionBudget: enabled: true priorityClassName: "" useMCP: false sds: token: aud: istio-ca sts: servicePort: 0 meshNetworks: {} mountMtlsCerts: false base: enableCRDTemplates: false validationURL: "" pilot: autoscaleEnabled: true autoscaleMin: 1 autoscaleMax: 5 replicaCount: 1 image: pilot traceSampling: 1.0 env: {} cpu: targetAverageUtilization: 80 nodeSelector: {} keepaliveMaxServerConnectionAge: 30m enableProtocolSniffingForOutbound: true enableProtocolSniffingForInbound: true deploymentLabels: podLabels: {} configMap: true telemetry: enabled: true v2: enabled: true metadataExchange: wasmEnabled: false prometheus: wasmEnabled: false enabled: true stackdriver: enabled: false logging: false monitoring: false topology: false configOverride: {} istiodRemote: injectionURL: "" gateways: istio-egressgateway: env: {} autoscaleEnabled: true type: ClusterIP name: istio-egressgateway secretVolumes: - name: egressgateway-certs secretName: istio-egressgateway-certs mountPath: /etc/istio/egressgateway-certs - name: egressgateway-ca-certs secretName: istio-egressgateway-ca-certs mountPath: /etc/istio/egressgateway-ca-certs istio-ingressgateway: autoscaleEnabled: true type: LoadBalancer name: istio-ingressgateway env: {} secretVolumes: - name: ingressgateway-certs secretName: istio-ingressgateway-certs mountPath: /etc/istio/ingressgateway-certs - name: ingressgateway-ca-certs secretName: istio-ingressgateway-ca-certs mountPath: /etc/istio/ingressgateway-ca-certs
#temp1.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: namespace: istio-system spec: components: base: enabled: false cni: enabled: false egressGateways: - enabled: false name: istio-egressgateway ingressGateways: - enabled: false name: istio-ingressgateway istiodRemote: enabled: false pilot: enabled: false hub: gcr.io/istio-testing meshConfig: defaultConfig: proxyMetadata: {}
OverlayIOP将ReadYaml(And)Profile所得到的temp0.yaml覆盖于temp1.yaml之上,得到final.yaml
#empty yaml # The empty profile has everything disabled # This is useful as a base for custom user configuration apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: components: base: enabled: false pilot: enabled: false ingressGateways: - name: istio-ingressgateway enabled: false
# final.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: creationTimestamp: null namespace: istio-system spec: components: base: enabled: false cni: enabled: false egressGateways: - enabled: false name: istio-egressgateway ingressGateways: - enabled: false name: istio-ingressgateway istiodRemote: enabled: false pilot: enabled: true hub: docker.io/istio installPackagePath: /istio/manifests meshConfig: defaultConfig: proxyMetadata: {} enablePrometheusMerge: true profile: empty tag: 1.1.5 values: base: enableCRDTemplates: false validationURL: "" defaultRevision: "" gateways: istio-egressgateway: autoscaleEnabled: true env: {} name: istio-egressgateway secretVolumes: - mountPath: /etc/istio/egressgateway-certs name: egressgateway-certs secretName: istio-egressgateway-certs - mountPath: /etc/istio/egressgateway-ca-certs name: egressgateway-ca-certs secretName: istio-egressgateway-ca-certs type: ClusterIP istio-ingressgateway: autoscaleEnabled: true env: {} name: istio-ingressgateway secretVolumes: - mountPath: /etc/istio/ingressgateway-certs name: ingressgateway-certs secretName: istio-ingressgateway-certs - mountPath: /etc/istio/ingressgateway-ca-certs name: ingressgateway-ca-certs secretName: istio-ingressgateway-ca-certs type: LoadBalancer global: configValidation: true defaultNodeSelector: {} defaultPodDisruptionBudget: enabled: true defaultResources: requests: cpu: 10m imagePullPolicy: "" imagePullSecrets: [] istioNamespace: istio-system istiod: enableAnalysis: false jwtPolicy: third-party-jwt logAsJson: false logging: level: default:info meshNetworks: {} mountMtlsCerts: false multiCluster: clusterName: "" enabled: false network: "" omitSidecarInjectorConfigMap: false oneNamespace: false operatorManageWebhooks: false pilotCertProvider: istiod priorityClassName: "" proxy: autoInject: enabled clusterDomain: cluster.local componentLogLevel: misc:error enableCoreDump: false excludeIPRanges: "" excludeInboundPorts: "" excludeOutboundPorts: "" image: proxyv2 includeIPRanges: '*' logLevel: warning privileged: false readinessFailureThreshold: 30 readinessInitialDelaySeconds: 1 readinessPeriodSeconds: 2 resources: limits: cpu: 2000m memory: 1024Mi requests: cpu: 100m memory: 128Mi statusPort: 15020 tracer: zipkin proxy_init: image: proxyv2 resources: limits: cpu: 2000m memory: 1024Mi requests: cpu: 10m memory: 10Mi sds: token: aud: istio-ca sts: servicePort: 0 tracer: datadog: {} lightstep: {} stackdriver: {} zipkin: {} useMCP: false istiodRemote: injectionURL: "" pilot: autoscaleEnabled: true autoscaleMax: 5 autoscaleMin: 1 configMap: true cpu: targetAverageUtilization: 80 deploymentLabels: null enableProtocolSniffingForInbound: true enableProtocolSniffingForOutbound: true env: {} image: pilot keepaliveMaxServerConnectionAge: 30m nodeSelector: {} podLabels: {} replicaCount: 1 traceSampling: 1 telemetry: enabled: true v2: enabled: true metadataExchange: wasmEnabled: false prometheus: enabled: true wasmEnabled: false stackdriver: configOverride: {} enabled: false logging: false monitoring: false topology: false
配置部分总结如下,operator将绝大部分面向用户的配置复杂度都隐藏在了内置profile中,其中base profile是基础演变项,演变过程为base profile -> select profile -> user config -> set flag,越往后优先级越高。在具体实践中,内置profile能满足大多数需求,若有额外需求则使用user config解决,set flag不便于管理。
前面提到过,operator要使用helm的chart rendering,因为通过GenerateConfig生成的final.yaml可以映射到helm的values.yaml。并且为了便于用于理解与维护helm chart,istio控制面的每一个组件都有一个chart与之对应,final.yaml中各个组件的配置最终映射到各个chart的values.yaml进行渲染。charts目录如下所示:
每个组件的chart渲染成功后生成所需的manifest,并利用k8s的api与apiserver进行交互,最后成功创建或更新istio正常运行所需的所有资源。
Manifest命令基本与Install命令的流程类似,只是通过helm渲染后不需要与apiserver交互并创建资源,因此不再赘述。
https://docs.google.com/document/d/11j9ZtYWNWnxQYnZy8ayZav1FMwTH6F6z6fkDYZ7V298/edit
这个文档可以好好看看。