Skip to content

Latest commit

 

History

History
275 lines (222 loc) · 8.14 KB

README.md

File metadata and controls

275 lines (222 loc) · 8.14 KB

istio-practice

Repo to collect the things I do to practice with Istio.

This guide is written with the assumption that the reader already understands and uses Docker and Kubernetes.

The guide has been developed using Linux and MacOS. Not so sure about Windows. Your mileage may vary.

This guide uses a kubernetes cluster in AWS EKS. For a version that uses your local dev machine, go here

Prerequisites

You need the following tools installed. Links have been provided to documentation on how to install them.

Clone this repository

git clone https://github.com/RothAndrew/istio-practice.git
cd istio-practice

Create a Kubernetes cluster using Terraform

Note: This requires real money and access to an AWS account where you can provision resources. It will create a VPC, subnets, the cluster, EC2 resources, and IAM resources. See main.tf for full details.

Make sure your AWS CLI is configured to point at the right profile. aws sts get-caller-identity without specifying a profile should point to where you want to deploy to.

cd eks
terraform init
terraform apply

If you get Error running command 'curl ...', just rerun terraform apply, the script that waits for the cluster to come up timed out.

Next, generate a kubeconfig context

aws eks update-kubeconfig --name "istio-practice-test-eks-cluster" --alias "istio-practice"

Your kubectl context should automatically switch. Run kubectl get nodes to be sure.

Install Istio using Istio Operator

  1. Install the operator

    istioctl operator init
  2. Install the Istio demo configuration profile

    kubectl create ns istio-system
    kubectl apply -f - <<EOF
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      namespace: istio-system
      name: example-istiocontrolplane
    spec:
      profile: demo
    EOF

BookInfo Demo App

  1. Deploy the app

    kubectl create ns bookinfo
    kubectl label ns bookinfo "istio-injection=enabled"
    kubectl -n bookinfo apply -f "https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml"
  2. Create a Gateway and VirtualService

    kubectl -n bookinfo apply -f "https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml"
  3. Ensure the app is reachable from the internet by going to http://<YourELBUrl>/productpage. Use the Elastic Load Balancer URL associated with the istio-ingressgateway service.

  4. Refresh the page a few times. Notice that the stars ratings change from black to red and disappear. This is because there are 3 versions of the "reviews" service. Later we will use destination rules to fix that.

  5. Delete the Gateway and VirtualService. We will create a new one once we have enabled HTTPS.

    kubectl -n bookinfo delete -f "https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml"

Mutual TLS

To force mTLS cluster-wide for all services managed in the istio mesh, run

kubectl apply -n istio-system -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
spec:
  mtls:
    mode: STRICT
EOF

HTTPS

Next, let's configure Istio to accept HTTPS traffic, and to redirect all HTTP traffic to HTTPS.

  1. Update istio's configuration to turn on SDS and HTTPS

    kubectl apply -f - <<EOF
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      namespace: istio-system
      name: example-istiocontrolplane
    spec:
      profile: demo
      values:
        gateways:
          istio-ingressgateway:
            sds:
              enabled: true
        global:
          k8sIngress:
            enabled: true
            enableHttps: true
            gatewayName: ingressgateway
    EOF
  2. Modify the Gateway istio-autogenerated-k8s-ingress to use STS and to redirect all HTTP traffic to HTTPS

    kubectl -n istio-system \
      patch gateway istio-autogenerated-k8s-ingress --type=json \
      -p='[{"op": "replace", "path": "/spec/servers/1/tls", "value": {"credentialName": "ingress-cert", "mode": "SIMPLE", "privateKey": "sds", "serverCertificate": "sds"}},{"op": "replace", "path": "/spec/servers/0/tls", "value": {"httpsRedirect": true}}]'
  3. Install cert-manager

    arkade install cert-manager
  4. Create a Route53 Record Set that points at the Elastic Load Balancer that got created for Istio's IngressGateway.

  5. Create the ClusterIssuers for cert-manager

    [email protected]
    kubectl apply -f - <<EOF
    apiVersion: cert-manager.io/v1alpha2
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-staging
      namespace: istio-system
    spec:
      acme:
        # The ACME server URL
        server: https://acme-staging-v02.api.letsencrypt.org/directory
        # Email address used for ACME registration
        email: "$EMAIL_ADDRESS"
        # Name of a secret used to store the ACME account private key
        privateKeySecretRef:
          name: letsencrypt-staging
        # Enable the HTTP-01 challenge provider
        solvers:
          - http01:
              ingress:
                class: istio
    ---
    apiVersion: cert-manager.io/v1alpha2
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-prod
      namespace: istio-system
    spec:
      acme:
        # The ACME server URL
        server: https://acme-v02.api.letsencrypt.org/directory
        # Email address used for ACME registration
        email: "$EMAIL_ADDRESS"
        # Name of a secret used to store the ACME account private key
        privateKeySecretRef:
          name: letsencrypt-prod
        # Enable the HTTP-01 challenge provider
        solvers:
          - http01:
              ingress:
                class: istio
    EOF
  6. Create a Certificate

    INGRESS_DOMAIN=foo.example.com
    kubectl apply -f - <<EOF
    apiVersion: cert-manager.io/v1alpha2
    kind: Certificate
    metadata:
      name: ingress-cert
      namespace: istio-system
    spec:
      secretName: ingress-cert
      issuerRef:
        name: letsencrypt-staging
        kind: ClusterIssuer
      commonName: $INGRESS_DOMAIN
      dnsNames:
      - $INGRESS_DOMAIN
    EOF

    If you want the istio-autogenerated-k8s-ingress Gateway to accept HTTPS traffice for multiple FQDNs, Add more FQDNs to the dnsNames property in the Certificate

  7. Create a new VirtualService that uses the correct DNS name

    kubectl apply -n bookinfo -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: bookinfo
    spec:
      hosts:
      - $INGRESS_DOMAIN
      gateways:
      - istio-autogenerated-k8s-ingress.istio-system.svc.cluster.local
      http:
      - match:
        - uri:
            exact: /productpage
        - uri:
            prefix: /static
        - uri:
            exact: /login
        - uri:
            exact: /logout
        - uri:
            prefix: /api/v1/products
        route:
        - destination:
            host: productpage
            port:
              number: 9080
    EOF
  8. Navigate to https://$INGRESS_DOMAIN/productpage. You should get the product page with a good HTTPS cert if you used letsencrypt-prod, or an untrusted one signed by "Fake LE" if you used letsencrypt-staging ClusterIssuer

  9. Navigate to http://$INGRESS_DOMAIN/productpage. Verify that it automatically redirects you to HTTPS.

Cleanup

  1. Delete the Terraform resources

    cd eks
    terraform destroy
  2. Delete the leftover Elastic Load Balancer in AWS EC2

  3. Delete the Route53 Record Set(s) that you created