diff --git a/README.md b/README.md index f2d2759cc..365b02e72 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ If you are willing to kickstart your Istio experience using Pipeline, check out ## Installation -The operator (`release-1.1` branch) installs the 1.1.9 version of Istio, and can run on Minikube v0.33.1+ and Kubernetes 1.10.0+. +The operator (`release-1.2` branch) installs the 1.2.2 version of Istio, and can run on Minikube v0.33.1+ and Kubernetes 1.10.0+. As a pre-requisite it needs a Kubernetes cluster (you can create one using [Pipeline](https://github.com/banzaicloud/pipeline)). diff --git a/config/README.md b/config/README.md index 55ede3a33..de01750f5 100644 --- a/config/README.md +++ b/config/README.md @@ -6,28 +6,28 @@ Firstly, you'll need to install the necessary crds and namespace with the follow ``` bases: - - github.com/banzaicloud/istio-operator/config?ref=release-1.1 + - github.com/banzaicloud/istio-operator/config?ref=release-1.2 ``` - + Secondly, you can install the operator with multiple possible configurations with the use of overlays (choose one option). - + - `basic`: installs the clusterrole, clusterrolebinding and statefulset for the operator - + ``` bases: - - github.com/banzaicloud/istio-operator/config/overlays/basic?ref=release-1.1 + - github.com/banzaicloud/istio-operator/config/overlays/basic?ref=release-1.2 ``` - `auth-proxy-enabled`: besides the basic configs, installs the auth proxy resources as well - + ``` bases: - - github.com/banzaicloud/istio-operator/config/overlays/auth-proxy-enabled?ref=release-1.1 + - github.com/banzaicloud/istio-operator/config/overlays/auth-proxy-enabled?ref=release-1.2 ``` - `prometheus-scpraping-enabled`: besides the basic configs, enables Prometheus scraping for the manager pod - + ``` bases: - - github.com/banzaicloud/istio-operator/config/overlays/prometheus-scpraping-enabled?ref=release-1.1 + - github.com/banzaicloud/istio-operator/config/overlays/prometheus-scpraping-enabled?ref=release-1.2 ``` diff --git a/config/base/crds/istio_v1beta1_istio.yaml b/config/base/crds/istio_v1beta1_istio.yaml index 95e48b936..c884214df 100644 --- a/config/base/crds/istio_v1beta1_istio.yaml +++ b/config/base/crds/istio_v1beta1_istio.yaml @@ -61,8 +61,19 @@ spec: type: string enabled: type: boolean + healthCheck: + description: Enable health checking on the Citadel CSR signing API. + https://istio.io/docs/tasks/security/health-check/ + type: boolean image: type: string + maxWorkloadCertTTL: + description: Citadel uses a flag max-workload-cert-ttl to control + the maximum lifetime for Istio certificates issued to workloads. + The default value is 90 days. If workload-cert-ttl on Citadel + or node agent is greater than max-workload-cert-ttl, Citadel will + fail issuing the certificate. + type: string nodeSelector: type: object resources: @@ -71,6 +82,12 @@ spec: items: type: object type: array + workloadCertTTL: + description: For the workloads running in Kubernetes, the lifetime + of their Istio certificates is controlled by the workload-cert-ttl + flag on Citadel. The default value is 90 days. This value should + be no greater than max-workload-cert-ttl of Citadel. + type: string type: object controlPlaneSecurityEnabled: description: ControlPlaneSecurityEnabled control plane services are @@ -263,6 +280,51 @@ spec: type: object type: array type: object + localityLB: + description: Locality based load balancing distribution or failover + settings. + properties: + distribute: + description: 'Optional: only one of distribute or failover can be + set. Explicitly specify loadbalancing weight across different + zones and geographical locations. Refer to [Locality weighted + load balancing](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/load_balancing/locality_weight) + If empty, the locality weight is set according to the endpoints + number within it.' + items: + properties: + from: + description: Originating locality, '/' separated, e.g. 'region/zone'. + type: string + to: + description: Map of upstream localities to traffic distribution + weights. The sum of all weights should be == 100. Any locality + not assigned a weight will receive no traffic. + type: object + type: object + type: array + enabled: + description: If set to true, locality based load balancing will + be enabled + type: boolean + failover: + description: 'Optional: only failover or distribute can be set. + Explicitly specify the region traffic will land on when endpoints + in local region becomes unhealthy. Should be used together with + OutlierDetection to detect unhealthy endpoints. Note: if no OutlierDetection + specified, this will not take effect.' + items: + properties: + from: + description: Originating region. + type: string + to: + description: Destination region the traffic will fail over + to when endpoints in the 'from' region becomes unhealthy. + type: string + type: object + type: array + type: object meshExpansion: description: If set to true, the pilot and citadel mtls will be exposed on the ingress gateway also the remote istios will be connected through @@ -283,6 +345,10 @@ spec: minReplicas: format: int32 type: integer + multiClusterSupport: + description: Turn it on if you use mixer that supports multi cluster + telemetry + type: boolean nodeSelector: type: object replicaCount: @@ -367,12 +433,35 @@ spec: proxy: description: Proxy configuration options properties: + componentLogLevel: + description: Per Component log level for proxy, applies to gateways + and sidecars. If a component level is not set, then the "LogLevel" + will be used. If left empty, "misc:error" is used. + type: string + dnsRefreshRate: + description: Configure the DNS refresh rate for Envoy cluster of + type STRICT_DNS This must be given it terms of seconds. For example, + 300s is valid but 5m is invalid. + pattern: ^[0-9]{1,5}s$ + type: string enableCoreDump: description: If set, newly injected sidecars will have core dumps enabled. type: boolean image: type: string + logLevel: + description: 'Log level for proxy, applies to gateways and sidecars. + If left empty, "warning" is used. Expected values are: trace|debug|info|warning|error|critical|off' + enum: + - trace + - debug + - info + - warning + - error + - critical + - "off" + type: string privileged: description: If set to true, istio-proxy container will have privileged securityContext @@ -391,6 +480,8 @@ spec: will be distributed through the SecretDiscoveryService instead of using K8S secrets to mount the certificates properties: + customTokenDirectory: + type: string enabled: description: If set to true, mTLS certificates for the sidecars will be distributed through the SecretDiscoveryService instead @@ -420,9 +511,21 @@ spec: properties: affinity: type: object + alwaysInjectSelector: + description: 'AlwaysInjectSelector: Forces the injection on pods + whose labels match this selector. It''s an array of label selectors, + that will be OR''ed, meaning we will iterate over it and stop + at the first match' + items: + type: object + type: array autoInjectionPolicyEnabled: description: This controls the 'policy' in the sidecar injector type: boolean + enableNamespacesByDefault: + description: This controls whether the webhook looks for namespaces + for injection enabled or disabled + type: boolean enabled: type: boolean image: @@ -460,6 +563,14 @@ spec: description: Logging level for CNI binary type: string type: object + neverInjectSelector: + description: 'NeverInjectSelector: Refuses the injection on pods + whose labels match this selector. It''s an array of label selectors, + that will be OR''ed, meaning we will iterate over it and stop + at the first match Takes precedence over AlwaysInjectSelector.' + items: + type: object + type: array nodeSelector: type: object replicaCount: @@ -533,7 +644,7 @@ spec: type: boolean version: description: Contains the intended Istio version - pattern: ^1.1 + pattern: ^1.2 type: string watchAdapterCRDs: description: Whether or not to establish watches for adapter-specific diff --git a/config/base/crds/istio_v1beta1_remoteistio.yaml b/config/base/crds/istio_v1beta1_remoteistio.yaml index 51cdc641b..ff7e3c1ac 100644 --- a/config/base/crds/istio_v1beta1_remoteistio.yaml +++ b/config/base/crds/istio_v1beta1_remoteistio.yaml @@ -61,8 +61,19 @@ spec: type: string enabled: type: boolean + healthCheck: + description: Enable health checking on the Citadel CSR signing API. + https://istio.io/docs/tasks/security/health-check/ + type: boolean image: type: string + maxWorkloadCertTTL: + description: Citadel uses a flag max-workload-cert-ttl to control + the maximum lifetime for Istio certificates issued to workloads. + The default value is 90 days. If workload-cert-ttl on Citadel + or node agent is greater than max-workload-cert-ttl, Citadel will + fail issuing the certificate. + type: string nodeSelector: type: object resources: @@ -71,6 +82,12 @@ spec: items: type: object type: array + workloadCertTTL: + description: For the workloads running in Kubernetes, the lifetime + of their Istio certificates is controlled by the workload-cert-ttl + flag on Citadel. The default value is 90 days. This value should + be no greater than max-workload-cert-ttl of Citadel. + type: string type: object defaultResources: description: DefaultResources are applied for all Istio components by @@ -106,12 +123,35 @@ spec: proxy: description: Proxy configuration options properties: + componentLogLevel: + description: Per Component log level for proxy, applies to gateways + and sidecars. If a component level is not set, then the "LogLevel" + will be used. If left empty, "misc:error" is used. + type: string + dnsRefreshRate: + description: Configure the DNS refresh rate for Envoy cluster of + type STRICT_DNS This must be given it terms of seconds. For example, + 300s is valid but 5m is invalid. + pattern: ^[0-9]{1,5}s$ + type: string enableCoreDump: description: If set, newly injected sidecars will have core dumps enabled. type: boolean image: type: string + logLevel: + description: 'Log level for proxy, applies to gateways and sidecars. + If left empty, "warning" is used. Expected values are: trace|debug|info|warning|error|critical|off' + enum: + - trace + - debug + - info + - warning + - error + - critical + - "off" + type: string privileged: description: If set to true, istio-proxy container will have privileged securityContext @@ -130,9 +170,21 @@ spec: properties: affinity: type: object + alwaysInjectSelector: + description: 'AlwaysInjectSelector: Forces the injection on pods + whose labels match this selector. It''s an array of label selectors, + that will be OR''ed, meaning we will iterate over it and stop + at the first match' + items: + type: object + type: array autoInjectionPolicyEnabled: description: This controls the 'policy' in the sidecar injector type: boolean + enableNamespacesByDefault: + description: This controls whether the webhook looks for namespaces + for injection enabled or disabled + type: boolean enabled: type: boolean image: @@ -170,6 +222,14 @@ spec: description: Logging level for CNI binary type: string type: object + neverInjectSelector: + description: 'NeverInjectSelector: Refuses the injection on pods + whose labels match this selector. It''s an array of label selectors, + that will be OR''ed, meaning we will iterate over it and stop + at the first match Takes precedence over AlwaysInjectSelector.' + items: + type: object + type: array nodeSelector: type: object replicaCount: diff --git a/config/base/manager/manager.yaml b/config/base/manager/manager.yaml index 769d27698..3d0374116 100644 --- a/config/base/manager/manager.yaml +++ b/config/base/manager/manager.yaml @@ -36,7 +36,7 @@ spec: containers: - command: - /manager - image: banzaicloud/istio-operator:latest-1.1 + image: banzaicloud/istio-operator:latest-1.2 imagePullPolicy: Always name: manager env: diff --git a/config/samples/istio_v1beta1_istio.yaml b/config/samples/istio_v1beta1_istio.yaml index cbfb3d0a3..b0b384654 100644 --- a/config/samples/istio_v1beta1_istio.yaml +++ b/config/samples/istio_v1beta1_istio.yaml @@ -5,7 +5,7 @@ metadata: controller-tools.k8s.io: "1.0" name: istio-sample spec: - version: "1.1.9" + version: "1.2.2" mtls: false includeIPRanges: "*" excludeIPRanges: "" @@ -19,7 +19,7 @@ spec: enabled: false pilot: enabled: true - image: "docker.io/istio/pilot:1.1.9" + image: "docker.io/istio/pilot:1.2.2" replicaCount: 1 minReplicas: 1 maxReplicas: 5 @@ -30,10 +30,10 @@ spec: memory: 2048Mi citadel: enabled: true - image: "docker.io/istio/citadel:1.1.9" + image: "docker.io/istio/citadel:1.2.2" galley: enabled: true - image: "docker.io/istio/galley:1.1.9" + image: "docker.io/istio/galley:1.2.2" replicaCount: 1 gateways: enabled: true @@ -96,13 +96,13 @@ spec: enabled: false mixer: enabled: true - image: "docker.io/istio/mixer:1.1.9" + image: "docker.io/istio/mixer:1.2.2" replicaCount: 1 minReplicas: 1 maxReplicas: 5 sidecarInjector: enabled: true - image: "docker.io/istio/sidecar_injector:1.1.9" + image: "docker.io/istio/sidecar_injector:1.2.2" replicaCount: 1 rewriteAppHTTPProbe: true autoInjectionPolicyEnabled: true @@ -116,9 +116,9 @@ spec: memory: 50Mi nodeAgent: enabled: false - image: "docker.io/istio/node-agent-k8s:1.1.9" + image: "docker.io/istio/node-agent-k8s:1.2.2" proxy: - image: "docker.io/istio/proxyv2:1.1.9" + image: "docker.io/istio/proxyv2:1.2.2" enableCoreDump: false resources: requests: @@ -128,7 +128,7 @@ spec: cpu: 2000m memory: 1024Mi proxyInit: - image: "docker.io/istio/proxy_init:1.1.9" + image: "docker.io/istio/proxy_init:1.2.2" defaultPodDisruptionBudget: enabled: true outboundTrafficPolicy: @@ -145,3 +145,15 @@ spec: accessToken: secure: true cacertPath: /etc/lightstep/cacert.pem + localityLB: + enabled: false + # distribute: + # - from: "us-central1/*" + # to: + # "us-central1/*": 80 + # "us-central2/*": 20 + # failover: + # - from: us-east + # to: eu-west + # - from: us-west + # to: us-east diff --git a/config/samples/istio_v1beta1_istio_cni.yaml b/config/samples/istio_v1beta1_istio_cni.yaml index b46df5517..3f9820094 100644 --- a/config/samples/istio_v1beta1_istio_cni.yaml +++ b/config/samples/istio_v1beta1_istio_cni.yaml @@ -5,7 +5,7 @@ metadata: controller-tools.k8s.io: "1.0" name: istio-sample spec: - version: "1.1.9" + version: "1.2.2" mtls: false autoInjectionNamespaces: - "default" diff --git a/config/samples/istio_v1beta1_istio_cni_gke.yaml b/config/samples/istio_v1beta1_istio_cni_gke.yaml index b8f3ce8f4..2a0fd3348 100644 --- a/config/samples/istio_v1beta1_istio_cni_gke.yaml +++ b/config/samples/istio_v1beta1_istio_cni_gke.yaml @@ -5,7 +5,7 @@ metadata: controller-tools.k8s.io: "1.0" name: istio-sample spec: - version: "1.1.9" + version: "1.2.2" mtls: false autoInjectionNamespaces: - "default" diff --git a/config/samples/istio_v1beta1_istio_meshexpansion.yaml b/config/samples/istio_v1beta1_istio_meshexpansion.yaml index 1bb931569..b932bf6f7 100644 --- a/config/samples/istio_v1beta1_istio_meshexpansion.yaml +++ b/config/samples/istio_v1beta1_istio_meshexpansion.yaml @@ -5,7 +5,7 @@ metadata: controller-tools.k8s.io: "1.0" name: istio-sample spec: - version: "1.1.9" + version: "1.2.2" autoInjectionNamespaces: - "default" useMCP: true diff --git a/config/samples/istio_v1beta1_istio_minimal.yaml b/config/samples/istio_v1beta1_istio_minimal.yaml index 096a7e02a..99810a523 100644 --- a/config/samples/istio_v1beta1_istio_minimal.yaml +++ b/config/samples/istio_v1beta1_istio_minimal.yaml @@ -7,7 +7,7 @@ metadata: controller-tools.k8s.io: "1.0" name: istio-sample spec: - version: "1.1.9" + version: "1.2.2" mtls: false autoInjectionNamespaces: - "default" diff --git a/config/samples/istio_v1beta1_istio_multimesh.yaml b/config/samples/istio_v1beta1_istio_multimesh.yaml index efdd689b0..48210c5dd 100644 --- a/config/samples/istio_v1beta1_istio_multimesh.yaml +++ b/config/samples/istio_v1beta1_istio_multimesh.yaml @@ -5,7 +5,7 @@ metadata: controller-tools.k8s.io: "1.0" name: multimesh spec: - version: "1.1.9" + version: "1.2.2" autoInjectionNamespaces: - "default" useMCP: true diff --git a/config/samples/istio_v1beta1_istio_nodeaffinities.yaml b/config/samples/istio_v1beta1_istio_nodeaffinities.yaml index 65c00c37c..6eabf4f5a 100644 --- a/config/samples/istio_v1beta1_istio_nodeaffinities.yaml +++ b/config/samples/istio_v1beta1_istio_nodeaffinities.yaml @@ -5,7 +5,7 @@ metadata: controller-tools.k8s.io: "1.0" name: istio-sample spec: - version: "1.1.9" + version: "1.2.2" mtls: false includeIPRanges: "*" excludeIPRanges: "" @@ -16,7 +16,7 @@ spec: enabled: false pilot: enabled: true - image: "docker.io/istio/pilot:1.1.9" + image: "docker.io/istio/pilot:1.2.2" replicaCount: 1 minReplicas: 1 maxReplicas: 5 @@ -30,10 +30,10 @@ spec: tolerationSeconds: 6000 citadel: enabled: true - image: "docker.io/istio/citadel:1.1.9" + image: "docker.io/istio/citadel:1.2.2" galley: enabled: true - image: "docker.io/istio/galley:1.1.9" + image: "docker.io/istio/galley:1.2.2" replicaCount: 1 gateways: enabled: true @@ -89,24 +89,24 @@ spec: enabled: false mixer: enabled: true - image: "docker.io/istio/mixer:1.1.9" + image: "docker.io/istio/mixer:1.2.2" replicaCount: 1 minReplicas: 1 maxReplicas: 5 sidecarInjector: enabled: true - image: "docker.io/istio/sidecar_injector:1.1.9" + image: "docker.io/istio/sidecar_injector:1.2.2" replicaCount: 1 rewriteAppHTTPProbe: true autoInjectionPolicyEnabled: true nodeAgent: enabled: false - image: "docker.io/istio/node-agent-k8s:1.1.9" + image: "docker.io/istio/node-agent-k8s:1.2.2" proxy: - image: "docker.io/istio/proxyv2:1.1.9" + image: "docker.io/istio/proxyv2:1.2.2" enableCoreDump: false proxyInit: - image: "docker.io/istio/proxy_init:1.1.9" + image: "docker.io/istio/proxy_init:1.2.2" defaultPodDisruptionBudget: enabled: true outboundTrafficPolicy: diff --git a/config/samples/istio_v1beta1_istio_sds_auth.yaml b/config/samples/istio_v1beta1_istio_sds_auth.yaml index ebdc34783..a49a56b32 100644 --- a/config/samples/istio_v1beta1_istio_sds_auth.yaml +++ b/config/samples/istio_v1beta1_istio_sds_auth.yaml @@ -5,7 +5,7 @@ metadata: controller-tools.k8s.io: "1.0" name: istio-sample spec: - version: "1.1.9" + version: "1.2.2" mtls: true autoInjectionNamespaces: - "default" @@ -20,7 +20,7 @@ spec: enabled: true sds: enabled: true - image: "docker.io/istio/node-agent-k8s:1.1.9" + image: "docker.io/istio/node-agent-k8s:1.2.2" resources: requests: cpu: 100m @@ -30,4 +30,4 @@ spec: memory: 1024Mi nodeAgent: enabled: true - image: "docker.io/istio/node-agent-k8s:1.1.9" + image: "docker.io/istio/node-agent-k8s:1.2.2" diff --git a/docs/federation/gateway/README.md b/docs/federation/gateway/README.md index 2717e85be..493e0da83 100644 --- a/docs/federation/gateway/README.md +++ b/docs/federation/gateway/README.md @@ -15,7 +15,7 @@ For demo purposes, create 3 clusters, a single node [Banzai Cloud PKE](https://b ```bash ❯ git clone https://github.com/banzaicloud/istio-operator.git ❯ cd istio-operator -❯ git checkout release-1.1 +❯ git checkout release-1.2 ``` [Pipeline platform](https://beta.banzaicloud.io/) is the easiest way to setup that environment using our [CLI tool](https://banzaicloud.com/blog/cli-ux/) ([install](https://github.com/banzaicloud/banzai-cli#installation)) for [Pipeline](https:/github.com/banzaicloud/pipeline), simply called `banzai`. diff --git a/docs/federation/gateway/samples/istio-multicluster-cr.yaml b/docs/federation/gateway/samples/istio-multicluster-cr.yaml index fe67fe23e..07738fb40 100644 --- a/docs/federation/gateway/samples/istio-multicluster-cr.yaml +++ b/docs/federation/gateway/samples/istio-multicluster-cr.yaml @@ -3,7 +3,7 @@ kind: Istio metadata: name: gateway-multicluster spec: - version: "1.1.9" + version: "1.2.2" autoInjectionNamespaces: - "default" mtls: true diff --git a/docs/federation/multimesh/README.md b/docs/federation/multimesh/README.md index b7bf0cc02..e4e83103c 100644 --- a/docs/federation/multimesh/README.md +++ b/docs/federation/multimesh/README.md @@ -15,7 +15,7 @@ For demonstrative purposes, create 2 clusters, a 2 node [Banzai Cloud PKE](https ```bash ❯ git clone https://github.com/banzaicloud/istio-operator.git ❯ cd istio-operator -❯ git checkout release-1.1 +❯ git checkout release-1.2 ``` ## Create the clusters on the Banzai Cloud Pipeline platform @@ -193,7 +193,7 @@ In order to allow access to `echo` running on the GKE cluster, we need to create For DNS resolution for services under the `*.global` domain, you need to assign these services an IP address. In this example we’ll use IPs in 127.255.0.0/16. Application traffic for these IPs will be captured by the sidecar and routed to the appropriate remote service. -> Each service (in the .global DNS domain) must have a unique IP within the cluster, but they are not need to be routable. +> Each service (in the .global DNS domain) must have a unique IP within the cluster, but they are not need to be routable. ```bash ❯ kubectl apply --context=$CTX_PKE -n default -f - < +$ kubectl describe istio -n istio-system istio -o yaml | grep "image:" + image: docker.io/istio/citadel:1.1.11 + image: docker.io/istio/galley:1.1.11 + image: docker.io/istio-mixer:1.1.11 + image: docker.io/istio-pilot:1.1.11 + image: docker.io/istio/proxyv2:1.1.11 + image: docker.io/istio/sidecar_injector:1.1.11 ``` #### Deploy sample BookInfo application -Let's make sure that Istio 1.0.7 is properly installed with Istio's BookInfo application: +Let's make sure that Istio 1.1.11 is properly installed with Istio's BookInfo application: ```bash -$ kubectl -n default apply -f https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/platform/kube/bookinfo.yaml +$ kubectl -n default apply -f https://raw.githubusercontent.com/istio/istio/release-1.1/samples/bookinfo/platform/kube/bookinfo.yaml service "details" created deployment.extensions "details-v1" created service "ratings" created @@ -157,7 +106,7 @@ deployment.extensions "reviews-v3" created service "productpage" created deployment.extensions "productpage-v1" created -$ kubectl -n default apply -f https://raw.githubusercontent.com/istio/istio/release-1.0/samples/bookinfo/networking/bookinfo-gateway.yaml +$ kubectl -n default apply -f https://raw.githubusercontent.com/istio/istio/release-1.1/samples/bookinfo/networking/bookinfo-gateway.yaml gateway.networking.istio.io "bookinfo-gateway" created virtualservice.networking.istio.io "bookinfo" created ``` @@ -169,12 +118,12 @@ $ INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jso $ open http://$INGRESS_HOST/productpage ``` -#### Install Istio 1.1.9 +#### Install Istio 1.2.2 -To install Istio 1.1.9, first we need to check out the `release-1.1` branch of our operator (this branch supports the Istio 1.1.x versions): +To install Istio 1.2.2, first we need to check out the `release-1.2` branch of our operator (this branch supports the Istio 1.2.x versions): ```bash $ git clone git@github.com:banzaicloud/istio-operator.git -$ git checkout release-1.1 +$ git checkout release-1.2 ``` > If you installed Istio operator with `make` in the previous section go to to `Install Istio Operator with make`, if you installed it with `helm` go to `Install Istio Operator with helm`. If you haven't installed Istio operator so far you can choose whichever install option you like. @@ -194,16 +143,16 @@ Alternatively, you can deploy the operator using a [Helm chart](https://github.c ```bash $ helm repo add banzaicloud-stable https://kubernetes-charts.banzaicloud.com -$ helm upgrade istio-operator --install --namespace=istio-system --set-string operator.image.tag=0.1.19 banzaicloud-stable/istio-operator +$ helm upgrade istio-operator --install --namespace=istio-system --set-string operator.image.tag=0.2.0 banzaicloud-stable/istio-operator ``` -*Note: As of now, the `0.1.19` tag is the latest version of our operator to support Istio versions 1.1.x.* +*Note: As of now, the `0.2.0` tag is the latest version of our operator to support Istio versions 1.2.x.* **Apply the new Custom Resource** -> If you've installed Istio 1.0.7 or earlier with the Istio operator, and if you check the logs of the operator pod at this point, you will see the following error message: `intended Istio version is unsupported by this version of the operator`. We need to update the Istio Custom Resource with Istio 1.1's components for the operator to be reconciled with the Istio control plane. +> If you've installed Istio 1.1.11 or earlier with the Istio operator, and if you check the logs of the operator pod at this point, you will see the following error message: `intended Istio version is unsupported by this version of the operator`. We need to update the Istio Custom Resource with Istio 1.2's components for the operator to be reconciled with the Istio control plane. -To deploy Istio 1.1.9 with its default configuration options, use the following command: +To deploy Istio 1.2.2 with its default configuration options, use the following command: ```bash $ kubectl apply -n istio-system -f config/samples/istio_v1beta1_istio.yaml @@ -225,94 +174,19 @@ istio-sidecar-injector-66cd99d8c8-bp4j7 1/1 Running 0 7m istio-telemetry-7b667c5fbb-2lfdc 2/2 Running 0 7m ``` -The `Istio` Custom Resource is showing `Available` in its status field, and the Istio components are now using `1.1.9` images: +The `Istio` Custom Resource is showing `Available` in its status field, and the Istio components are now using `1.2.2` images: ```bash -$ kubectl describe istio -n istio-system istio -Name: istio-sample -Namespace: istio-system -Labels: controller-tools.k8s.io=1.0 -Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"istio.banzaicloud.io/v1beta1","kind":"Istio","metadata":{"annotations":{},"labels":{"controller-tools.k8s.io":"1.0"},"name":"istio-sampl... -API Version: istio.banzaicloud.io/v1beta1 -Kind: Istio -Metadata: - Creation Timestamp: 2019-03-31T10:07:22Z - Finalizers: - istio-operator.finializer.banzaicloud.io - Generation: 3 - Resource Version: 21904 - Self Link: /apis/istio.banzaicloud.io/v1beta1/namespaces/istio-system/istios/istio-sample - UID: c6a095da-539c-11e9-9080-42010a9a0136 -Spec: - Auto Injection Namespaces: - default - Citadel: - Image: docker.io/istio/citadel:1.1.9 - Replica Count: 1 - Control Plane Security Enabled: false - Default Pod Disruption Budget: - Enabled: true - Exclude IP Ranges: - Galley: - Image: docker.io/istio/galley:1.1.9 - Replica Count: 1 - Gateways: - Egress: - Max Replicas: 5 - Min Replicas: 1 - Replica Count: 1 - Service Annotations: - Service Labels: - Service Type: ClusterIP - Ingress: - Max Replicas: 5 - Min Replicas: 1 - Replica Count: 1 - Service Annotations: - Service Labels: - Service Type: LoadBalancer - K8s ingress: - Enabled: false - Include IP Ranges: * - Mixer: - Image: docker.io/istio/mixer:1.1.9 - Max Replicas: 5 - Min Replicas: 1 - Replica Count: 1 - Mtls: false - Node Agent: - Enabled: false - Image: docker.io/istio/node-agent-k8s:1.1.9 - Outbound Traffic Policy: - Mode: ALLOW_ANY - Pilot: - Image: docker.io/istio/pilot:1.1.9 - Max Replicas: 5 - Min Replicas: 1 - Replica Count: 1 - Trace Sampling: 1 - Proxy: - Enable Core Dump: false - Image: docker.io/istio/proxyv2:1.1.9 - Proxy Init: - Image: docker.io/istio/proxy_init:1.1.9 - Sds: - Enabled: false - Sidecar Injector: - Image: docker.io/istio/sidecar_injector:1.1.9 - Replica Count: 1 - Rewrite App HTTP Probe: true - Tracing: - Zipkin: - Address: zipkin.istio-system:9411 - Version: 1.1.9 -Status: - Error Message: - Status: Available -Events: +$ kubectl describe istio -n istio-system istio -o yaml | grep "image:" + image: docker.io/istio/citadel:1.2.2 + image: docker.io/istio/galley:1.2.2 + image: docker.io/istio-mixer:1.2.2 + image: docker.io/istio-pilot:1.2.2 + image: docker.io/istio/proxyv2:1.2.2 + image: docker.io/istio/sidecar_injector:1.2.2 ``` -At this point, your Istio control plane is upgraded to Istio 1.1.9 and your BookInfo application should still be available at: +At this point, your Istio control plane is upgraded to Istio 1.2.2 and your BookInfo application should still be available at: ```bash $ open http://$INGRESS_HOST/productpage ``` diff --git a/pkg/apis/istio/v1beta1/defaults.go b/pkg/apis/istio/v1beta1/defaults.go index 071d4f5a2..5f48402f6 100644 --- a/pkg/apis/istio/v1beta1/defaults.go +++ b/pkg/apis/istio/v1beta1/defaults.go @@ -28,7 +28,7 @@ import ( const ( defaultImageHub = "docker.io/istio" - defaultImageVersion = "1.1.9" + defaultImageVersion = "1.2.2" defaultPilotImage = defaultImageHub + "/" + "pilot" + ":" + defaultImageVersion defaultCitadelImage = defaultImageHub + "/" + "citadel" + ":" + defaultImageVersion defaultGalleyImage = defaultImageHub + "/" + "galley" + ":" + defaultImageVersion @@ -275,6 +275,15 @@ func SetDefaults(config *Istio) { if config.Spec.ProxyInit.Image == "" { config.Spec.ProxyInit.Image = defaultProxyInitImage } + if config.Spec.Proxy.ComponentLogLevel == "" { + config.Spec.Proxy.ComponentLogLevel = "misc:error" + } + if config.Spec.Proxy.LogLevel == "" { + config.Spec.Proxy.LogLevel = "warning" + } + if config.Spec.Proxy.DNSRefreshRate == "" { + config.Spec.Proxy.DNSRefreshRate = "300s" + } // PDB config if config.Spec.DefaultPodDisruptionBudget.Enabled == nil { config.Spec.DefaultPodDisruptionBudget.Enabled = util.BoolPointer(false) @@ -323,6 +332,10 @@ func SetDefaults(config *Istio) { if config.Spec.MeshExpansion == nil { config.Spec.MeshExpansion = util.BoolPointer(defaultMeshExpansion) } + + if config.Spec.UseMCP == nil { + config.Spec.UseMCP = util.BoolPointer(true) + } } func SetRemoteIstioDefaults(remoteconfig *RemoteIstio) { diff --git a/pkg/apis/istio/v1beta1/istio_types.go b/pkg/apis/istio/v1beta1/istio_types.go index 1060c53d3..3622c7e2d 100644 --- a/pkg/apis/istio/v1beta1/istio_types.go +++ b/pkg/apis/istio/v1beta1/istio_types.go @@ -26,7 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -const supportedIstioMinorVersionRegex = "^1.1" +const supportedIstioMinorVersionRegex = "^1.2" // IstioVersion stores the intended Istio version type IstioVersion string @@ -49,6 +49,8 @@ type SDSConfiguration struct { // and pass to sds server, which will be used to request key/cert eventually // this flag is ignored if UseTrustworthyJwt is set UseNormalJwt bool `json:"useNormalJwt,omitempty"` + + CustomTokenDirectory string `json:"customTokenDirectory,omitempty"` } // PilotConfiguration defines config options for Pilot @@ -68,13 +70,19 @@ type PilotConfiguration struct { // CitadelConfiguration defines config options for Citadel type CitadelConfiguration struct { - Enabled *bool `json:"enabled,omitempty"` - Image string `json:"image,omitempty"` - CASecretName string `json:"caSecretName,omitempty"` - Resources *corev1.ResourceRequirements `json:"resources,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Image string `json:"image,omitempty"` + CASecretName string `json:"caSecretName,omitempty"` + // Enable health checking on the Citadel CSR signing API. https://istio.io/docs/tasks/security/health-check/ + HealthCheck *bool `json:"healthCheck,omitempty"` + // For the workloads running in Kubernetes, the lifetime of their Istio certificates is controlled by the workload-cert-ttl flag on Citadel. The default value is 90 days. This value should be no greater than max-workload-cert-ttl of Citadel. + WorkloadCertTTL string `json:"workloadCertTTL,omitempty"` + // Citadel uses a flag max-workload-cert-ttl to control the maximum lifetime for Istio certificates issued to workloads. The default value is 90 days. If workload-cert-ttl on Citadel or node agent is greater than max-workload-cert-ttl, Citadel will fail issuing the certificate. + MaxWorkloadCertTTL string `json:"maxWorkloadCertTTL,omitempty"` + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` } // GalleyConfiguration defines config options for Galley @@ -137,6 +145,8 @@ type MixerConfiguration struct { NodeSelector map[string]string `json:"nodeSelector,omitempty"` Affinity *corev1.Affinity `json:"affinity,omitempty"` Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + // Turn it on if you use mixer that supports multi cluster telemetry + MultiClusterSupport *bool `json:"multiClusterSupport,omitempty"` } // InitCNIConfiguration defines config for the sidecar proxy init CNI plugin @@ -174,10 +184,21 @@ type SidecarInjectorConfiguration struct { // even when mTLS is enabled. RewriteAppHTTPProbe bool `json:"rewriteAppHTTPProbe,omitempty"` // This controls the 'policy' in the sidecar injector - AutoInjectionPolicyEnabled *bool `json:"autoInjectionPolicyEnabled,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + AutoInjectionPolicyEnabled *bool `json:"autoInjectionPolicyEnabled,omitempty"` + // This controls whether the webhook looks for namespaces for injection enabled or disabled + EnableNamespacesByDefault *bool `json:"enableNamespacesByDefault,omitempty"` + // NeverInjectSelector: Refuses the injection on pods whose labels match this selector. + // It's an array of label selectors, that will be OR'ed, meaning we will iterate + // over it and stop at the first match + // Takes precedence over AlwaysInjectSelector. + NeverInjectSelector []metav1.LabelSelector `json:"neverInjectSelector,omitempty"` + // AlwaysInjectSelector: Forces the injection on pods whose labels match this selector. + // It's an array of label selectors, that will be OR'ed, meaning we will iterate + // over it and stop at the first match + AlwaysInjectSelector []metav1.LabelSelector `json:"alwaysInjectSelector,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` } // NodeAgentConfiguration defines config options for NodeAgent @@ -196,8 +217,20 @@ type ProxyConfiguration struct { // If set to true, istio-proxy container will have privileged securityContext Privileged bool `json:"privileged,omitempty"` // If set, newly injected sidecars will have core dumps enabled. - EnableCoreDump bool `json:"enableCoreDump,omitempty"` - Resources *corev1.ResourceRequirements `json:"resources,omitempty"` + EnableCoreDump bool `json:"enableCoreDump,omitempty"` + // Log level for proxy, applies to gateways and sidecars. If left empty, "warning" is used. + // Expected values are: trace|debug|info|warning|error|critical|off + // +kubebuilder:validation:Enum=trace,debug,info,warning,error,critical,off + LogLevel string `json:"logLevel,omitempty"` + // Per Component log level for proxy, applies to gateways and sidecars. If a component level is + // not set, then the "LogLevel" will be used. If left empty, "misc:error" is used. + ComponentLogLevel string `json:"componentLogLevel,omitempty"` + // Configure the DNS refresh rate for Envoy cluster of type STRICT_DNS + // This must be given it terms of seconds. For example, 300s is valid but 5m is invalid. + // +kubebuilder:validation:Pattern=^[0-9]{1,5}s$ + DNSRefreshRate string `json:"dnsRefreshRate,omitempty"` + + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` } // ProxyInitConfiguration defines config options for Proxy Init containers @@ -272,10 +305,58 @@ type IstioCoreDNS struct { Tolerations []corev1.Toleration `json:"tolerations,omitempty"` } +// Describes how traffic originating in the 'from' zone is +// distributed over a set of 'to' zones. Syntax for specifying a zone is +// {region}/{zone} and terminal wildcards are allowed on any +// segment of the specification. Examples: +// * - matches all localities +// us-west/* - all zones and sub-zones within the us-west region +type LocalityLBDistributeConfiguration struct { + // Originating locality, '/' separated, e.g. 'region/zone'. + From string `json:"from,omitempty"` + // Map of upstream localities to traffic distribution weights. The sum of + // all weights should be == 100. Any locality not assigned a weight will + // receive no traffic. + To map[string]uint32 `json:"to,omitempty"` +} + +// Specify the traffic failover policy across regions. Since zone +// failover is supported by default this only needs to be specified for +// regions when the operator needs to constrain traffic failover so that +// the default behavior of failing over to any endpoint globally does not +// apply. This is useful when failing over traffic across regions would not +// improve service health or may need to be restricted for other reasons +// like regulatory controls. +type LocalityLBFailoverConfiguration struct { + // Originating region. + From string `json:"from,omitempty"` + // Destination region the traffic will fail over to when endpoints in + // the 'from' region becomes unhealthy. + To string `json:"to,omitempty"` +} + +// Locality-weighted load balancing allows administrators to control the +// distribution of traffic to endpoints based on the localities of where the +// traffic originates and where it will terminate. +type LocalityLBConfiguration struct { + // If set to true, locality based load balancing will be enabled + Enabled *bool `json:"enabled,omitempty"` + // Optional: only one of distribute or failover can be set. + // Explicitly specify loadbalancing weight across different zones and geographical locations. + // Refer to [Locality weighted load balancing](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/load_balancing/locality_weight) + // If empty, the locality weight is set according to the endpoints number within it. + Distribute []*LocalityLBDistributeConfiguration `json:"distribute,omitempty"` + // Optional: only failover or distribute can be set. + // Explicitly specify the region traffic will land on when endpoints in local region becomes unhealthy. + // Should be used together with OutlierDetection to detect unhealthy endpoints. + // Note: if no OutlierDetection specified, this will not take effect. + Failover []*LocalityLBFailoverConfiguration `json:"failover,omitempty"` +} + // IstioSpec defines the desired state of Istio type IstioSpec struct { // Contains the intended Istio version - // +kubebuilder:validation:Pattern=^1.1 + // +kubebuilder:validation:Pattern=^1.2 Version IstioVersion `json:"version"` // MTLS enables or disables global mTLS @@ -330,7 +411,7 @@ type IstioSpec struct { WatchOneNamespace bool `json:"watchOneNamespace,omitempty"` // Use the Mesh Control Protocol (MCP) for configuring Mixer and Pilot. Requires galley. - UseMCP bool `json:"useMCP,omitempty"` + UseMCP *bool `json:"useMCP,omitempty"` // Set the default set of namespaces to which services, service entries, virtual services, destination rules should be exported to DefaultConfigVisibility string `json:"defaultConfigVisibility,omitempty"` @@ -364,6 +445,9 @@ type IstioSpec struct { // Istio CoreDNS provides DNS resolution for services in multi mesh setups IstioCoreDNS IstioCoreDNS `json:"istioCoreDNS,omitempty"` + // Locality based load balancing distribution or failover settings. + LocalityLB *LocalityLBConfiguration `json:"localityLB,omitempty"` + networkName string meshNetworks *MeshNetworks } diff --git a/pkg/apis/istio/v1beta1/istio_types_test.go b/pkg/apis/istio/v1beta1/istio_types_test.go index 7adbc4b1c..97ceeffc1 100644 --- a/pkg/apis/istio/v1beta1/istio_types_test.go +++ b/pkg/apis/istio/v1beta1/istio_types_test.go @@ -36,7 +36,7 @@ func TestStorageIstio(t *testing.T) { Namespace: "default", }, Spec: IstioSpec{ - Version: "1.1.0", + Version: "1.2.2", }, } g := gomega.NewGomegaWithT(t) diff --git a/pkg/apis/istio/v1beta1/zz_generated.deepcopy.go b/pkg/apis/istio/v1beta1/zz_generated.deepcopy.go index 334f152e4..ab8736bd0 100644 --- a/pkg/apis/istio/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/istio/v1beta1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ package v1beta1 import ( v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -32,6 +33,11 @@ func (in *CitadelConfiguration) DeepCopyInto(out *CitadelConfiguration) { *out = new(bool) **out = **in } + if in.HealthCheck != nil { + in, out := &in.HealthCheck, &out.HealthCheck + *out = new(bool) + **out = **in + } if in.Resources != nil { in, out := &in.Resources, &out.Resources *out = new(v1.ResourceRequirements) @@ -431,6 +437,11 @@ func (in *IstioSpec) DeepCopyInto(out *IstioSpec) { in.NodeAgent.DeepCopyInto(&out.NodeAgent) in.Proxy.DeepCopyInto(&out.Proxy) out.ProxyInit = in.ProxyInit + if in.UseMCP != nil { + in, out := &in.UseMCP, &out.UseMCP + *out = new(bool) + **out = **in + } in.DefaultPodDisruptionBudget.DeepCopyInto(&out.DefaultPodDisruptionBudget) out.OutboundTrafficPolicy = in.OutboundTrafficPolicy in.Tracing.DeepCopyInto(&out.Tracing) @@ -445,6 +456,11 @@ func (in *IstioSpec) DeepCopyInto(out *IstioSpec) { **out = **in } in.IstioCoreDNS.DeepCopyInto(&out.IstioCoreDNS) + if in.LocalityLB != nil { + in, out := &in.LocalityLB, &out.LocalityLB + *out = new(LocalityLBConfiguration) + (*in).DeepCopyInto(*out) + } if in.meshNetworks != nil { in, out := &in.meshNetworks, &out.meshNetworks *out = new(MeshNetworks) @@ -521,6 +537,88 @@ func (in *LightstepConfiguration) DeepCopy() *LightstepConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalityLBConfiguration) DeepCopyInto(out *LocalityLBConfiguration) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.Distribute != nil { + in, out := &in.Distribute, &out.Distribute + *out = make([]*LocalityLBDistributeConfiguration, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(LocalityLBDistributeConfiguration) + (*in).DeepCopyInto(*out) + } + } + } + if in.Failover != nil { + in, out := &in.Failover, &out.Failover + *out = make([]*LocalityLBFailoverConfiguration, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(LocalityLBFailoverConfiguration) + **out = **in + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalityLBConfiguration. +func (in *LocalityLBConfiguration) DeepCopy() *LocalityLBConfiguration { + if in == nil { + return nil + } + out := new(LocalityLBConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalityLBDistributeConfiguration) DeepCopyInto(out *LocalityLBDistributeConfiguration) { + *out = *in + if in.To != nil { + in, out := &in.To, &out.To + *out = make(map[string]uint32, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalityLBDistributeConfiguration. +func (in *LocalityLBDistributeConfiguration) DeepCopy() *LocalityLBDistributeConfiguration { + if in == nil { + return nil + } + out := new(LocalityLBDistributeConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalityLBFailoverConfiguration) DeepCopyInto(out *LocalityLBFailoverConfiguration) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalityLBFailoverConfiguration. +func (in *LocalityLBFailoverConfiguration) DeepCopy() *LocalityLBFailoverConfiguration { + if in == nil { + return nil + } + out := new(LocalityLBFailoverConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MeshNetwork) DeepCopyInto(out *MeshNetwork) { *out = *in @@ -634,6 +732,11 @@ func (in *MixerConfiguration) DeepCopyInto(out *MixerConfiguration) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.MultiClusterSupport != nil { + in, out := &in.MultiClusterSupport, &out.MultiClusterSupport + *out = new(bool) + **out = **in + } return } @@ -977,6 +1080,25 @@ func (in *SidecarInjectorConfiguration) DeepCopyInto(out *SidecarInjectorConfigu *out = new(bool) **out = **in } + if in.EnableNamespacesByDefault != nil { + in, out := &in.EnableNamespacesByDefault, &out.EnableNamespacesByDefault + *out = new(bool) + **out = **in + } + if in.NeverInjectSelector != nil { + in, out := &in.NeverInjectSelector, &out.NeverInjectSelector + *out = make([]metav1.LabelSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AlwaysInjectSelector != nil { + in, out := &in.AlwaysInjectSelector, &out.AlwaysInjectSelector + *out = make([]metav1.LabelSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector *out = make(map[string]string, len(*in)) diff --git a/pkg/crds/crds.go b/pkg/crds/crds.go index 12fc9f5ce..0d43705e1 100644 --- a/pkg/crds/crds.go +++ b/pkg/crds/crds.go @@ -20,7 +20,6 @@ import ( "fmt" "strings" - patch "github.com/banzaicloud/k8s-objectmatcher/patch" "github.com/go-logr/logr" "github.com/goph/emperror" extensionsobj "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" @@ -29,6 +28,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" + patch "github.com/banzaicloud/k8s-objectmatcher/patch" + istiov1beta1 "github.com/banzaicloud/istio-operator/pkg/apis/istio/v1beta1" "github.com/banzaicloud/istio-operator/pkg/util" ) @@ -89,36 +90,6 @@ func InitCrds() []*extensionsobj.CustomResourceDefinition { crd("QuotaSpec", "QuotaSpecs", crdConfigs[Apim], "", "", "", extensionsobj.NamespaceScoped), crd("rule", "rules", crdConfigs[Policy], "mixer", "istio.io.mixer", "core", extensionsobj.NamespaceScoped), crd("attributemanifest", "attributemanifests", crdConfigs[Policy], "mixer", "istio.io.mixer", "core", extensionsobj.NamespaceScoped), - crd("bypass", "bypasses", crdConfigs[Policy], "mixer", "bypass", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("circonus", "circonuses", crdConfigs[Policy], "mixer", "circonus", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("denier", "deniers", crdConfigs[Policy], "mixer", "denier", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("fluentd", "fluentds", crdConfigs[Policy], "mixer", "fluentd", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("kubernetesenv", "kubernetesenvs", crdConfigs[Policy], "mixer", "kubernetesenv", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("listchecker", "listcheckers", crdConfigs[Policy], "mixer", "listchecker", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("memquota", "memquotas", crdConfigs[Policy], "mixer", "memquota", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("noop", "noops", crdConfigs[Policy], "mixer", "noop", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("opa", "opas", crdConfigs[Policy], "mixer", "opa", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("prometheus", "prometheuses", crdConfigs[Policy], "mixer", "prometheus", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("rbac", "rbacs", crdConfigs[Policy], "mixer", "rbac", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("redisquota", "redisquotas", crdConfigs[Policy], "mixer", "redisquota", "mixer-adapter", extensionsobj.NamespaceScoped), // helm chart misses app:mixer label - crd("servicecontrol", "servicecontrols", crdConfigs[Policy], "mixer", "servicecontrol", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("signalfx", "signalfxs", crdConfigs[Policy], "mixer", "signalfx", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("solarwinds", "solarwindses", crdConfigs[Policy], "mixer", "solarwinds", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("stackdriver", "stackdrivers", crdConfigs[Policy], "mixer", "stackdriver", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("statsd", "statsds", crdConfigs[Policy], "mixer", "statsd", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("stdio", "stdios", crdConfigs[Policy], "mixer", "stdio", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("apikey", "apikeys", crdConfigs[Policy], "mixer", "apikey", "mixer-instance", extensionsobj.NamespaceScoped), - crd("authorization", "authorizations", crdConfigs[Policy], "mixer", "authorization", "mixer-instance", extensionsobj.NamespaceScoped), - crd("checknothing", "checknothings", crdConfigs[Policy], "mixer", "checknothing", "mixer-instance", extensionsobj.NamespaceScoped), - crd("kubernetes", "kuberneteses", crdConfigs[Policy], "mixer", "adapter.template.kubernetes", "mixer-instance", extensionsobj.NamespaceScoped), - crd("listentry", "listentries", crdConfigs[Policy], "mixer", "listentry", "mixer-instance", extensionsobj.NamespaceScoped), - crd("logentry", "logentries", crdConfigs[Policy], "mixer", "logentry", "mixer-instance", extensionsobj.NamespaceScoped), - crd("edge", "edges", crdConfigs[Policy], "mixer", "edge", "mixer-instance", extensionsobj.NamespaceScoped), - crd("metric", "metrics", crdConfigs[Policy], "mixer", "metric", "mixer-instance", extensionsobj.NamespaceScoped), - crd("quota", "quotas", crdConfigs[Policy], "mixer", "quota", "mixer-instance", extensionsobj.NamespaceScoped), - crd("reportnothing", "reportnothings", crdConfigs[Policy], "mixer", "reportnothing", "mixer-instance", extensionsobj.NamespaceScoped), - crd("servicecontrolreport", "servicecontrolreports", crdConfigs[Policy], "mixer", "servicecontrolreport", "mixer-instance", extensionsobj.NamespaceScoped), - crd("tracespan", "tracespans", crdConfigs[Policy], "mixer", "tracespan", "mixer-instance", extensionsobj.NamespaceScoped), crd("RbacConfig", "RbacConfigs", crdConfigs[Rbac], "mixer", "istio.io.mixer", "rbac", extensionsobj.NamespaceScoped), crd("ServiceRole", "ServiceRoles", crdConfigs[Rbac], "mixer", "istio.io.mixer", "rbac", extensionsobj.NamespaceScoped), crd("ServiceRoleBinding", "ServiceRoleBindings", crdConfigs[Rbac], "mixer", "istio.io.mixer", "rbac", extensionsobj.NamespaceScoped), @@ -126,10 +97,8 @@ func InitCrds() []*extensionsobj.CustomResourceDefinition { crd("instance", "instances", crdConfigs[Policy], "mixer", "instance", "mixer-instance", extensionsobj.NamespaceScoped), crd("template", "templates", crdConfigs[Policy], "mixer", "template", "mixer-template", extensionsobj.NamespaceScoped), crd("handler", "handlers", crdConfigs[Policy], "mixer", "handler", "mixer-handler", extensionsobj.NamespaceScoped), - crd("cloudwatch", "cloudwatches", crdConfigs[Policy], "mixer", "cloudwatch", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("dogstatsd", "dogstatsds", crdConfigs[Policy], "mixer", "dogstatsd", "mixer-adapter", extensionsobj.NamespaceScoped), - crd("zipkin", "zipkins", crdConfigs[Policy], "mixer", "zipkin", "mixer-adapter", extensionsobj.NamespaceScoped), crd("Sidecar", "Sidecars", crdConfigs[Networking], "istio-pilot", "", "", extensionsobj.NamespaceScoped), + crd("AuthorizationPolicy", "authorizationpolicies", crdConfigs[Rbac], "isito-pilot", "", "rbac", extensionsobj.NamespaceScoped), } } diff --git a/pkg/resources/citadel/deployment.go b/pkg/resources/citadel/deployment.go index f791c94dc..7725d568a 100644 --- a/pkg/resources/citadel/deployment.go +++ b/pkg/resources/citadel/deployment.go @@ -23,7 +23,6 @@ import ( apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/intstr" "github.com/banzaicloud/istio-operator/pkg/resources/templates" "github.com/banzaicloud/istio-operator/pkg/util" @@ -33,7 +32,6 @@ func (r *Reconciler) deployment() runtime.Object { var args = []string{ "--append-dns-names=true", "--grpc-port=8060", - "--grpc-hostname=citadel", fmt.Sprintf("--citadel-storage-namespace=%s", r.Config.Namespace), fmt.Sprintf("--custom-dns-names=istio-pilot-service-account.%[1]s:istio-pilot.%[1]s", r.Config.Namespace), "--monitoring-port=15014", @@ -51,6 +49,28 @@ func (r *Reconciler) deployment() runtime.Object { ) } + if util.PointerToBool(r.Config.Spec.Citadel.HealthCheck) { + args = append(args, + "--liveness-probe-path=/tmp/ca.liveness", + "--liveness-probe-interval=60s", + "--probe-check-interval=15s", + ) + } + + if r.Config.Spec.Citadel.WorkloadCertTTL != "" { + args = append(args, + "--workload-cert-ttl", + r.Config.Spec.Citadel.WorkloadCertTTL, + ) + } + + if r.Config.Spec.Citadel.MaxWorkloadCertTTL != "" { + args = append(args, + "--max-workload-cert-ttl", + r.Config.Spec.Citadel.MaxWorkloadCertTTL, + ) + } + var citadelContainer = apiv1.Container{ Name: "citadel", Image: r.Config.Spec.Citadel.Image, @@ -60,22 +80,28 @@ func (r *Reconciler) deployment() runtime.Object { r.Config.Spec.Citadel.Resources, r.Config.Spec.DefaultResources, ), - LivenessProbe: &apiv1.Probe{ + TerminationMessagePath: apiv1.TerminationMessagePathDefault, + TerminationMessagePolicy: apiv1.TerminationMessageReadFile, + } + + if util.PointerToBool(r.Config.Spec.Citadel.HealthCheck) { + citadelContainer.LivenessProbe = &apiv1.Probe{ Handler: apiv1.Handler{ - HTTPGet: &apiv1.HTTPGetAction{ - Path: "/version", - Port: intstr.FromInt(15014), - Scheme: apiv1.URISchemeHTTP, + Exec: &apiv1.ExecAction{ + Command: []string{ + "/usr/local/bin/istio_ca", + "probe", + "--probe-path=/tmp/ca.liveness", + "--interval=125s", + }, }, }, - InitialDelaySeconds: 5, - PeriodSeconds: 5, + InitialDelaySeconds: 60, + PeriodSeconds: 60, FailureThreshold: 30, SuccessThreshold: 1, TimeoutSeconds: 1, - }, - TerminationMessagePath: apiv1.TerminationMessagePathDefault, - TerminationMessagePolicy: apiv1.TerminationMessageReadFile, + } } if r.Config.Spec.Citadel.CASecretName != "" { diff --git a/pkg/resources/common/configmap.go b/pkg/resources/common/configmap.go index 89f05efa5..4f438a43d 100644 --- a/pkg/resources/common/configmap.go +++ b/pkg/resources/common/configmap.go @@ -104,10 +104,10 @@ func (r *Reconciler) meshConfig() string { "defaultConfig": defaultConfig, "rootNamespace": "istio-system", "connectTimeout": "10s", - "localityLbSetting": nil, + "localityLbSetting": r.getLocalityLBConfiguration(), } - if r.Config.Spec.UseMCP { + if util.PointerToBool(r.Config.Spec.UseMCP) { meshConfig["configSources"] = []map[string]interface{}{ r.defaultConfigSource(), } @@ -117,6 +117,24 @@ func (r *Reconciler) meshConfig() string { return string(marshaledConfig) } +func (r *Reconciler) getLocalityLBConfiguration() *istiov1beta1.LocalityLBConfiguration { + var localityLbConfiguration *istiov1beta1.LocalityLBConfiguration + + if r.Config.Spec.LocalityLB == nil || !util.PointerToBool(r.Config.Spec.LocalityLB.Enabled) { + return localityLbConfiguration + } + + if r.Config.Spec.LocalityLB != nil { + localityLbConfiguration = r.Config.Spec.LocalityLB.DeepCopy() + localityLbConfiguration.Enabled = nil + if localityLbConfiguration.Distribute != nil && localityLbConfiguration.Failover != nil { + localityLbConfiguration.Failover = nil + } + } + + return localityLbConfiguration +} + func (r *Reconciler) meshNetworks() string { marshaledConfig, _ := yaml.Marshal(r.Config.Spec.GetMeshNetworks()) return string(marshaledConfig) diff --git a/pkg/resources/galley/configmap.go b/pkg/resources/galley/configmap.go index cf1b61bfc..c5210ea54 100644 --- a/pkg/resources/galley/configmap.go +++ b/pkg/resources/galley/configmap.go @@ -42,6 +42,7 @@ func (r *Reconciler) configMap() runtime.Object { func (r *Reconciler) validatingWebhookConfig(ns string) string { fail := admissionv1beta1.Fail + se := admissionv1beta1.SideEffectClassNone webhook := admissionv1beta1.ValidatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ Name: webhookName, @@ -106,6 +107,7 @@ func (r *Reconciler) validatingWebhookConfig(ns string) string { }, }, FailurePolicy: &fail, + SideEffects: &se, }, { Name: "mixer.validation.istio.io", @@ -153,11 +155,18 @@ func (r *Reconciler) validatingWebhookConfig(ns string) string { "metrics", "quotas", "reportnothings", - "tracespans"}, + "tracespans", + "adapters", + "handlers", + "instances", + "templates", + "zipkins", + }, }, }, }, FailurePolicy: &fail, + SideEffects: &se, }, }, } diff --git a/pkg/resources/galley/deployment.go b/pkg/resources/galley/deployment.go index c4423303c..38e83a8fd 100644 --- a/pkg/resources/galley/deployment.go +++ b/pkg/resources/galley/deployment.go @@ -49,7 +49,7 @@ func (r *Reconciler) deployment() runtime.Object { containerArgs = append(containerArgs, "--insecure=true") } - if !r.Config.Spec.UseMCP { + if !util.PointerToBool(r.Config.Spec.UseMCP) { containerArgs = append(containerArgs, "--enable-server=false") } diff --git a/pkg/resources/gateways/deployment.go b/pkg/resources/gateways/deployment.go index 234014dbf..7b868fa03 100644 --- a/pkg/resources/gateways/deployment.go +++ b/pkg/resources/gateways/deployment.go @@ -102,6 +102,14 @@ func (r *Reconciler) deployment(gw string) runtime.Object { args = append(args, "--applicationPorts", gwConfig.ApplicationPorts) } + if r.Config.Spec.Proxy.LogLevel != "" { + args = append(args, "--proxyLogLevel", r.Config.Spec.Proxy.LogLevel) + } + + if r.Config.Spec.Proxy.ComponentLogLevel != "" { + args = append(args, "--proxyComponentLogLevel", r.Config.Spec.Proxy.ComponentLogLevel) + } + containers = append(containers, apiv1.Container{ Name: "istio-proxy", Image: r.Config.Spec.Proxy.Image, @@ -229,6 +237,15 @@ func (r *Reconciler) envVars(gwConfig *istiov1beta1.GatewayConfiguration) []apiv Name: "ISTIO_META_ROUTER_MODE", Value: "sni-dnat", }, + { + Name: "NODE_NAME", + ValueFrom: &apiv1.EnvVarSource{ + FieldRef: &apiv1.ObjectFieldSelector{ + FieldPath: "spec.nodeName", + APIVersion: "v1", + }, + }, + }, } if util.PointerToBool(gwConfig.SDS.Enabled) { envVars = append(envVars, apiv1.EnvVar{ @@ -272,7 +289,7 @@ func (r *Reconciler) volumeMounts(gw string, gwConfig *istiov1beta1.GatewayConfi if util.PointerToBool(r.Config.Spec.SDS.Enabled) { vms = append(vms, apiv1.VolumeMount{ Name: "sdsudspath", - MountPath: "/var/run/sds/uds_path", + MountPath: "/var/run/sds", ReadOnly: true, }) if r.Config.Spec.SDS.UseTrustworthyJwt { @@ -325,13 +342,11 @@ func (r *Reconciler) volumes(gw string, gwConfig *istiov1beta1.GatewayConfigurat }, } if util.PointerToBool(r.Config.Spec.SDS.Enabled) { - hostPathType := apiv1.HostPathSocket volumes = append(volumes, apiv1.Volume{ Name: "sdsudspath", VolumeSource: apiv1.VolumeSource{ HostPath: &apiv1.HostPathVolumeSource{ - Path: "/var/run/sds/uds_path", - Type: &hostPathType, + Path: "/var/run/sds", }, }, }) diff --git a/pkg/resources/gateways/gateways.go b/pkg/resources/gateways/gateways.go index cf86d392c..d7d0a36f6 100644 --- a/pkg/resources/gateways/gateways.go +++ b/pkg/resources/gateways/gateways.go @@ -91,6 +91,7 @@ func (r *Reconciler) Reconcile(log logr.Logger) error { var rsv = []resources.ResourceVariationWithDesiredState{ {ResourceVariation: r.serviceAccount}, + // TODO: remove {ResourceVariation: r.clusterRole}, {ResourceVariation: r.clusterRoleBinding}, {ResourceVariation: r.deployment}, diff --git a/pkg/resources/mixer/deployment.go b/pkg/resources/mixer/deployment.go index df934c270..67172f9ea 100644 --- a/pkg/resources/mixer/deployment.go +++ b/pkg/resources/mixer/deployment.go @@ -50,37 +50,10 @@ func (r *Reconciler) deployment(t string) runtime.Object { }, Spec: apiv1.PodSpec{ ServiceAccountName: serviceAccountName, - Volumes: []apiv1.Volume{ - { - Name: "istio-certs", - VolumeSource: apiv1.VolumeSource{ - Secret: &apiv1.SecretVolumeSource{ - SecretName: fmt.Sprintf("istio.%s", serviceAccountName), - Optional: util.BoolPointer(true), - DefaultMode: util.IntPointer(420), - }, - }, - }, - { - Name: "uds-socket", - VolumeSource: apiv1.VolumeSource{ - EmptyDir: &apiv1.EmptyDirVolumeSource{}, - }, - }, - { - Name: fmt.Sprintf("%s-adapter-secret", t), - VolumeSource: apiv1.VolumeSource{ - Secret: &apiv1.SecretVolumeSource{ - SecretName: fmt.Sprintf("%s-adapter-secret", t), - Optional: util.BoolPointer(true), - DefaultMode: util.IntPointer(420), - }, - }, - }, - }, - Affinity: r.Config.Spec.Mixer.Affinity, - NodeSelector: r.Config.Spec.Mixer.NodeSelector, - Tolerations: r.Config.Spec.Mixer.Tolerations, + Volumes: r.volumes(t), + Affinity: r.Config.Spec.Mixer.Affinity, + NodeSelector: r.Config.Spec.Mixer.NodeSelector, + Tolerations: r.Config.Spec.Mixer.Tolerations, Containers: []apiv1.Container{ r.mixerContainer(t, r.Config.Namespace), r.istioProxyContainer(t), @@ -91,6 +64,69 @@ func (r *Reconciler) deployment(t string) runtime.Object { } } +func (r *Reconciler) volumes(t string) []apiv1.Volume { + volumes := []apiv1.Volume{ + { + Name: "istio-certs", + VolumeSource: apiv1.VolumeSource{ + Secret: &apiv1.SecretVolumeSource{ + SecretName: fmt.Sprintf("istio.%s", serviceAccountName), + Optional: util.BoolPointer(true), + DefaultMode: util.IntPointer(420), + }, + }, + }, + { + Name: "uds-socket", + VolumeSource: apiv1.VolumeSource{ + EmptyDir: &apiv1.EmptyDirVolumeSource{}, + }, + }, + { + Name: fmt.Sprintf("%s-adapter-secret", t), + VolumeSource: apiv1.VolumeSource{ + Secret: &apiv1.SecretVolumeSource{ + SecretName: fmt.Sprintf("%s-adapter-secret", t), + Optional: util.BoolPointer(true), + DefaultMode: util.IntPointer(420), + }, + }, + }, + } + + if util.PointerToBool(r.Config.Spec.SDS.Enabled) { + volumes = append(volumes, apiv1.Volume{ + Name: "sds-uds-path", + VolumeSource: apiv1.VolumeSource{ + HostPath: &apiv1.HostPathVolumeSource{ + Path: "/var/run/sds", + }, + }, + }) + if r.Config.Spec.SDS.UseTrustworthyJwt { + volumes = append(volumes, apiv1.Volume{ + Name: "istio-token", + VolumeSource: apiv1.VolumeSource{ + Projected: &apiv1.ProjectedVolumeSource{ + Sources: []apiv1.VolumeProjection{ + { + ServiceAccountToken: &apiv1.ServiceAccountTokenProjection{ + Path: "istio-token", + ExpirationSeconds: util.Int64Pointer(43200), + Audience: "cluster.local", + }, + }, + }, + DefaultMode: util.IntPointer(420), + }, + }, + }) + } + } + + return volumes +} + func (r *Reconciler) mixerContainer(t string, ns string) apiv1.Container { containerArgs := []string{ "--address", @@ -106,7 +142,7 @@ func (r *Reconciler) mixerContainer(t string, ns string) apiv1.Container { "http://"+r.Config.Spec.Tracing.Zipkin.Address+"/api/v1/spans") } - if r.Config.Spec.UseMCP { + if util.PointerToBool(r.Config.Spec.UseMCP) { if r.Config.Spec.ControlPlaneSecurityEnabled { containerArgs = append(containerArgs, "--configStoreURL", "mcps://istio-galley."+r.Config.Namespace+".svc:9901") if t == "telemetry" { @@ -143,7 +179,7 @@ func (r *Reconciler) mixerContainer(t string, ns string) apiv1.Container { ReadOnly: true, }, } - if r.Config.Spec.UseMCP { + if util.PointerToBool(r.Config.Spec.UseMCP) { volumeMounts = append(volumeMounts, apiv1.VolumeMount{ Name: "istio-certs", MountPath: "/etc/certs", @@ -197,6 +233,32 @@ func (r *Reconciler) mixerContainer(t string, ns string) apiv1.Container { } func (r *Reconciler) istioProxyContainer(t string) apiv1.Container { + vms := []apiv1.VolumeMount{ + { + Name: "istio-certs", + MountPath: "/etc/certs", + ReadOnly: true, + }, + { + Name: "uds-socket", + MountPath: "/sock", + }, + } + + if util.PointerToBool(r.Config.Spec.SDS.Enabled) { + vms = append(vms, apiv1.VolumeMount{ + Name: "sds-uds-path", + MountPath: "/var/run/sds", + ReadOnly: true, + }) + if r.Config.Spec.SDS.UseTrustworthyJwt { + vms = append(vms, apiv1.VolumeMount{ + Name: "istio-token", + MountPath: "/var/run/secrets/tokens", + }) + } + } + return apiv1.Container{ Name: "istio-proxy", Image: r.Config.Spec.Proxy.Image, @@ -222,17 +284,7 @@ func (r *Reconciler) istioProxyContainer(t string) apiv1.Container { r.Config.Spec.Proxy.Resources, r.Config.Spec.DefaultResources, ), - VolumeMounts: []apiv1.VolumeMount{ - { - Name: "istio-certs", - MountPath: "/etc/certs", - ReadOnly: true, - }, - { - Name: "uds-socket", - MountPath: "/sock", - }, - }, + VolumeMounts: vms, TerminationMessagePath: apiv1.TerminationMessagePathDefault, TerminationMessagePolicy: apiv1.TerminationMessageReadFile, } diff --git a/pkg/resources/mixer/kubernetes.go b/pkg/resources/mixer/kubernetes.go index 954a4de03..da6dd03c7 100644 --- a/pkg/resources/mixer/kubernetes.go +++ b/pkg/resources/mixer/kubernetes.go @@ -42,21 +42,24 @@ func (r *Reconciler) kubernetesEnvHandler() *k8sutil.DynamicObject { } func (r *Reconciler) attributesKubernetes() *k8sutil.DynamicObject { - return &k8sutil.DynamicObject{ + attributes := &k8sutil.DynamicObject{ Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "kuberneteses", + Resource: "instances", }, - Kind: "kubernetes", + Kind: "instance", Name: "attributes", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "source_uid": `source.uid | ""`, - "source_ip": `source.ip | ip("0.0.0.0")`, - "destination_uid": `destination.uid | ""`, - "destination_port": `destination.port | 0`, - "attribute_bindings": map[string]interface{}{ + "compiledTemplate": "kubernetes", + "params": map[string]interface{}{ + "source_uid": `source.uid | ""`, + "source_ip": `source.ip | ip("0.0.0.0")`, + "destination_uid": `destination.uid | ""`, + "destination_port": `destination.port | 0`, + }, + "attributeBindings": map[string]string{ "source.ip": `$out.source_pod_ip | ip("0.0.0.0")`, "source.uid": `$out.source_pod_uid | "unknown"`, "source.labels": `$out.source_labels | emptyStringMap()`, @@ -67,7 +70,7 @@ func (r *Reconciler) attributesKubernetes() *k8sutil.DynamicObject { "source.workload.uid": `$out.source_workload_uid | "unknown"`, "source.workload.name": `$out.source_workload_name | "unknown"`, "source.workload.namespace": `$out.source_workload_namespace | "unknown"`, - "source.cluster.id": `$out.source_cluster_id | "unknown"`, + "source.cluster.id": `"unknown"`, "destination.ip": `$out.destination_pod_ip | ip("0.0.0.0")`, "destination.uid": `$out.destination_pod_uid | "unknown"`, "destination.labels": `$out.destination_labels | emptyStringMap()`, @@ -79,11 +82,21 @@ func (r *Reconciler) attributesKubernetes() *k8sutil.DynamicObject { "destination.workload.uid": `$out.destination_workload_uid | "unknown"`, "destination.workload.name": `$out.destination_workload_name | "unknown"`, "destination.workload.namespace": `$out.destination_workload_namespace | "unknown"`, - "destination.cluster.id": `$out.destination_cluster_id | "unknown"`, + "destination.cluster.id": `"unknown"`, }, }, Owner: r.Config, } + + if util.PointerToBool(r.Config.Spec.Mixer.MultiClusterSupport) { + if bindings, ok := attributes.Spec["attributeBindings"].(map[string]string); ok { + bindings["source.cluster.id"] = `$out.source_cluster_id | "unknown"` + bindings["destination.cluster.id"] = `$out.destination_cluster_id | "unknown"` + attributes.Spec["attributeBindings"] = bindings + } + } + + return attributes } func (r *Reconciler) kubeAttrRule() *k8sutil.DynamicObject { @@ -100,7 +113,7 @@ func (r *Reconciler) kubeAttrRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "kubernetesenv", - "instances": util.EmptyTypedStrSlice("attributes.kubernetes"), + "instances": util.EmptyTypedStrSlice("attributes"), }, }, }, @@ -122,7 +135,7 @@ func (r *Reconciler) tcpKubeAttrRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "kubernetesenv", - "instances": util.EmptyTypedStrSlice("attributes.kubernetes"), + "instances": util.EmptyTypedStrSlice("attributes"), }, }, "match": `context.protocol == "tcp"`, diff --git a/pkg/resources/mixer/logging.go b/pkg/resources/mixer/logging.go index a0c2e9c2a..47fdd4c0e 100644 --- a/pkg/resources/mixer/logging.go +++ b/pkg/resources/mixer/logging.go @@ -48,58 +48,61 @@ func (r *Reconciler) accessLogLogentry() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "logentries", + Resource: "instances", }, - Kind: "logentry", + Kind: "instance", Name: "accesslog", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "severity": `"Info"`, - "timestamp": "request.time", - "variables": map[string]interface{}{ - "sourceIp": `source.ip | ip("0.0.0.0")`, - "sourceApp": `source.labels["app"] | ""`, - "sourcePrincipal": `source.principal | ""`, - "sourceName": `source.name | ""`, - "sourceWorkload": `source.workload.name | ""`, - "sourceNamespace": `source.namespace | ""`, - "sourceOwner": `source.owner | ""`, - "destinationApp": `destination.labels["app"] | ""`, - "destinationIp": `destination.ip | ip("0.0.0.0")`, - "destinationServiceHost": `destination.service.host | ""`, - "destinationWorkload": `destination.workload.name | ""`, - "destinationName": `destination.name | ""`, - "destinationNamespace": `destination.namespace | ""`, - "destinationOwner": `destination.owner | ""`, - "destinationPrincipal": `destination.principal | ""`, - "apiClaims": `request.auth.raw_claims | ""`, - "apiKey": `request.api_key | request.headers["x-api-key"] | ""`, - "protocol": `request.scheme | context.protocol | "http"`, - "method": `request.method | ""`, - "url": `request.path | ""`, - "responseCode": `response.code | 0`, - "responseFlags": `context.proxy_error_code | ""`, - "responseSize": `response.size | 0`, - "permissiveResponseCode": `rbac.permissive.response_code | "none"`, - "permissiveResponsePolicyID": `rbac.permissive.effective_policy_id | "none"`, - "requestSize": `request.size | 0`, - "requestId": `request.headers["x-request-id"] | ""`, - "clientTraceId": `request.headers["x-client-trace-id"] | ""`, - "latency": `response.duration | "0ms"`, - "connection_security_policy": `conditional((context.reporter.kind | "inbound") == "outbound", "unknown", conditional(connection.mtls | false, "mutual_tls", "none"))`, - "requestedServerName": `connection.requested_server_name | ""`, - "userAgent": `request.useragent | ""`, - "responseTimestamp": `response.time`, - "receivedBytes": `request.total_size | 0`, - "sentBytes": `response.total_size | 0`, - "referer": `request.referer | ""`, - "httpAuthority": `request.headers[":authority"] | request.host | ""`, - "xForwardedFor": `request.headers["x-forwarded-for"] | "0.0.0.0"`, - "reporter": `conditional((context.reporter.kind | "inbound") == "outbound", "source", "destination")`, - "grpcStatus": `response.grpc_status | ""`, - "grpcMessage": `response.grpc_message | ""`, + "compiledTemplate": "logentry", + "params": map[string]interface{}{ + "severity": `"Info"`, + "timestamp": "request.time", + "variables": map[string]interface{}{ + "sourceIp": `source.ip | ip("0.0.0.0")`, + "sourceApp": `source.labels["app"] | ""`, + "sourcePrincipal": `source.principal | ""`, + "sourceName": `source.name | ""`, + "sourceWorkload": `source.workload.name | ""`, + "sourceNamespace": `source.namespace | ""`, + "sourceOwner": `source.owner | ""`, + "destinationApp": `destination.labels["app"] | ""`, + "destinationIp": `destination.ip | ip("0.0.0.0")`, + "destinationServiceHost": `destination.service.host | ""`, + "destinationWorkload": `destination.workload.name | ""`, + "destinationName": `destination.name | ""`, + "destinationNamespace": `destination.namespace | ""`, + "destinationOwner": `destination.owner | ""`, + "destinationPrincipal": `destination.principal | ""`, + "apiClaims": `request.auth.raw_claims | ""`, + "apiKey": `request.api_key | request.headers["x-api-key"] | ""`, + "protocol": `request.scheme | context.protocol | "http"`, + "method": `request.method | ""`, + "url": `request.path | ""`, + "responseCode": `response.code | 0`, + "responseFlags": `context.proxy_error_code | ""`, + "responseSize": `response.size | 0`, + "permissiveResponseCode": `rbac.permissive.response_code | "none"`, + "permissiveResponsePolicyID": `rbac.permissive.effective_policy_id | "none"`, + "requestSize": `request.size | 0`, + "requestId": `request.headers["x-request-id"] | ""`, + "clientTraceId": `request.headers["x-client-trace-id"] | ""`, + "latency": `response.duration | "0ms"`, + "connection_security_policy": `conditional((context.reporter.kind | "inbound") == "outbound", "unknown", conditional(connection.mtls | false, "mutual_tls", "none"))`, + "requestedServerName": `connection.requested_server_name | ""`, + "userAgent": `request.useragent | ""`, + "responseTimestamp": `response.time`, + "receivedBytes": `request.total_size | 0`, + "sentBytes": `response.total_size | 0`, + "referer": `request.referer | ""`, + "httpAuthority": `request.headers[":authority"] | request.host | ""`, + "xForwardedFor": `request.headers["x-forwarded-for"] | "0.0.0.0"`, + "reporter": `conditional((context.reporter.kind | "inbound") == "outbound", "source", "destination")`, + "grpcStatus": `response.grpc_status | ""`, + "grpcMessage": `response.grpc_message | ""`, + }, + "monitored_resource_type": `"global"`, }, - "monitored_resource_type": `"global"`, }, Owner: r.Config, } @@ -110,43 +113,46 @@ func (r *Reconciler) tcpAccessLogLogentry() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "logentries", + Resource: "instances", }, - Kind: "logentry", + Kind: "instance", Name: "tcpaccesslog", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "severity": `"Info"`, - "timestamp": `context.time | timestamp("2017-01-01T00:00:00Z")`, - "variables": map[string]interface{}{ - "connectionEvent": `connection.event | ""`, - "sourceIp": `source.ip | ip("0.0.0.0")`, - "sourceApp": `source.labels["app"] | ""`, - "sourcePrincipal": `source.principal | ""`, - "sourceName": `source.name | ""`, - "sourceWorkload": `source.workload.name | ""`, - "sourceNamespace": `source.namespace | ""`, - "sourceOwner": `source.owner | ""`, - "destinationApp": `destination.labels["app"] | ""`, - "destinationIp": `destination.ip | ip("0.0.0.0")`, - "destinationServiceHost": `destination.service.host | ""`, - "destinationWorkload": `destination.workload.name | ""`, - "destinationName": `destination.name | ""`, - "destinationNamespace": `destination.namespace | ""`, - "destinationOwner": `destination.owner | ""`, - "destinationPrincipal": `destination.principal | ""`, - "protocol": `context.protocol | "tcp"`, - "connectionDuration": `connection.duration | "0ms"`, - "connection_security_policy": `conditional((context.reporter.kind | "inbound") == "outbound", "unknown", conditional(connection.mtls | false, "mutual_tls", "none"))`, - "requestedServerName": `connection.requested_server_name | ""`, - "receivedBytes": `connection.received.bytes | 0`, - "sentBytes": `connection.sent.bytes | 0`, - "totalReceivedBytes": `connection.received.bytes_total | 0`, - "totalSentBytes": `connection.sent.bytes_total | 0`, - "reporter": `conditional((context.reporter.kind | "inbound") == "outbound", "source", "destination")`, - "responseFlags": `context.proxy_error_code | ""`, + "compiledTemplate": "logentry", + "params": map[string]interface{}{ + "severity": `"Info"`, + "timestamp": `context.time | timestamp("2017-01-01T00:00:00Z")`, + "variables": map[string]interface{}{ + "connectionEvent": `connection.event | ""`, + "sourceIp": `source.ip | ip("0.0.0.0")`, + "sourceApp": `source.labels["app"] | ""`, + "sourcePrincipal": `source.principal | ""`, + "sourceName": `source.name | ""`, + "sourceWorkload": `source.workload.name | ""`, + "sourceNamespace": `source.namespace | ""`, + "sourceOwner": `source.owner | ""`, + "destinationApp": `destination.labels["app"] | ""`, + "destinationIp": `destination.ip | ip("0.0.0.0")`, + "destinationServiceHost": `destination.service.host | ""`, + "destinationWorkload": `destination.workload.name | ""`, + "destinationName": `destination.name | ""`, + "destinationNamespace": `destination.namespace | ""`, + "destinationOwner": `destination.owner | ""`, + "destinationPrincipal": `destination.principal | ""`, + "protocol": `context.protocol | "tcp"`, + "connectionDuration": `connection.duration | "0ms"`, + "connection_security_policy": `conditional((context.reporter.kind | "inbound") == "outbound", "unknown", conditional(connection.mtls | false, "mutual_tls", "none"))`, + "requestedServerName": `connection.requested_server_name | ""`, + "receivedBytes": `connection.received.bytes | 0`, + "sentBytes": `connection.sent.bytes | 0`, + "totalReceivedBytes": `connection.received.bytes_total | 0`, + "totalSentBytes": `connection.sent.bytes_total | 0`, + "reporter": `conditional((context.reporter.kind | "inbound") == "outbound", "source", "destination")`, + "responseFlags": `context.proxy_error_code | ""`, + }, + "monitored_resource_type": `"global"`, }, - "monitored_resource_type": `"global"`, }, Owner: r.Config, } @@ -166,7 +172,7 @@ func (r *Reconciler) stdioRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "stdio", - "instances": util.EmptyTypedStrSlice("accesslog.logentry"), + "instances": util.EmptyTypedStrSlice("accesslog"), }, }, "match": `context.protocol == "http" || context.protocol == "grpc"`, @@ -189,7 +195,7 @@ func (r *Reconciler) stdioTcpRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "stdio", - "instances": util.EmptyTypedStrSlice("tcpaccesslog.logentry"), + "instances": util.EmptyTypedStrSlice("tcpaccesslog"), }, }, "match": `context.protocol == "tcp"`, diff --git a/pkg/resources/mixer/monitoring.go b/pkg/resources/mixer/monitoring.go index 4a2414db0..cb0ec8fc9 100644 --- a/pkg/resources/mixer/monitoring.go +++ b/pkg/resources/mixer/monitoring.go @@ -39,13 +39,13 @@ func (r *Reconciler) prometheusHandler() *k8sutil.DynamicObject { "metrics": []map[string]interface{}{ { "name": "requests_total", - "instance_name": "requestcount.metric." + r.Config.Namespace, + "instance_name": "requestcount.instance." + r.Config.Namespace, "kind": "COUNTER", "label_names": metricLabels(), }, { "name": "request_duration_seconds", - "instance_name": "requestduration.metric." + r.Config.Namespace, + "instance_name": "requestduration.instance." + r.Config.Namespace, "kind": "DISTRIBUTION", "label_names": metricLabels(), "buckets": map[string]interface{}{ @@ -56,7 +56,7 @@ func (r *Reconciler) prometheusHandler() *k8sutil.DynamicObject { }, { "name": "request_bytes", - "instance_name": "requestsize.metric." + r.Config.Namespace, + "instance_name": "requestsize.instance." + r.Config.Namespace, "kind": "DISTRIBUTION", "label_names": metricLabels(), "buckets": map[string]interface{}{ @@ -69,7 +69,7 @@ func (r *Reconciler) prometheusHandler() *k8sutil.DynamicObject { }, { "name": "response_bytes", - "instance_name": "responsesize.metric." + r.Config.Namespace, + "instance_name": "responsesize.instance." + r.Config.Namespace, "kind": "DISTRIBUTION", "label_names": metricLabels(), "buckets": map[string]interface{}{ @@ -82,25 +82,25 @@ func (r *Reconciler) prometheusHandler() *k8sutil.DynamicObject { }, { "name": "tcp_sent_bytes_total", - "instance_name": "tcpbytesent.metric." + r.Config.Namespace, + "instance_name": "tcpbytesent.instance." + r.Config.Namespace, "kind": "COUNTER", "label_names": tcpMetricLabels(), }, { "name": "tcp_received_bytes_total", - "instance_name": "tcpbytereceived.metric." + r.Config.Namespace, + "instance_name": "tcpbytereceived.instance." + r.Config.Namespace, "kind": "COUNTER", "label_names": tcpMetricLabels(), }, { "name": "tcp_connections_opened_total", - "instance_name": "tcpconnectionsopened.metric." + r.Config.Namespace, + "instance_name": "tcpconnectionsopened.instance." + r.Config.Namespace, "kind": "COUNTER", "label_names": tcpMetricLabels(), }, { "name": "tcp_connections_closed_total", - "instance_name": "tcpconnectionsclosed.metric." + r.Config.Namespace, + "instance_name": "tcpconnectionsclosed.instance." + r.Config.Namespace, "kind": "COUNTER", "label_names": tcpMetricLabels(), }, @@ -116,15 +116,18 @@ func (r *Reconciler) requestCountMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "requestcount", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": "1", - "dimensions": metricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": "1", + "dimensions": metricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -135,15 +138,18 @@ func (r *Reconciler) requestDurationMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "requestduration", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": `response.duration | "0ms"`, - "dimensions": metricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": `response.duration | "0ms"`, + "dimensions": metricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -154,15 +160,18 @@ func (r *Reconciler) requestSizeMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "requestsize", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": `request.size | 0`, - "dimensions": metricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": `request.size | 0`, + "dimensions": metricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -173,15 +182,18 @@ func (r *Reconciler) responseSizeMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "responsesize", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": `response.size | 0`, - "dimensions": metricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": `response.size | 0`, + "dimensions": metricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -192,15 +204,18 @@ func (r *Reconciler) tcpByteSentMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "tcpbytesent", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": `connection.sent.bytes | 0`, - "dimensions": tcpMetricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": `connection.sent.bytes | 0`, + "dimensions": tcpMetricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -211,15 +226,18 @@ func (r *Reconciler) tcpByteReceivedMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "tcpbytereceived", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": `connection.received.bytes | 0`, - "dimensions": tcpMetricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": `connection.received.bytes | 0`, + "dimensions": tcpMetricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -230,15 +248,18 @@ func (r *Reconciler) tcpConnectionsOpenedMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "tcpconnectionsopened", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": "1", - "dimensions": tcpMetricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": "1", + "dimensions": tcpMetricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -249,15 +270,18 @@ func (r *Reconciler) tcpConnectionsClosedMetric() *k8sutil.DynamicObject { Gvr: schema.GroupVersionResource{ Group: "config.istio.io", Version: "v1alpha2", - Resource: "metrics", + Resource: "instances", }, - Kind: "metric", + Kind: "instance", Name: "tcpconnectionsclosed", Namespace: r.Config.Namespace, Spec: map[string]interface{}{ - "value": "1", - "dimensions": tcpMetricDimensions(), - "monitored_resource_type": `"UNSPECIFIED"`, + "compiledTemplate": "metric", + "params": map[string]interface{}{ + "value": "1", + "dimensions": tcpMetricDimensions(), + "monitored_resource_type": `"UNSPECIFIED"`, + }, }, Owner: r.Config, } @@ -277,10 +301,10 @@ func (r *Reconciler) promHttpRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "prometheus", - "instances": util.EmptyTypedStrSlice("requestcount.metric", "requestduration.metric", "requestsize.metric", "responsesize.metric"), + "instances": util.EmptyTypedStrSlice("requestcount", "requestduration", "requestsize", "responsesize"), }, }, - "match": `(context.protocol == "http" || context.protocol == "grpc") && (match((request.useragent | "-"), "kube-probe*") == false)`, + "match": `(context.protocol == "http" || context.protocol == "grpc") && (match((request.useragent | "-"), "kube-probe*") == false) && (match((request.useragent | "-"), "Prometheus*") == false)`, }, Owner: r.Config, } @@ -300,7 +324,7 @@ func (r *Reconciler) promTcpRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "prometheus", - "instances": util.EmptyTypedStrSlice("tcpbytesent.metric", "tcpbytereceived.metric"), + "instances": util.EmptyTypedStrSlice("tcpbytesent", "tcpbytereceived"), }, }, "match": `context.protocol == "tcp"`, @@ -323,7 +347,7 @@ func (r *Reconciler) promTcpConnectionOpenRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "prometheus", - "instances": util.EmptyTypedStrSlice("tcpconnectionsopened.metric"), + "instances": util.EmptyTypedStrSlice("tcpconnectionsopened"), }, }, "match": `context.protocol == "tcp" && ((connection.event | "na") == "open")`, @@ -346,7 +370,7 @@ func (r *Reconciler) promTcpConnectionClosedRule() *k8sutil.DynamicObject { "actions": []interface{}{ map[string]interface{}{ "handler": "prometheus", - "instances": util.EmptyTypedStrSlice("tcpconnectionsclosed.metric"), + "instances": util.EmptyTypedStrSlice("tcpconnectionsclosed"), }, }, "match": `context.protocol == "tcp" && ((connection.event | "na") == "close")`, @@ -368,13 +392,13 @@ func metricDimensions() map[string]interface{} { func tcpMetricDimensions() map[string]interface{} { return map[string]interface{}{ - "reporter": `conditional((context.reporter.kind | "inbound") == "outbound", "source", "destination")`, - "source_workload": `source.workload.name | "unknown"`, - "source_workload_namespace": `source.workload.namespace | "unknown"`, - "source_principal": `source.principal | "unknown"`, - "source_app": `source.labels["app"] | "unknown"`, - "source_version": `source.labels["version"] | "unknown"`, - "source_cluster_id": `source.cluster.id | "unknown"`, + "reporter": `conditional((context.reporter.kind | "inbound") == "outbound", "source", "destination")`, + "source_workload": `source.workload.name | "unknown"`, + "source_workload_namespace": `source.workload.namespace | "unknown"`, + "source_principal": `source.principal | "unknown"`, + "source_app": `source.labels["app"] | "unknown"`, + "source_version": `source.labels["version"] | "unknown"`, + // "source_cluster_id": `source.cluster.id | "unknown"`, "destination_workload": `destination.workload.name | "unknown"`, "destination_workload_namespace": `destination.workload.namespace | "unknown"`, "destination_principal": `destination.principal | "unknown"`, @@ -383,9 +407,9 @@ func tcpMetricDimensions() map[string]interface{} { "destination_service": `destination.service.host | "unknown"`, "destination_service_name": `destination.service.name | "unknown"`, "destination_service_namespace": `destination.service.namespace | "unknown"`, - "destination_cluster_id": `destination.cluster.id | "unknown"`, - "connection_security_policy": `conditional((context.reporter.kind | "inbound") == "outbound", "unknown", conditional(connection.mtls | false, "mutual_tls", "none"))`, - "response_flags": `context.proxy_error_code | "-"`, + // "destination_cluster_id": `destination.cluster.id | "unknown"`, + "connection_security_policy": `conditional((context.reporter.kind | "inbound") == "outbound", "unknown", conditional(connection.mtls | false, "mutual_tls", "none"))`, + "response_flags": `context.proxy_error_code | "-"`, } } @@ -406,7 +430,7 @@ func tcpMetricLabels() []interface{} { "source_workload", "source_workload_namespace", "source_version", - "source_cluster_id", + // "source_cluster_id", "destination_app", "destination_principal", "destination_workload", @@ -415,7 +439,7 @@ func tcpMetricLabels() []interface{} { "destination_service", "destination_service_name", "destination_service_namespace", - "destination_cluster_id", + // "destination_cluster_id", "connection_security_policy", "response_flags", ) diff --git a/pkg/resources/nodeagent/daemonset.go b/pkg/resources/nodeagent/daemonset.go index 0b82c9824..9d04c1487 100644 --- a/pkg/resources/nodeagent/daemonset.go +++ b/pkg/resources/nodeagent/daemonset.go @@ -32,7 +32,9 @@ func (r *Reconciler) daemonSet() runtime.Object { labels := util.MergeLabels(nodeAgentLabels, labelSelector) hostPathType := apiv1.HostPathUnset return &appsv1.DaemonSet{ - ObjectMeta: templates.ObjectMeta(daemonSetName, labels, r.Config), + ObjectMeta: templates.ObjectMetaWithAnnotations(daemonSetName, labels, map[string]string{ + "sidecar.istio.io/inject": "false", + }, r.Config), Spec: appsv1.DaemonSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: labels, @@ -44,6 +46,7 @@ func (r *Reconciler) daemonSet() runtime.Object { }, Spec: apiv1.PodSpec{ ServiceAccountName: serviceAccountName, + PriorityClassName: "", Containers: []apiv1.Container{ { Name: "nodeagent", diff --git a/pkg/resources/pilot/deployment.go b/pkg/resources/pilot/deployment.go index 53f571f94..60de39bc8 100644 --- a/pkg/resources/pilot/deployment.go +++ b/pkg/resources/pilot/deployment.go @@ -76,78 +76,86 @@ func (r *Reconciler) containerPorts() []apiv1.ContainerPort { } func (r *Reconciler) containers() []apiv1.Container { - - containers := []apiv1.Container{ - { - Name: "discovery", - Image: r.Config.Spec.Pilot.Image, - ImagePullPolicy: r.Config.Spec.ImagePullPolicy, - Args: r.containerArgs(), - Ports: r.containerPorts(), - ReadinessProbe: &apiv1.Probe{ - Handler: apiv1.Handler{ - HTTPGet: &apiv1.HTTPGetAction{ - Path: "/ready", - Port: intstr.FromInt(8080), - Scheme: apiv1.URISchemeHTTP, - }, + discoveryContainer := apiv1.Container{ + Name: "discovery", + Image: r.Config.Spec.Pilot.Image, + ImagePullPolicy: r.Config.Spec.ImagePullPolicy, + Args: r.containerArgs(), + Ports: r.containerPorts(), + ReadinessProbe: &apiv1.Probe{ + Handler: apiv1.Handler{ + HTTPGet: &apiv1.HTTPGetAction{ + Path: "/ready", + Port: intstr.FromInt(8080), + Scheme: apiv1.URISchemeHTTP, }, - InitialDelaySeconds: 5, - PeriodSeconds: 30, - TimeoutSeconds: 5, - FailureThreshold: 3, - SuccessThreshold: 1, }, - Env: []apiv1.EnvVar{ - { - Name: "POD_NAME", - ValueFrom: &apiv1.EnvVarSource{ - FieldRef: &apiv1.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.name", - }, + InitialDelaySeconds: 5, + PeriodSeconds: 30, + TimeoutSeconds: 5, + FailureThreshold: 3, + SuccessThreshold: 1, + }, + Env: []apiv1.EnvVar{ + { + Name: "POD_NAME", + ValueFrom: &apiv1.EnvVarSource{ + FieldRef: &apiv1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.name", }, }, - { - Name: "POD_NAMESPACE", - ValueFrom: &apiv1.EnvVarSource{ - FieldRef: &apiv1.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.namespace", - }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &apiv1.EnvVarSource{ + FieldRef: &apiv1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.namespace", }, }, - {Name: "PILOT_PUSH_THROTTLE", Value: "100"}, - {Name: "GODEBUG", Value: "gctrace=2"}, - { - Name: "PILOT_TRACE_SAMPLING", - Value: fmt.Sprintf("%.2f", r.Config.Spec.Pilot.TraceSampling), - }, - {Name: "PILOT_DISABLE_XDS_MARSHALING_TO_ANY", Value: "1"}, - {Name: "MESHNETWORKS_HASH", Value: r.Config.Spec.GetMeshNetworksHash()}, }, - Resources: templates.GetResourcesRequirementsOrDefault( - r.Config.Spec.Pilot.Resources, - r.Config.Spec.DefaultResources, - ), - VolumeMounts: []apiv1.VolumeMount{ - { - Name: "config-volume", - MountPath: "/etc/istio/config", - }, - { - Name: "istio-certs", - MountPath: "/etc/certs", - ReadOnly: true, - }, + {Name: "PILOT_PUSH_THROTTLE", Value: "100"}, + {Name: "GODEBUG", Value: "gctrace=2"}, + { + Name: "PILOT_TRACE_SAMPLING", + Value: fmt.Sprintf("%.2f", r.Config.Spec.Pilot.TraceSampling), + }, + {Name: "PILOT_DISABLE_XDS_MARSHALING_TO_ANY", Value: "1"}, + {Name: "MESHNETWORKS_HASH", Value: r.Config.Spec.GetMeshNetworksHash()}, + }, + Resources: templates.GetResourcesRequirementsOrDefault( + r.Config.Spec.Pilot.Resources, + r.Config.Spec.DefaultResources, + ), + VolumeMounts: []apiv1.VolumeMount{ + { + Name: "config-volume", + MountPath: "/etc/istio/config", + }, + { + Name: "istio-certs", + MountPath: "/etc/certs", + ReadOnly: true, }, - TerminationMessagePath: apiv1.TerminationMessagePathDefault, - TerminationMessagePolicy: apiv1.TerminationMessageReadFile, }, + TerminationMessagePath: apiv1.TerminationMessagePathDefault, + TerminationMessagePolicy: apiv1.TerminationMessageReadFile, + } + + if r.Config.Spec.LocalityLB != nil && util.PointerToBool(r.Config.Spec.LocalityLB.Enabled) { + discoveryContainer.Env = append(discoveryContainer.Env, apiv1.EnvVar{ + Name: "PILOT_ENABLE_LOCALITY_LOAD_BALANCING", + Value: "1", + }) + } + + containers := []apiv1.Container{ + discoveryContainer, } if util.PointerToBool(r.Config.Spec.Pilot.Sidecar) { - containers = append(containers, apiv1.Container{ + proxyContainer := apiv1.Container{ Name: "istio-proxy", Image: r.Config.Spec.Proxy.Image, ImagePullPolicy: r.Config.Spec.ImagePullPolicy, @@ -182,15 +190,31 @@ func (r *Reconciler) containers() []apiv1.Container { }, TerminationMessagePath: apiv1.TerminationMessagePathDefault, TerminationMessagePolicy: apiv1.TerminationMessageReadFile, - }) + } + + if util.PointerToBool(r.Config.Spec.SDS.Enabled) { + proxyContainer.VolumeMounts = append(proxyContainer.VolumeMounts, apiv1.VolumeMount{ + Name: "sds-uds-path", + MountPath: "/var/run/sds", + ReadOnly: true, + }) + + if r.Config.Spec.SDS.UseTrustworthyJwt { + proxyContainer.VolumeMounts = append(proxyContainer.VolumeMounts, apiv1.VolumeMount{ + Name: "istio-token", + MountPath: "/var/run/secrets/tokens", + }) + } + } + + containers = append(containers, proxyContainer) } return containers } func (r *Reconciler) deployment() runtime.Object { - - return &appsv1.Deployment{ + deployment := &appsv1.Deployment{ ObjectMeta: templates.ObjectMeta(deploymentName, util.MergeLabels(pilotLabels, labelSelector), r.Config), Spec: appsv1.DeploymentSpec{ Replicas: util.IntPointer(k8sutil.GetHPAReplicaCountOrDefault(r.Client, types.NamespacedName{ @@ -239,4 +263,37 @@ func (r *Reconciler) deployment() runtime.Object { }, }, } + + if util.PointerToBool(r.Config.Spec.SDS.Enabled) { + deployment.Spec.Template.Spec.Volumes = append(deployment.Spec.Template.Spec.Volumes, apiv1.Volume{ + Name: "sds-uds-path", + VolumeSource: apiv1.VolumeSource{ + HostPath: &apiv1.HostPathVolumeSource{ + Path: "/var/run/sds", + }, + }, + }) + + if r.Config.Spec.SDS.UseTrustworthyJwt { + deployment.Spec.Template.Spec.Volumes = append(deployment.Spec.Template.Spec.Volumes, apiv1.Volume{ + Name: "istio-token", + VolumeSource: apiv1.VolumeSource{ + Projected: &apiv1.ProjectedVolumeSource{ + Sources: []apiv1.VolumeProjection{ + { + ServiceAccountToken: &apiv1.ServiceAccountTokenProjection{ + Path: "istio-token", + ExpirationSeconds: util.Int64Pointer(43200), + Audience: "cluster.local", + }, + }, + }, + DefaultMode: util.IntPointer(420), + }, + }, + }) + } + } + + return deployment } diff --git a/pkg/resources/sidecarinjector/configmap.go b/pkg/resources/sidecarinjector/configmap.go index 060ab278d..aa87cb623 100644 --- a/pkg/resources/sidecarinjector/configmap.go +++ b/pkg/resources/sidecarinjector/configmap.go @@ -17,14 +17,13 @@ limitations under the License. package sidecarinjector import ( - "strconv" + "encoding/json" "strings" "github.com/ghodss/yaml" apiv1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" - istiov1beta1 "github.com/banzaicloud/istio-operator/pkg/apis/istio/v1beta1" "github.com/banzaicloud/istio-operator/pkg/resources/gateways" "github.com/banzaicloud/istio-operator/pkg/resources/templates" "github.com/banzaicloud/istio-operator/pkg/util" @@ -35,86 +34,116 @@ func (r *Reconciler) configMap() runtime.Object { ObjectMeta: templates.ObjectMeta(configMapName, util.MergeLabels(sidecarInjectorLabels, labelSelector), r.Config), Data: map[string]string{ "config": r.siConfig(), + "values": r.getValues(), }, } } +func (r *Reconciler) getValues() string { + podDNSSearchNamespaces := make([]string, 0) + if util.PointerToBool(r.Config.Spec.MultiMesh) { + podDNSSearchNamespaces = append(podDNSSearchNamespaces, []string{ + "global", + "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global", + }...) + return "" + } + + values := map[string]interface{}{ + "sidecarInjectorWebhook": map[string]interface{}{ + "rewriteAppHTTPProbe": r.Config.Spec.SidecarInjector.RewriteAppHTTPProbe, + }, + "global": map[string]interface{}{ + "trustDomain": "cluster.local", + "imagePullPolicy": r.Config.Spec.ImagePullPolicy, + "network": r.Config.Spec.GetNetworkName(), + "podDNSSearchNamespaces": podDNSSearchNamespaces, + "proxy_init": map[string]interface{}{ + "image": r.Config.Spec.ProxyInit.Image, + }, + "tracer": map[string]interface{}{ + "lightstep": map[string]interface{}{ + "CACertPath": r.Config.Spec.Tracing.Lightstep.CacertPath, + }, + }, + "sds": map[string]interface{}{ + "customTokenDirectory": r.Config.Spec.SDS.CustomTokenDirectory, + "useTrustworthyJwt": r.Config.Spec.SDS.UseTrustworthyJwt, + "enabled": r.Config.Spec.SDS.Enabled, + }, + "proxy": map[string]interface{}{ + "image": r.Config.Spec.Proxy.Image, + "statusPort": 15020, + "tracer": r.Config.Spec.Tracing.Tracer, + "clusterDomain": "cluster.local", + "logLevel": r.Config.Spec.Proxy.LogLevel, + "componentLogLevel": r.Config.Spec.Proxy.ComponentLogLevel, + "dnsRefreshRate": r.Config.Spec.Proxy.DNSRefreshRate, + "enableCoreDump": r.Config.Spec.Proxy.EnableCoreDump, + "includeIPRanges": r.Config.Spec.IncludeIPRanges, + "excludeIPRanges": r.Config.Spec.ExcludeIPRanges, + "excludeInboundPorts": "", + "excludeOutboundPorts": "", + "privileged": r.Config.Spec.Proxy.Privileged, + "readinessFailureThreshold": 30, + "readinessInitialDelaySeconds": 1, + "readinessPeriodSeconds": 2, + "resources": r.Config.Spec.Proxy.Resources, + "envoyMetricsService": map[string]interface{}{ + "enabled": false, + }, + "envoyStatsd": map[string]interface{}{ + "enabled": false, + }, + }, + }, + } + + j, _ := json.Marshal(&values) + + return string(j) +} + func (r *Reconciler) siConfig() string { autoInjection := "disabled" if util.PointerToBool(r.Config.Spec.SidecarInjector.AutoInjectionPolicyEnabled) { autoInjection = "enabled" } - siConfig := map[string]string{ + siConfig := map[string]interface{}{ "policy": autoInjection, "template": r.templateConfig(), } + + if len(r.Config.Spec.SidecarInjector.AlwaysInjectSelector) > 0 { + siConfig["alwaysInjectSelector"] = r.Config.Spec.SidecarInjector.AlwaysInjectSelector + } + if len(r.Config.Spec.SidecarInjector.NeverInjectSelector) > 0 { + siConfig["neverInjectSelector"] = r.Config.Spec.SidecarInjector.NeverInjectSelector + } + marshaledConfig, _ := yaml.Marshal(siConfig) // this is a static config, so we don't have to deal with errors return string(marshaledConfig) } -func (r *Reconciler) proxyInitContainer() string { - if util.PointerToBool(r.Config.Spec.SidecarInjector.InitCNIConfiguration.Enabled) { - return "" - } - - return ` -- name: istio-init - image: ` + r.Config.Spec.ProxyInit.Image + ` - args: - - "-p" - - [[ .MeshConfig.ProxyListenPort ]] - - "-u" - - 1337 - - "-m" - - [[ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/interceptionMode` + "`" + ` .ProxyConfig.InterceptionMode ]] - - "-i" - - "[[ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/includeOutboundIPRanges` + "`" + ` "` + r.Config.Spec.IncludeIPRanges + `" ]]" - - "-x" - - "[[ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/excludeOutboundIPRanges` + "`" + ` "` + r.Config.Spec.ExcludeIPRanges + `" ]]" - - "-b" - - "[[ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/includeInboundPorts` + "`" + ` (includeInboundPorts .Spec.Containers) ]]" - - "-d" - - "[[ excludeInboundPort (annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` "15020" ) (annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/excludeInboundPorts` + "`" + ` "" ) ]]" - [[ if (isset .ObjectMeta.Annotations ` + "`" + `traffic.sidecar.istio.io/kubevirtInterfaces` + "`" + `) -]] - - "-k" - - "[[ index .ObjectMeta.Annotations ` + "`" + `traffic.sidecar.istio.io/kubevirtInterfaces` + "`" + ` ]]" - [[ end -]] - imagePullPolicy: ` + string(r.Config.Spec.ImagePullPolicy) + ` -` + r.getFormattedResources(r.Config.Spec.SidecarInjector.Init.Resources, 2) + ` - securityContext: - capabilities: - add: - - NET_ADMIN - privileged: ` + strconv.FormatBool(r.Config.Spec.Proxy.Privileged) + ` - restartPolicy: Always - ` -} - -func (r *Reconciler) dnsConfig() string { - if !util.PointerToBool(r.Config.Spec.MultiMesh) { - return "" - } - return ` +func (r *Reconciler) templateConfig() string { + return `rewriteAppHTTPProbe: {{ valueOrDefault .Values.sidecarInjectorWebhook.rewriteAppHTTPProbe false }} +{{- if .Values.global.podDNSSearchNamespaces }} dnsConfig: searches: - - global - - "[[ valueOrDefault .DeploymentMeta.Namespace "default" ]].global" -` -} - -func (r *Reconciler) templateConfig() string { - return `rewriteAppHTTPProbe: ` + strconv.FormatBool(r.Config.Spec.SidecarInjector.RewriteAppHTTPProbe) + ` -` + r.dnsConfig() + ` + {{- range .Values.global.podDNSSearchNamespaces }} + - {{ render . }} + {{- end }} +{{- end }} initContainers: -[[ if ne (annotation .ObjectMeta ` + "`" + `sidecar.istio.io/interceptionMode` + "`" + ` .ProxyConfig.InterceptionMode) "NONE" ]] +{{ if ne (annotation .ObjectMeta ` + "`" + `sidecar.istio.io/interceptionMode` + "`" + ` .ProxyConfig.InterceptionMode) "NONE" }} ` + r.proxyInitContainer() + ` +{{ end -}} ` + r.coreDumpContainer() + ` -[[ end -]] containers: - name: istio-proxy - image: "[[ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/proxyImage` + "` \"" + r.Config.Spec.Proxy.Image + `" ]]" + image: "{{ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/proxyImage` + "`" + ` .Values.global.proxy.image }}" ports: - containerPort: 15090 protocol: TCP @@ -123,40 +152,59 @@ containers: - proxy - sidecar - --domain - - $(POD_NAMESPACE).svc.cluster.local + - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} - --configPath - - [[ .ProxyConfig.ConfigPath ]] + - "{{ .ProxyConfig.ConfigPath }}" - --binaryPath - - [[ .ProxyConfig.BinaryPath ]] + - "{{ .ProxyConfig.BinaryPath }}" - --serviceCluster - [[ if ne "" (index .ObjectMeta.Labels "app") -]] - - [[ index .ObjectMeta.Labels "app" ]].$(POD_NAMESPACE) - [[ else -]] - - [[ valueOrDefault .DeploymentMeta.Name "istio-proxy" ]].[[ valueOrDefault .DeploymentMeta.Namespace "default" ]] - [[ end -]] + {{ if ne "" (index .ObjectMeta.Labels ` + "`" + `app` + "`" + `) -}} + - "{{ index .ObjectMeta.Labels "app" }}.$(POD_NAMESPACE)" + {{ else -}} + - "{{ valueOrDefault .DeploymentMeta.Name ` + "`" + `istio-proxy` + "`" + ` }}.{{ valueOrDefault .DeploymentMeta.Namespace ` + "`" + `default` + "`" + ` }}" + {{ end -}} - --drainDuration - - [[ formatDuration .ProxyConfig.DrainDuration ]] + - "{{ formatDuration .ProxyConfig.DrainDuration }}" - --parentShutdownDuration - - [[ formatDuration .ProxyConfig.ParentShutdownDuration ]] + - "{{ formatDuration .ProxyConfig.ParentShutdownDuration }}" - --discoveryAddress - - [[ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/discoveryAddress` + "`" + ` .ProxyConfig.DiscoveryAddress ]] + - "{{ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/discoveryAddress` + "`" + ` .ProxyConfig.DiscoveryAddress }}" ` + r.tracingProxyArgs() + ` +{{- if .Values.global.proxy.logLevel }} + - --proxyLogLevel={{ .Values.global.proxy.logLevel }} +{{- end}} +{{- if .Values.global.proxy.componentLogLevel }} + - --proxyComponentLogLevel={{ .Values.global.proxy.componentLogLevel }} +{{- end}} + - --dnsRefreshRate + - {{ .Values.global.proxy.dnsRefreshRate }} - --connectTimeout - - [[ formatDuration .ProxyConfig.ConnectTimeout ]] + - "{{ formatDuration .ProxyConfig.ConnectTimeout }}" + {{- if .Values.global.proxy.envoyStatsd.enabled }} + - --statsdUdpAddress + - "{{ .ProxyConfig.StatsdUdpAddress }}" +{{- end }} +{{- if .Values.global.proxy.envoyMetricsService.enabled }} + - --envoyMetricsServiceAddress + - "{{ .ProxyConfig.EnvoyMetricsServiceAddress }}" +{{- end }} - --proxyAdminPort - - [[ .ProxyConfig.ProxyAdminPort ]] - [[ if gt .ProxyConfig.Concurrency 0 -]] + - "{{ .ProxyConfig.ProxyAdminPort }}" + {{ if gt .ProxyConfig.Concurrency 0 -}} - --concurrency - - [[ .ProxyConfig.Concurrency ]] - [[ end -]] + - "{{ .ProxyConfig.Concurrency }}" + {{ end -}} - --controlPlaneAuthPolicy - - [[ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/controlPlaneAuthPolicy` + "`" + ` .ProxyConfig.ControlPlaneAuthPolicy ]] -[[- if (ne (annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` 15020 ) "0") ]] + - "{{ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/controlPlaneAuthPolicy` + "`" + ` .ProxyConfig.ControlPlaneAuthPolicy }}" +{{- if (ne (annotation .ObjectMeta "status.sidecar.istio.io/port" .Values.global.proxy.statusPort) "0") }} - --statusPort - - [[ annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` 15020 ]] + - "{{ annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` .Values.global.proxy.statusPort }}" - --applicationPorts - - "[[ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/applicationPorts` + "`" + ` (applicationPorts .Spec.Containers) ]]" -[[- end ]] + - "{{ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/applicationPorts` + "`" + ` (applicationPorts .Spec.Containers) }}" +{{- end }} +{{- if .Values.global.trustDomain }} + - --trust-domain={{ .Values.global.trustDomain }} +{{- end }} env: - name: POD_NAME valueFrom: @@ -170,7 +218,12 @@ containers: valueFrom: fieldRef: fieldPath: status.podIP -` + r.hostIPEnv() + ` +{{ if eq .Values.global.proxy.tracer "datadog" }} + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP +{{ end }} - name: ISTIO_META_POD_NAME valueFrom: fieldRef: @@ -179,77 +232,160 @@ containers: valueFrom: fieldRef: fieldPath: metadata.namespace -` + r.networkName() + ` - name: ISTIO_META_INTERCEPTION_MODE - value: [[ or (index .ObjectMeta.Annotations "sidecar.istio.io/interceptionMode") .ProxyConfig.InterceptionMode.String ]] - [[ if .ObjectMeta.Annotations ]] + value: "{{ or (index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/interceptionMode` + "`" + `) .ProxyConfig.InterceptionMode.String }}" + - name: ISTIO_META_INCLUDE_INBOUND_PORTS + value: "{{ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/includeInboundPorts` + "`" + ` (applicationPorts .Spec.Containers) }}" + {{- if .Values.global.network }} + - name: ISTIO_META_NETWORK + value: "{{ .Values.global.network }}" + {{- end }} + {{ if .ObjectMeta.Annotations }} - name: ISTIO_METAJSON_ANNOTATIONS value: | - [[ toJSON .ObjectMeta.Annotations ]] - [[ end ]] - [[ if .ObjectMeta.Labels ]] + {{ toJSON .ObjectMeta.Annotations }} + {{ end }} + {{ if .ObjectMeta.Labels }} - name: ISTIO_METAJSON_LABELS value: | - [[ toJSON .ObjectMeta.Labels ]] - [[ end ]] - [[- if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/bootstrapOverride` + "`" + `) ]] + {{ toJSON .ObjectMeta.Labels }} + {{ end }} + {{- if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/bootstrapOverride` + "`" + `) }} - name: ISTIO_BOOTSTRAP_OVERRIDE value: "/etc/istio/custom-bootstrap/custom_bootstrap.json" - [[- end ]] - imagePullPolicy: ` + string(r.Config.Spec.ImagePullPolicy) + ` - [[ if (ne (annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` 15020 ) "0") ]] + {{- end }} + {{- if .Values.global.sds.customTokenDirectory }} + - name: ISTIO_META_SDS_TOKEN_PATH + value: "{{ .Values.global.sds.customTokenDirectory -}}/sdstoken" + {{- end }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + {{ if ne (annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` .Values.global.proxy.statusPort) ` + "`" + `0` + "`" + ` }} readinessProbe: httpGet: path: /healthz/ready - port: [[ annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` 15020 ]] - initialDelaySeconds: [[ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/initialDelaySeconds` + "`" + ` "1" ]] - periodSeconds: [[ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/periodSeconds` + "`" + ` "2" ]] - failureThreshold: [[ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/failureThreshold` + "`" + ` "30" ]] - [[ end -]] + port: {{ annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` .Values.global.proxy.statusPort }} + initialDelaySeconds: {{ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/initialDelaySeconds` + "`" + ` .Values.global.proxy.readinessInitialDelaySeconds }} + periodSeconds: {{ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/periodSeconds` + "`" + ` .Values.global.proxy.readinessPeriodSeconds }} + failureThreshold: {{ annotation .ObjectMeta ` + "`" + `readiness.status.sidecar.istio.io/failureThreshold` + "`" + ` .Values.global.proxy.readinessFailureThreshold }} + {{ end -}} securityContext: - privileged: ` + strconv.FormatBool(r.Config.Spec.Proxy.Privileged) + ` - readOnlyRootFilesystem: ` + strconv.FormatBool(!r.Config.Spec.Proxy.EnableCoreDump) + ` - [[ if eq (annotation .ObjectMeta ` + "`" + `sidecar.istio.io/interceptionMode` + "`" + ` .ProxyConfig.InterceptionMode) "TPROXY" -]] + {{- if .Values.global.proxy.privileged }} + privileged: true + {{- end }} + {{- if ne .Values.global.proxy.enableCoreDump true }} + readOnlyRootFilesystem: true + {{- end }} + {{ if eq (annotation .ObjectMeta ` + "`" + `sidecar.istio.io/interceptionMode` + "`" + ` .ProxyConfig.InterceptionMode) ` + "`" + `TPROXY` + "`" + ` -}} capabilities: add: - NET_ADMIN runAsGroup: 1337 - [[ else -]] - ` + r.runAsGroup() + ` + {{ else -}} + {{ if and .Values.global.sds.enabled .Values.global.sds.useTrustworthyJwt }} + runAsGroup: 1337 + {{- end }} runAsUser: 1337 - [[- end ]] - [[ if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyCPU` + "`" + `) -]] + {{- end }} resources: + {{ if or (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyCPU` + "`" + `) (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyMemory` + "`" + `) -}} requests: - cpu: [[ index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyCPU` + "`" + ` ]] - memory: [[ index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyMemory` + "`" + ` ]] - [[ else -]] -` + r.getFormattedResources(r.Config.Spec.Proxy.Resources, 2) + ` - [[ end -]] + {{ if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyCPU` + "`" + `) -}} + cpu: "{{ index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyCPU` + "`" + ` }}" + {{ end}} + {{ if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyMemory` + "`" + `) -}} + memory: "{{ index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/proxyMemory` + "`" + ` }}" + {{ end }} + {{ else -}} +{{- if .Values.global.proxy.resources }} + {{ toYaml .Values.global.proxy.resources | indent 4 }} +{{- end }} + {{ end -}} volumeMounts: - [[- if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/bootstrapOverride` + "`" + `) ]] + {{ if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/bootstrapOverride` + "`" + `) }} - mountPath: /etc/istio/custom-bootstrap name: custom-bootstrap-volume - [[- end ]] + {{- end }} - mountPath: /etc/istio/proxy name: istio-envoy - ` + r.volumeMounts() + ` - [[- if isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolumeMount` + "`" + ` ]] - [[ range $index, $value := fromJSON (index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolumeMount` + "`" + `) ]] - - name: "[[ $index ]]" - [[ toYaml $value | indent 4 ]] - [[ end ]] - [[- end ]] + {{- if .Values.global.sds.enabled }} + - mountPath: /var/run/sds + name: sds-uds-path + readOnly: true + {{- if .Values.global.sds.useTrustworthyJwt }} + - mountPath: /var/run/secrets/tokens + name: istio-token + {{- end }} + {{- if .Values.global.sds.customTokenDirectory }} + - mountPath: "{{ .Values.global.sds.customTokenDirectory -}}" + name: custom-sds-token + readOnly: true + {{- end }} + {{- else }} + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + {{- end }} + {{- if and (eq .Values.global.proxy.tracer "lightstep") .Values.global.tracer.lightstep.cacertPath }} + - mountPath: {{ directory .ProxyConfig.GetTracing.GetLightstep.GetCacertPath }} + name: lightstep-certs + readOnly: true + {{- end }} + {{- if isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolumeMount` + "`" + ` }} + {{ range $index, $value := fromJSON (index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolumeMount` + "`" + `) }} + - name: "{{ $index }}" + {{ toYaml $value | indent 4 }} + {{ end }} + {{- end }} volumes: -[[- if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/bootstrapOverride` + "`" + `) ]] +{{- if (isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/bootstrapOverride` + "`" + `) }} - name: custom-bootstrap-volume configMap: - name: [[ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/bootstrapOverride` + "` ``" + ` ]] -[[- end ]] + name: {{ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/bootstrapOverride` + "`" + ` "" }} +{{- end }} - emptyDir: medium: Memory name: istio-envoy -` + r.volumes() +{{- if .Values.global.sds.enabled }} +- name: sds-uds-path + hostPath: + path: /var/run/sds +{{- if .Values.global.sds.customTokenDirectory }} +- name: custom-sds-token + secret: + secretName: sdstokensecret +{{- end }} +{{- if .Values.global.sds.useTrustworthyJwt }} +- name: istio-token + projected: + sources: + - serviceAccountToken: + path: istio-token + expirationSeconds: 43200 + audience: {{ .Values.global.trustDomain }} +{{- end }} +{{- else }} +- name: istio-certs + secret: + optional: true + {{ if eq .Spec.ServiceAccountName "" }} + secretName: istio.default + {{ else -}} + secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }} + {{ end -}} + {{- if isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolume` + "`" + ` }} + {{range $index, $value := fromJSON (index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolume` + "`" + `) }} +- name: "{{ $index }}" + {{ toYaml $value | indent 2 }} + {{ end }} + {{ end }} +{{- end }} +{{- if and (eq .Values.global.proxy.tracer "lightstep") .Values.global.tracer.lightstep.cacertPath }} +- name: lightstep-certs + secret: + optional: true + secretName: lightstep.cacert +{{- end }} +` } func (r *Reconciler) tracingProxyArgs() string { @@ -257,39 +393,21 @@ func (r *Reconciler) tracingProxyArgs() string { return "" } - switch r.Config.Spec.Tracing.Tracer { - case istiov1beta1.TracerTypeZipkin: - return ` - --zipkinAddress - - [[ .ProxyConfig.GetTracing.GetZipkin.GetAddress ]] -` - case istiov1beta1.TracerTypeLightstep: - return ` - --lightstepAddress - - [[ .ProxyConfig.GetTracing.GetLightstep.GetAddress ]] + return `{{- if eq .Values.global.proxy.tracer "lightstep" }} + - --lightstepAddress + - "{{ .ProxyConfig.GetTracing.GetLightstep.GetAddress }}" - --lightstepAccessToken - - [[ .ProxyConfig.GetTracing.GetLightstep.GetAccessToken ]] - - --lightstepSecure - - [[ .ProxyConfig.GetTracing.GetLightstep.GetSecure ]] + - "{{ .ProxyConfig.GetTracing.GetLightstep.GetAccessToken }}" + - --lightstepSecure={{ .ProxyConfig.GetTracing.GetLightstep.GetSecure }} - --lightstepCacertPath - - [[ .ProxyConfig.GetTracing.GetLightstep.GetCacertPath ]] -` - case istiov1beta1.TracerTypeDatadog: - return ` - --datadogAgentAddress - - [[ .ProxyConfig.GetTracing.GetDatadog.GetAddress ]] -` - } - - return "" -} - -func (r *Reconciler) hostIPEnv() string { - if !util.PointerToBool(r.Config.Spec.Tracing.Enabled) || r.Config.Spec.Tracing.Tracer != istiov1beta1.TracerTypeDatadog { - return "" - } - - return ` - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP + - "{{ .ProxyConfig.GetTracing.GetLightstep.GetCacertPath }}" +{{- else if eq .Values.global.proxy.tracer "zipkin" }} + - --zipkinAddress + - "{{ .ProxyConfig.GetTracing.GetZipkin.GetAddress }}" +{{- else if eq .Values.global.proxy.tracer "datadog" }} + - --datadogAgentAddress + - "{{ .ProxyConfig.GetTracing.GetDatadog.GetAddress }}" +{{- end }} ` } @@ -308,6 +426,56 @@ func (r *Reconciler) coreDumpContainer() string { return string(coreDumpContainerYAML) } +func (r *Reconciler) proxyInitContainer() string { + if util.PointerToBool(r.Config.Spec.SidecarInjector.InitCNIConfiguration.Enabled) { + return "" + } + + return `- name: istio-init + image: "{{ .Values.global.proxy_init.image }}" + args: + - "-p" + - "15001" + - "-u" + - 1337 + - "-m" + - "{{ annotation .ObjectMeta ` + "`" + `sidecar.istio.io/interceptionMode` + "`" + ` .ProxyConfig.InterceptionMode }}" + - "-i" + - "{{ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/includeOutboundIPRanges` + "`" + ` .Values.global.proxy.includeIPRanges }}" + - "-x" + - "{{ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/excludeOutboundIPRanges` + "`" + ` .Values.global.proxy.excludeIPRanges }}" + - "-b" + - "{{ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/includeInboundPorts` + "`" + ` (includeInboundPorts .Spec.Containers) }}" + - "-d" + - "{{ excludeInboundPort (annotation .ObjectMeta ` + "`" + `status.sidecar.istio.io/port` + "`" + ` .Values.global.proxy.statusPort) (annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/excludeInboundPorts` + "`" + ` .Values.global.proxy.excludeInboundPorts) }}" + {{ if or (isset .ObjectMeta.Annotations ` + "`" + `traffic.sidecar.istio.io/excludeOutboundPorts` + "`" + `) (ne .Values.global.proxy.excludeOutboundPorts "") -}} + - "-o" + - "{{ annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/excludeOutboundPorts` + "`" + ` .Values.global.proxy.excludeOutboundPorts }}" + {{ end -}} + {{ if (isset .ObjectMeta.Annotations ` + "`" + `traffic.sidecar.istio.io/kubevirtInterfaces` + "`" + `) -}} + - "-k" + - "{{ index .ObjectMeta.Annotations ` + "`" + `traffic.sidecar.istio.io/kubevirtInterfaces` + "`" + ` }}" + {{ end -}} + imagePullPolicy: "{{ .Values.global.imagePullPolicy }}" +` + r.getFormattedResources(r.Config.Spec.SidecarInjector.Init.Resources, 2) + ` + securityContext: + runAsUser: 0 + runAsNonRoot: false + capabilities: + add: + - NET_ADMIN + {{- if .Values.global.proxy.privileged }} + privileged: true + {{- end }} + restartPolicy: Always + env: + {{- if contains "*" (annotation .ObjectMeta ` + "`" + `traffic.sidecar.istio.io/includeInboundPorts` + "`" + ` "") }} + - name: INBOUND_CAPTURE_PORT + value: 15006 + {{- end }} + ` +} + func (r *Reconciler) getFormattedResources(resources *apiv1.ResourceRequirements, indentSize int) string { type Resources struct { Resources apiv1.ResourceRequirements `json:"resources,omitempty"` @@ -328,75 +496,6 @@ func (r *Reconciler) getFormattedResources(resources *apiv1.ResourceRequirements return indentWithSpaces(string(requirementsYAML), indentSize) } -func (r *Reconciler) runAsGroup() string { - if util.PointerToBool(r.Config.Spec.SDS.Enabled) && r.Config.Spec.SDS.UseTrustworthyJwt { - return "runAsGroup: 1337" - } - return "" -} - -func (r *Reconciler) networkName() string { - networkName := r.Config.Spec.GetNetworkName() - if util.PointerToBool(r.Config.Spec.MeshExpansion) && networkName != "" { - return ` - name: ISTIO_META_NETWORK - value: "` + networkName + `" -` - } - - return "" -} - -func (r *Reconciler) volumeMounts() string { - if !util.PointerToBool(r.Config.Spec.SDS.Enabled) { - return `- mountPath: /etc/certs/ - name: istio-certs - readOnly: true` - } - vms := `- mountPath: /var/run/sds/uds_path - name: sds-uds-path - readOnly: true` - if r.Config.Spec.SDS.UseTrustworthyJwt { - vms = vms + ` - - mountPath: /var/run/secrets/tokens - name: istio-token` - } - return vms -} - -func (r *Reconciler) volumes() string { - if !util.PointerToBool(r.Config.Spec.SDS.Enabled) { - return `- name: istio-certs - secret: - optional: true - [[ if eq .Spec.ServiceAccountName "" -]] - secretName: istio.default - [[ else -]] - secretName: [[ printf "istio.%s" .Spec.ServiceAccountName ]] - [[ end -]] - [[- if isset .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolume` + "`" + ` ]] - [[ range $index, $value := fromJSON (index .ObjectMeta.Annotations ` + "`" + `sidecar.istio.io/userVolume` + "`" + `) ]] -- name: "[[ $index ]]" - [[ toYaml $value | indent 2 ]] - [[ end ]] - [[ end ]]` - } - volumes := `- name: sds-uds-path - hostPath: - path: /var/run/sds/uds_path - type: Socket` - if r.Config.Spec.SDS.UseTrustworthyJwt { - volumes = volumes + ` -- name: istio-token - projected: - sources: - - serviceAccountToken: - path: istio-token - expirationSeconds: 43200 - audience: ""` - } - return volumes -} - func indentWithSpaces(v string, spaces int) string { pad := strings.Repeat(" ", spaces) return pad + strings.Replace(v, "\n", "\n"+pad, -1) diff --git a/pkg/resources/sidecarinjector/deployment.go b/pkg/resources/sidecarinjector/deployment.go index 93cc271ca..570cbcbd9 100644 --- a/pkg/resources/sidecarinjector/deployment.go +++ b/pkg/resources/sidecarinjector/deployment.go @@ -45,6 +45,7 @@ func (r *Reconciler) deployment() runtime.Object { }, Spec: apiv1.PodSpec{ ServiceAccountName: serviceAccountName, + PriorityClassName: "", Containers: []apiv1.Container{ { Name: "sidecar-injector-webhook", @@ -119,6 +120,10 @@ func (r *Reconciler) deployment() runtime.Object { Key: "config", Path: "config", }, + { + Key: "values", + Path: "values", + }, }, DefaultMode: util.IntPointer(420), }, diff --git a/pkg/resources/sidecarinjector/pdb.go b/pkg/resources/sidecarinjector/pdb.go new file mode 100644 index 000000000..782164e8c --- /dev/null +++ b/pkg/resources/sidecarinjector/pdb.go @@ -0,0 +1,40 @@ +/* +Copyright 2019 Banzai Cloud. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sidecarinjector + +import ( + policyv1beta1 "k8s.io/api/policy/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "github.com/banzaicloud/istio-operator/pkg/util" + + "github.com/banzaicloud/istio-operator/pkg/resources/templates" +) + +func (r *Reconciler) podDisruptionBudget() runtime.Object { + labels := util.MergeLabels(sidecarInjectorLabels, labelSelector) + return &policyv1beta1.PodDisruptionBudget{ + ObjectMeta: templates.ObjectMeta(pdbName, labels, r.Config), + Spec: policyv1beta1.PodDisruptionBudgetSpec{ + MinAvailable: util.IntstrPointer(1), + Selector: &metav1.LabelSelector{ + MatchLabels: labels, + }, + }, + } +} diff --git a/pkg/resources/sidecarinjector/sidecarinjector.go b/pkg/resources/sidecarinjector/sidecarinjector.go index 4acb14c56..08475bdc4 100644 --- a/pkg/resources/sidecarinjector/sidecarinjector.go +++ b/pkg/resources/sidecarinjector/sidecarinjector.go @@ -17,11 +17,12 @@ limitations under the License. package sidecarinjector import ( - "github.com/banzaicloud/istio-operator/pkg/util" "github.com/go-logr/logr" "github.com/goph/emperror" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/banzaicloud/istio-operator/pkg/util" + istiov1beta1 "github.com/banzaicloud/istio-operator/pkg/apis/istio/v1beta1" "github.com/banzaicloud/istio-operator/pkg/k8sutil" "github.com/banzaicloud/istio-operator/pkg/resources" @@ -36,6 +37,7 @@ const ( webhookName = "istio-sidecar-injector" deploymentName = "istio-sidecar-injector" serviceName = "istio-sidecar-injector" + pdbName = "istio-sidecar-injector" ) var sidecarInjectorLabels = map[string]string{ diff --git a/pkg/resources/sidecarinjector/webhook.go b/pkg/resources/sidecarinjector/webhook.go index e2a1b9ab4..faf678eda 100644 --- a/pkg/resources/sidecarinjector/webhook.go +++ b/pkg/resources/sidecarinjector/webhook.go @@ -28,7 +28,7 @@ import ( func (r *Reconciler) webhook() runtime.Object { fail := admissionv1beta1.Fail unknownSideEffects := admissionv1beta1.SideEffectClassUnknown - return &admissionv1beta1.MutatingWebhookConfiguration{ + webhook := &admissionv1beta1.MutatingWebhookConfiguration{ ObjectMeta: templates.ObjectMetaClusterScope(webhookName, sidecarInjectorLabels, r.Config), Webhooks: []admissionv1beta1.Webhook{ { @@ -63,4 +63,23 @@ func (r *Reconciler) webhook() runtime.Object { }, }, } + + if util.PointerToBool(r.Config.Spec.SidecarInjector.EnableNamespacesByDefault) { + webhook.Webhooks[0].NamespaceSelector = &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "name", + Operator: metav1.LabelSelectorOpNotIn, + Values: []string{r.Config.Namespace}, + }, + { + Key: "istio-injection", + Operator: metav1.LabelSelectorOpNotIn, + Values: []string{"disabled"}, + }, + }, + } + } + + return webhook }