diff --git a/.gitignore b/.gitignore index 95cf6da5..6a78657d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out .DS_Store + +artifacts/gcloud/ \ No newline at end of file diff --git a/artifacts/canaries/canary.yaml b/artifacts/canaries/canary.yaml index f4d88afb..70c86c07 100644 --- a/artifacts/canaries/canary.yaml +++ b/artifacts/canaries/canary.yaml @@ -25,7 +25,7 @@ spec: - public-gateway.istio-system.svc.cluster.local # Istio virtual service host names (optional) hosts: - - app.iowa.weavedx.com + - app.istio.weavedx.com canaryAnalysis: # schedule interval (default 60s) interval: 10s diff --git a/artifacts/canaries/deployment.yaml b/artifacts/canaries/deployment.yaml index de686bbc..57ed8a41 100644 --- a/artifacts/canaries/deployment.yaml +++ b/artifacts/canaries/deployment.yaml @@ -25,7 +25,7 @@ spec: spec: containers: - name: podinfod - image: quay.io/stefanprodan/podinfo:1.3.0 + image: quay.io/stefanprodan/podinfo:1.4.0 imagePullPolicy: IfNotPresent ports: - containerPort: 9898 diff --git a/artifacts/gke/istio-gateway.yaml b/artifacts/gke/istio-gateway.yaml new file mode 100644 index 00000000..79c01615 --- /dev/null +++ b/artifacts/gke/istio-gateway.yaml @@ -0,0 +1,27 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: Gateway +metadata: + name: public-gateway + namespace: istio-system +spec: + selector: + istio: ingressgateway + servers: + - port: + number: 80 + name: http + protocol: HTTP + hosts: + - "*" + tls: + httpsRedirect: true + - port: + number: 443 + name: https + protocol: HTTPS + hosts: + - "*" + tls: + mode: SIMPLE + privateKey: /etc/istio/ingressgateway-certs/tls.key + serverCertificate: /etc/istio/ingressgateway-certs/tls.crt diff --git a/artifacts/gke/istio-prometheus.yaml b/artifacts/gke/istio-prometheus.yaml new file mode 100644 index 00000000..ad9dbdcf --- /dev/null +++ b/artifacts/gke/istio-prometheus.yaml @@ -0,0 +1,443 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: prometheus + labels: + app: prometheus +rules: + - apiGroups: [""] + resources: + - nodes + - services + - endpoints + - pods + - nodes/proxy + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: + - configmaps + verbs: ["get"] + - nonResourceURLs: ["/metrics"] + verbs: ["get"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: prometheus + labels: + app: prometheus +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prometheus +subjects: + - kind: ServiceAccount + name: prometheus + namespace: istio-system +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: prometheus + namespace: istio-system + labels: + app: prometheus +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: prometheus + namespace: istio-system + labels: + app: prometheus +data: + prometheus.yml: |- + global: + scrape_interval: 15s + scrape_configs: + + - job_name: 'istio-mesh' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + + kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - istio-system + + relabel_configs: + - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-telemetry;prometheus + + + # Scrape config for envoy stats + - job_name: 'envoy-stats' + metrics_path: /stats/prometheus + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_container_port_name] + action: keep + regex: '.*-envoy-prom' + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:15090 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod_name + + metric_relabel_configs: + # Exclude some of the envoy metrics that have massive cardinality + # This list may need to be pruned further moving forward, as informed + # by performance and scalability testing. + - source_labels: [ cluster_name ] + regex: '(outbound|inbound|prometheus_stats).*' + action: drop + - source_labels: [ tcp_prefix ] + regex: '(outbound|inbound|prometheus_stats).*' + action: drop + - source_labels: [ listener_address ] + regex: '(.+)' + action: drop + - source_labels: [ http_conn_manager_listener_prefix ] + regex: '(.+)' + action: drop + - source_labels: [ http_conn_manager_prefix ] + regex: '(.+)' + action: drop + - source_labels: [ __name__ ] + regex: 'envoy_tls.*' + action: drop + - source_labels: [ __name__ ] + regex: 'envoy_tcp_downstream.*' + action: drop + - source_labels: [ __name__ ] + regex: 'envoy_http_(stats|admin).*' + action: drop + - source_labels: [ __name__ ] + regex: 'envoy_cluster_(lb|retry|bind|internal|max|original).*' + action: drop + + + - job_name: 'istio-policy' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - istio-system + + + relabel_configs: + - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-policy;http-monitoring + + - job_name: 'istio-telemetry' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - istio-system + + relabel_configs: + - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-telemetry;http-monitoring + + - job_name: 'pilot' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - istio-system + + relabel_configs: + - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-pilot;http-monitoring + + - job_name: 'galley' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - istio-system + + relabel_configs: + - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: istio-galley;http-monitoring + + # scrape config for API servers + - job_name: 'kubernetes-apiservers' + kubernetes_sd_configs: + - role: endpoints + namespaces: + names: + - default + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: kubernetes;https + + # scrape config for nodes (kubelet) + - job_name: 'kubernetes-nodes' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics + + # Scrape config for Kubelet cAdvisor. + # + # This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics + # (those whose names begin with 'container_') have been removed from the + # Kubelet metrics endpoint. This job scrapes the cAdvisor endpoint to + # retrieve those metrics. + # + # In Kubernetes 1.7.0-1.7.2, these metrics are only exposed on the cAdvisor + # HTTP endpoint; use "replacement: /api/v1/nodes/${1}:4194/proxy/metrics" + # in that case (and ensure cAdvisor's HTTP server hasn't been disabled with + # the --cadvisor-port=0 Kubelet flag). + # + # This job is not necessary and should be removed in Kubernetes 1.6 and + # earlier versions, or it will cause the metrics to be scraped twice. + - job_name: 'kubernetes-cadvisor' + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor + + # scrape config for service endpoints. + - job_name: 'kubernetes-service-endpoints' + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_name + + - job_name: 'kubernetes-pods' + kubernetes_sd_configs: + - role: pod + relabel_configs: # If first two labels are present, pod should be scraped by the istio-secure job. + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_sidecar_istio_io_status] + action: drop + regex: (.+) + - source_labels: [__meta_kubernetes_pod_annotation_istio_mtls] + action: drop + regex: (true) + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod_name + + - job_name: 'kubernetes-pods-istio-secure' + scheme: https + tls_config: + ca_file: /etc/istio-certs/root-cert.pem + cert_file: /etc/istio-certs/cert-chain.pem + key_file: /etc/istio-certs/key.pem + insecure_skip_verify: true # prometheus does not support secure naming. + kubernetes_sd_configs: + - role: pod + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + # sidecar status annotation is added by sidecar injector and + # istio_workload_mtls_ability can be specifically placed on a pod to indicate its ability to receive mtls traffic. + - source_labels: [__meta_kubernetes_pod_annotation_sidecar_istio_io_status, __meta_kubernetes_pod_annotation_istio_mtls] + action: keep + regex: (([^;]+);([^;]*))|(([^;]*);(true)) + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__] # Only keep address that is host:port + action: keep # otherwise an extra target with ':443' is added for https scheme + regex: ([^:]+):(\d+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod_name +--- + +# Source: istio/charts/prometheus/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: prometheus + namespace: istio-system + annotations: + prometheus.io/scrape: 'true' + labels: + name: prometheus +spec: + selector: + app: prometheus + ports: + - name: http-prometheus + protocol: TCP + port: 9090 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prometheus + namespace: istio-system + labels: + app: prometheus +spec: + replicas: 1 + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + annotations: + sidecar.istio.io/inject: "false" + scheduler.alpha.kubernetes.io/critical-pod: "" + spec: + serviceAccountName: prometheus + containers: + - name: prometheus + image: "docker.io/prom/prometheus:v2.7.1" + imagePullPolicy: IfNotPresent + args: + - '--storage.tsdb.retention=6h' + - '--config.file=/etc/prometheus/prometheus.yml' + ports: + - containerPort: 9090 + name: http + livenessProbe: + httpGet: + path: /-/healthy + port: 9090 + readinessProbe: + httpGet: + path: /-/ready + port: 9090 + resources: + requests: + cpu: 10m + + volumeMounts: + - name: config-volume + mountPath: /etc/prometheus + - mountPath: /etc/istio-certs + name: istio-certs + volumes: + - name: config-volume + configMap: + name: prometheus + - name: istio-certs + secret: + defaultMode: 420 + optional: true + secretName: istio.default diff --git a/docs/diagrams/flagger-gke-istio.png b/docs/diagrams/flagger-gke-istio.png new file mode 100644 index 00000000..c15d772e Binary files /dev/null and b/docs/diagrams/flagger-gke-istio.png differ diff --git a/docs/diagrams/istio-cert-manager-gke.png b/docs/diagrams/istio-cert-manager-gke.png new file mode 100644 index 00000000..46470f75 Binary files /dev/null and b/docs/diagrams/istio-cert-manager-gke.png differ diff --git a/docs/gitbook/SUMMARY.md b/docs/gitbook/SUMMARY.md index d2d1b664..ee7dce00 100644 --- a/docs/gitbook/SUMMARY.md +++ b/docs/gitbook/SUMMARY.md @@ -5,9 +5,8 @@ ## Install -* [Install Flagger](install/install-flagger.md) -* [Install Grafana](install/install-grafana.md) -* [Install Istio](install/install-istio.md) +* [Flagger Install on Kubernetes](install/flagger-install-on-kubernetes.md) +* [Flagger Install on Google Cloud](install/flagger-install-on-google-cloud.md) ## Usage @@ -15,3 +14,5 @@ * [Monitoring](usage/monitoring.md) * [Alerting](usage/alerting.md) + + diff --git a/docs/gitbook/how-it-works.md b/docs/gitbook/how-it-works.md index 02123a36..97faec2b 100644 --- a/docs/gitbook/how-it-works.md +++ b/docs/gitbook/how-it-works.md @@ -252,14 +252,14 @@ Spec: ```yaml canaryAnalysis: webhooks: - - name: integration-tests - url: http://podinfo.test:9898/echo + - name: integration-test + url: http://int-runner.test:8080/ timeout: 30s metadata: test: "all" token: "16688eb5e9f289f1991c" - - name: load-tests - url: http://podinfo.test:9898/echo + - name: db-test + url: http://migration-check.db/query timeout: 30s metadata: key1: "val1" diff --git a/docs/gitbook/install/install-istio.md b/docs/gitbook/install/flagger-install-on-google-cloud.md similarity index 53% rename from docs/gitbook/install/install-istio.md rename to docs/gitbook/install/flagger-install-on-google-cloud.md index 30a7ac2a..a3d7b888 100644 --- a/docs/gitbook/install/install-istio.md +++ b/docs/gitbook/install/flagger-install-on-google-cloud.md @@ -1,16 +1,15 @@ -# Install Istio +# Flagger install on Google Cloud -This guide walks you through setting up Istio with Jaeger, Prometheus, Grafana and -Let’s Encrypt TLS for ingress gateway on Google Kubernetes Engine. +This guide walks you through setting up Flagger and Istio on Google Kubernetes Engine. -![Istio GKE diagram](https://raw.githubusercontent.com/stefanprodan/istio-gke/master/docs/screens/istio-gcp-overview.png) +![GKE Cluster Overview](https://raw.githubusercontent.com/stefanprodan/flagger/master/docs/diagrams/flagger-gke-istio.png) ### Prerequisites You will be creating a cluster on Google’s Kubernetes Engine \(GKE\), if you don’t have an account you can sign up [here](https://cloud.google.com/free/) for free credits. -Login into GCP, create a project and enable billing for it. +Login into Google Cloud, create a project and enable billing for it. Install the [gcloud](https://cloud.google.com/sdk/) command line utility and configure your project with `gcloud init`. @@ -23,8 +22,8 @@ gcloud config set project PROJECT_ID Set the default compute region and zone: ```text -gcloud config set compute/region europe-west3 -gcloud config set compute/zone europe-west3-a +gcloud config set compute/region us-central1 +gcloud config set compute/zone us-central1-a ``` Enable the Kubernetes and Cloud DNS services for your project: @@ -34,46 +33,41 @@ gcloud services enable container.googleapis.com gcloud services enable dns.googleapis.com ``` -Install the `kubectl` command-line tool: +Install the kubectl command-line tool: ```text gcloud components install kubectl ``` -Install the `helm` command-line tool: - -```text -brew install kubernetes-helm -``` - ### GKE cluster setup -Create a cluster with three nodes using the latest Kubernetes version: +Create a cluster with the Istio add-on: ```bash -k8s_version=$(gcloud container get-server-config --format=json \ -| jq -r '.validNodeVersions[0]') +K8S_VERSION=$(gcloud container get-server-config --format=json \ +| jq -r '.validMasterVersions[0]') -gcloud container clusters create istio \ ---cluster-version=${k8s_version} \ ---zone=europe-west3-a \ ---num-nodes=3 \ +gcloud beta container clusters create istio \ +--cluster-version=${K8S_VERSION} \ +--zone=us-central1-a \ +--num-nodes=2 \ --machine-type=n1-highcpu-4 \ --preemptible \ --no-enable-cloud-logging \ --disk-size=30 \ --enable-autorepair \ ---scopes=gke-default,compute-rw,storage-rw +--addons=Istio \ +--istio-config=auth=MTLS_PERMISSIVE ``` -The above command will create a default node pool consisting of `n1-highcpu-4` \(vCPU: 4, RAM 3.60GB, DISK: 30GB\) +The above command will create a default node pool consisting of two `n1-highcpu-4` \(vCPU: 4, RAM 3.60GB, DISK: 30GB\) preemptible VMs. Preemptible VMs are up to 80% cheaper than regular instances and are terminated and replaced after a maximum of 24 hours. Set up credentials for `kubectl`: ```bash -gcloud container clusters get-credentials istio -z=europe-west3-a +gcloud container clusters get-credentials istio ``` Create a cluster admin role binding: @@ -87,9 +81,11 @@ kubectl create clusterrolebinding "cluster-admin-$(whoami)" \ Validate your setup with: ```bash -kubectl get nodes -o wide +kubectl -n istio-system get svc ``` +In a couple of seconds GCP should allocate an external IP to the `istio-ingressgateway` service. + ### Cloud DNS setup You will need an internet domain and access to the registrar to change the name servers to Google Cloud DNS. @@ -116,34 +112,30 @@ Wait for the name servers to change \(replace `example.com` with your domain\): watch dig +short NS example.com ``` -Create a static IP address named `istio-gateway-ip` in the same region as your GKE cluster: +Create a static IP address named `istio-gateway` using the Istio ingress IP: ```bash -gcloud compute addresses create istio-gateway-ip --region europe-west3 +export GATEWAY_IP=$(kubectl -n istio-system get svc/istio-ingressgateway -ojson \ +| jq -r .status.loadBalancer.ingress[0].ip) + +gcloud compute addresses create istio-gateway --addresses ${GATEWAY_IP} --region us-central1 ``` -Find the static IP address: - -```bash -gcloud compute addresses describe istio-gateway-ip --region europe-west3 -``` - -Create the following DNS records \(replace `example.com` with your domain and set your Istio Gateway IP\): +Create the following DNS records \(replace `example.com` with your domain\): ```bash DOMAIN="example.com" -GATEWAYIP="35.198.98.90" gcloud dns record-sets transaction start --zone=istio gcloud dns record-sets transaction add --zone=istio \ ---name="${DOMAIN}" --ttl=300 --type=A ${GATEWAYIP} +--name="${DOMAIN}" --ttl=300 --type=A ${GATEWAY_IP} gcloud dns record-sets transaction add --zone=istio \ ---name="www.${DOMAIN}" --ttl=300 --type=A ${GATEWAYIP} +--name="www.${DOMAIN}" --ttl=300 --type=A ${GATEWAY_IP} gcloud dns record-sets transaction add --zone=istio \ ---name="*.${DOMAIN}" --ttl=300 --type=A ${GATEWAYIP} +--name="*.${DOMAIN}" --ttl=300 --type=A ${GATEWAY_IP} gcloud dns record-sets transaction execute --zone istio ``` @@ -154,31 +146,22 @@ Verify that the wildcard DNS is working \(replace `example.com` with your domain watch host test.example.com ``` -### Install Istio with Helm +### Install Helm -Download the latest Istio release: +Install the [Helm](https://docs.helm.sh/using_helm/#installing-helm) command-line tool: -```bash -curl -L https://git.io/getLatestIstio | sh - -``` - -Navigate to `istio-x.x.x` dir and copy the Istio CLI in your bin: - -```bash -cd istio-x.x.x/ -sudo cp ./bin/istioctl /usr/local/bin/istioctl -``` - -Apply the Istio CRDs: - -```bash -kubectl apply -f ./install/kubernetes/helm/istio/templates/crds.yaml +```text +brew install kubernetes-helm ``` Create a service account and a cluster role binding for Tiller: ```bash -kubectl apply -f ./install/kubernetes/helm/helm-service-account.yaml +kubectl -n kube-system create sa tiller + +kubectl create clusterrolebinding tiller-cluster-rule \ +--clusterrole=cluster-admin \ +--serviceaccount=kube-system:tiller ``` Deploy Tiller in the `kube-system` namespace: @@ -187,125 +170,51 @@ Deploy Tiller in the `kube-system` namespace: helm init --service-account tiller ``` -Find the GKE IP ranges: +You should consider using SSL between Helm and Tiller, for more information on securing your Helm +installation see [docs.helm.sh](https://docs.helm.sh/using_helm/#securing-your-helm-installation). + +### Install cert-manager + +Jetstack's [cert-manager](https://github.com/jetstack/cert-manager) +is a Kubernetes operator that automatically creates and manages TLS certs issued by Let’s Encrypt. + +You'll be using cert-manager to provision a wildcard certificate for the Istio ingress gateway. + +Install cert-manager's CRDs: ```bash -gcloud container clusters describe istio --zone=europe-west3-a \ -| grep -e clusterIpv4Cidr -e servicesIpv4Cidr +CERT_REPO=https://raw.githubusercontent.com/jetstack/cert-manager + +kubectl apply -f ${CERT_REPO}/release-0.6/deploy/manifests/00-crds.yaml ``` -You'll be using the IP ranges to allow unrestricted egress traffic for services running inside the service mesh. - -Configure Istio with Prometheus, Jaeger, and cert-manager: - -```yaml -global: - nodePort: false - proxy: - # replace with your GKE IP ranges - includeIPRanges: "10.28.0.0/14,10.7.240.0/20" - -sidecarInjectorWebhook: - enabled: true - enableNamespacesByDefault: false - -gateways: - enabled: true - istio-ingressgateway: - replicaCount: 2 - autoscaleMin: 2 - autoscaleMax: 3 - # replace with your Istio Gateway IP - loadBalancerIP: "35.198.98.90" - type: LoadBalancer - -pilot: - enabled: true - replicaCount: 1 - autoscaleMin: 1 - autoscaleMax: 1 - resources: - requests: - cpu: 500m - memory: 1024Mi - -grafana: - enabled: true - security: - enabled: true - adminUser: admin - # change the password - adminPassword: admin - -prometheus: - enabled: true - -servicegraph: - enabled: true - -tracing: - enabled: true - jaeger: - tag: 1.7 - -certmanager: - enabled: true -``` - -Save the above file as `my-istio.yaml` and install Istio with Helm: +Create the cert-manager namespace and disable resource validation: ```bash -helm upgrade --install istio ./install/kubernetes/helm/istio \ ---namespace=istio-system \ --f ./my-istio.yaml +kubectl create namespace cert-manager + +kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true ``` -Verify that Istio workloads are running: +Install cert-manager with Helm: -```text -kubectl -n istio-system get pods +```bash +helm repo update && helm upgrade -i cert-manager \ +--namespace cert-manager \ +--version v0.6.0 \ +stable/cert-manager ``` -### Configure Istio Gateway with LE TLS +### Istio Gateway TLS setup -![Istio Let's Encrypt diagram](https://raw.githubusercontent.com/stefanprodan/istio-gke/master/docs/screens/istio-cert-manager-gcp.png) +![Istio Let's Encrypt](https://raw.githubusercontent.com/stefanprodan/flagger/master/docs/diagrams/istio-cert-manager-gke.png) -Create a Istio Gateway in istio-system namespace with HTTPS redirect: +Create a generic Istio Gateway to expose services outside the mesh on HTTPS: -```yaml -apiVersion: networking.istio.io/v1alpha3 -kind: Gateway -metadata: - name: public-gateway - namespace: istio-system -spec: - selector: - istio: ingressgateway - servers: - - port: - number: 80 - name: http - protocol: HTTP - hosts: - - "*" - tls: - httpsRedirect: true - - port: - number: 443 - name: https - protocol: HTTPS - hosts: - - "*" - tls: - mode: SIMPLE - privateKey: /etc/istio/ingressgateway-certs/tls.key - serverCertificate: /etc/istio/ingressgateway-certs/tls.crt -``` +```bash +REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master -Save the above resource as istio-gateway.yaml and then apply it: - -```text -kubectl apply -f ./istio-gateway.yaml +kubectl apply -f ${REPO}/artifacts/gke/istio-gateway.yaml ``` Create a service account with Cloud DNS admin role \(replace `my-gcp-project` with your project ID\): @@ -387,37 +296,76 @@ spec: - "example.com" ``` -Save the above resource as of-cert.yaml and then apply it: +Save the above resource as istio-gateway-cert.yaml and then apply it: ```text -kubectl apply -f ./of-cert.yaml +kubectl apply -f ./istio-gateway-cert.yaml ``` In a couple of seconds cert-manager should fetch a wildcard certificate from letsencrypt.org: ```text -kubectl -n istio-system logs deployment/certmanager -f +kubectl -n istio-system describe certificate istio-gateway -Certificate issued successfully -Certificate istio-system/istio-gateway scheduled for renewal in 1438 hours +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal CertIssued 1m52s cert-manager Certificate issued successfully ``` Recreate Istio ingress gateway pods: ```bash -kubectl -n istio-system delete pods -l istio=ingressgateway +kubectl -n istio-system get pods -l istio=ingressgateway ``` Note that Istio gateway doesn't reload the certificates from the TLS secret on cert-manager renewal. Since the GKE cluster is made out of preemptible VMs the gateway pods will be replaced once every 24h, -if your not using preemptible nodes then you need to manually kill the gateway pods every two months +if your not using preemptible nodes then you need to manually delete the gateway pods every two months before the certificate expires. -### Expose services outside the service mesh +### Install Prometheus -In order to expose services via the Istio Gateway you have to create a Virtual Service attached to Istio Gateway. +The GKE Istio add-on does not include a Prometheus instance that scraps the Istio telemetry service. +Because Flagger uses the Istio HTTP metrics to run the canary analysis you have to +deploy the following Prometheus configuration that's similar to the one that comes with the official Istio Helm chart. -Create a virtual service in `istio-system` namespace for Grafana \(replace `example.com` with your domain\): +```bash +REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master + +kubectl apply -f ${REPO}/artifacts/gke/istio-prometheus.yaml +``` + +### Install Flagger and Grafana + +Add Flagger Helm repository: + +```bash +helm repo add flagger https://flagger.app +``` + +Deploy Flagger in the `istio-system` namespace with Slack notifications enabled: + +```bash +helm upgrade -i flagger flagger/flagger \ +--namespace=istio-system \ +--set metricsServer=http://prometheus.istio-system:9090 \ +--set slack.url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \ +--set slack.channel=general \ +--set slack.user=flagger +``` + +Deploy Grafana in the `istio-system` namespace: + +```bash +helm upgrade -i flagger-grafana flagger/grafana \ +--namespace=istio-system \ +--set url=http://prometheus.istio-system:9090 \ +--set user=admin \ +--set password=replace-me +``` + +Expose Grafana through the public gateway by creating a virtual service \(replace `example.com` with your domain\): ```yaml apiVersion: networking.istio.io/v1alpha3 @@ -433,8 +381,7 @@ spec: http: - route: - destination: - host: grafana - timeout: 30s + host: flagger-grafana ``` Save the above resource as grafana-virtual-service.yaml and then apply it: @@ -444,17 +391,3 @@ kubectl apply -f ./grafana-virtual-service.yaml ``` Navigate to `http://grafana.example.com` in your browser and you should be redirected to the HTTPS version. - -Check that HTTP2 is enabled: - -```bash -curl -I --http2 https://grafana.example.com - -HTTP/2 200 -content-type: text/html; charset=UTF-8 -x-envoy-upstream-service-time: 3 -server: envoy -``` - - - diff --git a/docs/gitbook/install/flagger-install-on-kubernetes.md b/docs/gitbook/install/flagger-install-on-kubernetes.md new file mode 100644 index 00000000..c68f2228 --- /dev/null +++ b/docs/gitbook/install/flagger-install-on-kubernetes.md @@ -0,0 +1,143 @@ +# Flagger install on Kubernetes + +This guide walks you through setting up Flagger on a Kubernetes cluster. + +### Prerequisites + +Flagger requires a Kubernetes cluster **v1.11** or newer with the following admission controllers enabled: + +* MutatingAdmissionWebhook +* ValidatingAdmissionWebhook + +Flagger depends on [Istio](https://istio.io/docs/setup/kubernetes/quick-start/) **v1.0.3** or newer +with traffic management, telemetry and Prometheus enabled. + +A minimal Istio installation should contain the following services: + +* istio-pilot +* istio-ingressgateway +* istio-sidecar-injector +* istio-telemetry +* prometheus + +### Install Flagger + +Add Flagger Helm repository: + +```bash +helm repo add flagger https://flagger.app +``` + +Deploy Flagger in the _**istio-system**_ namespace: + +```bash +helm upgrade -i flagger flagger/flagger \ +--namespace=istio-system \ +--set metricsServer=http://prometheus.istio-system:9090 +``` + +You can install Flagger in any namespace as long as it can talk to the Istio Prometheus service on port 9090. + +Enable **Slack** notifications: + +```bash +helm upgrade -i flagger flagger/flagger \ +--namespace=istio-system \ +--set slack.url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \ +--set slack.channel=general \ +--set slack.user=flagger +``` + +If you don't have Tiller you can use the helm template command and apply the generated yaml with kubectl: + +```bash +# generate +helm template flagger/flagger \ +--name flagger \ +--namespace=istio-system \ +--set metricsServer=http://prometheus.istio-system:9090 \ +> $HOME/flagger.yaml + +# apply +kubectl apply -f $HOME/flagger.yaml +``` + +To uninstall the Flagger release with Helm run: + +```text +helm delete --purge flagger +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +> **Note** that on uninstall the Canary CRD will not be removed. +Deleting the CRD will make Kubernetes remove all the objects owned by Flagger like Istio virtual services, +Kubernetes deployments and ClusterIP services. + +If you want to remove all the objects created by Flagger you have delete the Canary CRD with kubectl: + +```text +kubectl delete crd canaries.flagger.app +``` + +### Install Grafana + +Flagger comes with a Grafana dashboard made for monitoring the canary analysis. + +Deploy Grafana in the _**istio-system**_ namespace: + +```bash +helm upgrade -i flagger-grafana flagger/grafana \ +--namespace=istio-system \ +--set url=http://prometheus.istio-system:9090 \ +--set user=admin \ +--set password=change-me +``` + +Or use helm template command and apply the generated yaml with kubectl: + +```bash +# generate +helm template flagger/grafana \ +--name flagger-grafana \ +--namespace=istio-system \ +--set url=http://prometheus.istio-system:9090 \ +--set user=admin \ +--set password=change-me \ +> $HOME/flagger-grafana.yaml + +# apply +kubectl apply -f $HOME/flagger-grafana.yaml +``` + +You can access Grafana using port forwarding: + +```bash +kubectl -n istio-system port-forward svc/flagger-grafana 3000:3000 +``` + +### Install Load Tester + +Flagger comes with an optional load testing service that generates traffic +during canary analysis when configured as a webhook. + +Deploy the load test runner with Helm: + +```bash +helm upgrade -i flagger-loadtester flagger/loadtester \ +--namepace=test \ +--set cmd.logOutput=true \ +--set cmd.timeout=1h +``` + +Deploy with kubectl: + +```bash +export REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master + +kubectl -n test apply -f ${REPO}/artifacts/loadtester/deployment.yaml +kubectl -n test apply -f ${REPO}/artifacts/loadtester/service.yaml +``` + +> **Note** that the load tester should be deployed in a namespace with Istio sidecar injection enabled. + diff --git a/docs/gitbook/install/install-flagger.md b/docs/gitbook/install/install-flagger.md deleted file mode 100644 index fd85d34d..00000000 --- a/docs/gitbook/install/install-flagger.md +++ /dev/null @@ -1,75 +0,0 @@ -# Install Flagger - -Before installing Flagger make sure you have [Istio](https://istio.io) running with Prometheus enabled. -If you are new to Istio you can follow this GKE guide -[Istio service mesh walk-through](https://docs.flagger.app/install/install-istio). - -**Prerequisites** - -* Kubernetes >= 1.11 -* Istio >= 1.0 -* Prometheus >= 2.6 - -### Install with Helm and Tiller - -Add Flagger Helm repository: - -```bash -helm repo add flagger https://flagger.app -``` - -Deploy Flagger in the _**istio-system**_ namespace: - -```bash -helm upgrade -i flagger flagger/flagger \ ---namespace=istio-system \ ---set metricsServer=http://prometheus.istio-system:9090 -``` - -Enable **Slack** notifications: - -```bash -helm upgrade -i flagger flagger/flagger \ ---namespace=istio-system \ ---set slack.url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \ ---set slack.channel=general \ ---set slack.user=flagger -``` - -### Install with kubectl - -If you don't have Tiller you can use the helm template command and apply the generated yaml with kubectl: - -```bash -# generate -helm template flagger/flagger \ ---name flagger \ ---namespace=istio-system \ ---set metricsServer=http://prometheus.istio-system:9090 \ ---set controlLoopInterval=1m > $HOME/flagger.yaml - -# apply -kubectl apply -f $HOME/flagger.yaml -``` - -### Uninstall - -To uninstall/delete the flagger release with Helm run: - -```text -helm delete --purge flagger -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -> **Note** that on uninstall the Canary CRD will not be removed. -Deleting the CRD will make Kubernetes remove all the objects owned by Flagger like Istio virtual services, -Kubernetes deployments and ClusterIP services. - - -If you want to remove all the objects created by Flagger you have delete the Canary CRD with kubectl: - -```text -kubectl delete crd canaries.flagger.app -``` - diff --git a/docs/gitbook/install/install-grafana.md b/docs/gitbook/install/install-grafana.md deleted file mode 100644 index 9fc9a69b..00000000 --- a/docs/gitbook/install/install-grafana.md +++ /dev/null @@ -1,48 +0,0 @@ -# Install Grafana - -Flagger comes with a Grafana dashboard made for monitoring the canary analysis. - -### Install with Helm and Tiller - -Add Flagger Helm repository: - -```bash -helm repo add flagger https://flagger.app -``` - -Deploy Grafana in the _**istio-system**_ namespace: - -```bash -helm upgrade -i flagger-grafana flagger/grafana \ ---namespace=istio-system \ ---set url=http://prometheus:9090 \ ---set user=admin \ ---set password=admin -``` - -### Install with kubectl - -If you don't have Tiller you can use the helm template command and apply the generated yaml with kubectl: - -```bash -# generate -helm template flagger/grafana \ ---name flagger-grafana \ ---namespace=istio-system \ ---set user=admin \ ---set password=admin > $HOME/flagger-grafana.yaml - -# apply -kubectl apply -f $HOME/flagger-grafana.yaml -``` - -### Uninstall - -To uninstall/delete the Grafana release with Helm run: - -```text -helm delete --purge flagger-grafana -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. -