Add chart to deploy IstioOperator resource 18/4718/1
authorTodd Malsbary <todd.malsbary@intel.com>
Tue, 8 Mar 2022 00:25:58 +0000 (16:25 -0800)
committerTodd Malsbary <todd.malsbary@intel.com>
Tue, 8 Mar 2022 00:25:58 +0000 (16:25 -0800)
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
Change-Id: Ia1ca6cdc9a69ad47c4a5d2d09a23009522df9f22

deploy/istio/.helmignore [new file with mode: 0644]
deploy/istio/Chart.yaml [new file with mode: 0644]
deploy/istio/istio.sh [new file with mode: 0755]
deploy/istio/templates/istio-operator.yaml [new file with mode: 0644]
deploy/istio/values.yaml [new file with mode: 0644]
env/lib/common.sh

diff --git a/deploy/istio/.helmignore b/deploy/istio/.helmignore
new file mode 100644 (file)
index 0000000..81285a6
--- /dev/null
@@ -0,0 +1,24 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+istio.sh
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/deploy/istio/Chart.yaml b/deploy/istio/Chart.yaml
new file mode 100644 (file)
index 0000000..0beb1ae
--- /dev/null
@@ -0,0 +1,5 @@
+# A simple chart to deploy Istio using the Istio operator.
+apiVersion: v2
+name: istio
+type: application
+version: 0.1.0
diff --git a/deploy/istio/istio.sh b/deploy/istio/istio.sh
new file mode 100755 (executable)
index 0000000..ddac47d
--- /dev/null
@@ -0,0 +1,223 @@
+#!/usr/bin/env bash
+set -eEux -o pipefail
+
+SCRIPTDIR="$(readlink -f $(dirname ${BASH_SOURCE[0]}))"
+LIBDIR="$(dirname $(dirname ${SCRIPTDIR}))/env/lib"
+
+source $LIBDIR/common.sh
+
+BUILDDIR=${SCRIPTDIR/deploy/build}
+mkdir -p ${BUILDDIR}
+
+function test_setup {
+    clone_istio_repository
+
+    # Create a temporary kubeconfig file for the tests
+    cluster_name=${CLUSTER_1_NAME:-cluster-1}
+    local -r cluster_1_kubeconfig="${BUILDDIR}/${cluster_name}.conf"
+    clusterctl -n metal3 get kubeconfig ${cluster_name} >${cluster_1_kubeconfig}
+    cluster_name=${CLUSTER_2_NAME:-cluster-2}
+    local -r cluster_2_kubeconfig="${BUILDDIR}/${cluster_name}.conf"
+    clusterctl -n metal3 get kubeconfig ${cluster_name} >${cluster_2_kubeconfig}
+
+    # Deploy sleep on cluster-1
+    kubectl --kubeconfig=${cluster_1_kubeconfig}  create namespace foo
+    kubectl --kubeconfig=${cluster_1_kubeconfig} label namespace foo istio-injection=enabled
+    cat <<EOF | kubectl --kubeconfig=${cluster_1_kubeconfig} apply -f -
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: psp:privileged-foo
+  namespace: foo
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: psp:privileged
+subjects:
+- kind: Group
+  name: system:serviceaccounts:foo
+  apiGroup: rbac.authorization.k8s.io
+EOF
+    kubectl --kubeconfig=${cluster_1_kubeconfig} apply -n foo -f ${ISTIOPATH}/samples/sleep/sleep.yaml --wait
+
+    # Deploy httpbin on cluster-2
+    kubectl --kubeconfig=${cluster_2_kubeconfig} create namespace bar
+    kubectl --kubeconfig=${cluster_2_kubeconfig} label namespace bar istio-injection=enabled
+    cat <<EOF | kubectl --kubeconfig=${cluster_2_kubeconfig} apply -f -
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: psp:privileged-bar
+  namespace: bar
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: psp:privileged
+subjects:
+- kind: Group
+  name: system:serviceaccounts:bar
+  apiGroup: rbac.authorization.k8s.io
+EOF
+    kubectl --kubeconfig=${cluster_2_kubeconfig} apply -n bar -f ${ISTIOPATH}/samples/httpbin/httpbin.yaml --wait
+
+    # Create service entry for httpbin on cluster-1
+    cat <<EOF | kubectl --kubeconfig=${cluster_1_kubeconfig} apply -f -
+apiVersion: networking.istio.io/v1alpha3
+kind: ServiceEntry
+metadata:
+  name: httpbin-bar
+  namespace: foo
+spec:
+  hosts:
+  # DNS name selected for the service
+  - httpbin.bar.cluster2
+  # Treat remote cluster services as part of the service mesh
+  # as all clusters in the service mesh share the same root of trust.
+  location: MESH_INTERNAL
+  ports:
+  - name: tcp
+    number: 8000
+    protocol: TCP
+  resolution: DNS
+  addresses:
+  # the IP address to which httpbin.bar.cluster2 will resolve to
+  # must be unique for each remote service, within a given cluster.
+  # This address need not be routable. Traffic for this IP will be captured
+  # by the sidecar and routed appropriately.
+  - 240.0.0.2
+  endpoints:
+  # This is the routable address of the ingress gateway in cluster2 that
+  # sits in front of sleep.foo service. Traffic from the sidecar will be
+  # routed to this address.
+  - address: $(kubectl --kubeconfig=${cluster_2_kubeconfig} config view | awk -F[/:] '/server/ {print $5}')
+    ports:
+      tcp: 32001 # Nodeport for istio-ingressgateway for port 15433
+EOF
+
+    # Create DestinationRule for httpbin on cluster-1
+    cat <<EOF | kubectl --kubeconfig=${cluster_1_kubeconfig} apply -f -
+apiVersion: networking.istio.io/v1alpha3
+kind: DestinationRule
+metadata:
+  name: httpbin-dr
+  namespace: foo
+spec:
+  host: httpbin.bar.cluster2
+  trafficPolicy:
+    tls:
+      mode: ISTIO_MUTUAL
+EOF
+
+    # Create Gateway resource on cluster-2
+    cat <<EOF | kubectl --kubeconfig=${cluster_2_kubeconfig} apply -f -
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+  name: httpbin-gateway
+  namespace: istio-system
+spec:
+  selector:
+    istio: ingressgateway
+  servers:
+    - port:
+        number: 15443
+        name: tls
+        protocol: TLS
+      tls:
+        mode: AUTO_PASSTHROUGH
+      hosts:
+        - "httpbin.bar.cluster2"
+EOF
+
+    # Create ServiceEntry on cluster-2 that is required to map the
+    # remote fqdn to local fqdn
+    cat <<EOF | kubectl --kubeconfig=${cluster_2_kubeconfig} apply -f -
+apiVersion: networking.istio.io/v1alpha3
+kind: ServiceEntry
+metadata:
+  name: httpbin-remote
+  namespace: istio-system # must be in same namespace as gateway
+spec:
+  resolution: DNS
+  location: MESH_INTERNAL
+  ports:
+  - name: tcp
+    number: 8000
+    protocol: TCP
+  exportTo:
+  - .
+  hosts:
+  - "httpbin.bar.cluster2"
+  endpoints:
+  - address: httpbin.bar.svc.cluster.local
+EOF
+
+    # Create DestinationRule and Virtual Service on cluster-2
+    cat <<EOF | kubectl --kubeconfig=${cluster_2_kubeconfig} apply -f -
+apiVersion: networking.istio.io/v1beta1
+kind: DestinationRule
+metadata:
+  name: httpbin-dr
+  namespace: istio-system
+spec:
+  host: "httpbin.bar.cluster2"
+  trafficPolicy:
+    tls:
+      mode: ISTIO_MUTUAL
+EOF
+}
+
+function httpbin_accessible_from_sleep_service {
+    cluster_name=${CLUSTER_1_NAME:-cluster-1}
+    local -r cluster_1_kubeconfig="${BUILDDIR}/${cluster_name}.conf"
+    local -r sleep_pod=$(kubectl --kubeconfig=${cluster_1_kubeconfig} get -n foo pod -l app=sleep -o jsonpath={.items..metadata.name})
+    kubectl --kubeconfig=${cluster_1_kubeconfig} exec ${sleep_pod} -n foo -c sleep -- curl -I httpbin.bar.cluster2:8000/headers
+}
+
+function test_teardown {
+    cluster_name=${CLUSTER_1_NAME:-cluster-1}
+    local -r cluster_1_kubeconfig="${BUILDDIR}/${cluster_name}.conf"
+    cluster_name=${CLUSTER_2_NAME:-cluster-2}
+    local -r cluster_2_kubeconfig="${BUILDDIR}/${cluster_name}.conf"
+
+    kubectl --kubeconfig=${cluster_2_kubeconfig} -n istio-system delete DestinationRule httpbin-dr --ignore-not-found
+    kubectl --kubeconfig=${cluster_2_kubeconfig} -n istio-system delete ServiceEntry httpbin-remote --ignore-not-found
+    kubectl --kubeconfig=${cluster_2_kubeconfig} -n istio-system delete Gateway httpbin-gateway --ignore-not-found
+
+    kubectl --kubeconfig=${cluster_1_kubeconfig} -n foo delete DestinationRule httpbin-dr --ignore-not-found
+    kubectl --kubeconfig=${cluster_1_kubeconfig} -n foo delete ServiceEntry httpbin-bar --ignore-not-found
+
+    kubectl --kubeconfig=${cluster_2_kubeconfig} -n bar delete -f ${ISTIOPATH}/samples/httpbin/httpbin.yaml --ignore-not-found
+    kubectl --kubeconfig=${cluster_2_kubeconfig} -n bar delete RoleBinding psp:privileged-bar --ignore-not-found
+    kubectl --kubeconfig=${cluster_2_kubeconfig} delete namespace bar --ignore-not-found
+
+    kubectl --kubeconfig=${cluster_1_kubeconfig} -n foo delete -f ${ISTIOPATH}/samples/sleep/sleep.yaml --ignore-not-found
+    kubectl --kubeconfig=${cluster_1_kubeconfig} -n foo delete RoleBinding psp:privileged-foo --ignore-not-found
+    kubectl --kubeconfig=${cluster_1_kubeconfig} delete namespace foo --ignore-not-found
+}
+
+function test_istio {
+    test_setup
+
+    WAIT_FOR_INTERVAL=10s
+    WAIT_FOR_TRIES=6
+    wait_for httpbin_accessible_from_sleep_service
+
+    test_teardown
+}
+
+case $1 in
+    "test") test_istio ;;
+    *) cat <<EOF
+Usage: $(basename $0) COMMAND
+
+The "test" command looks for the CLUSTER_1_NAME and CLUSTER_2_NAME
+variables in the environment (default: "cluster-1" and "cluster-2").
+This should be the name of the Cluster resources to execute the tests
+in.
+
+Commands:
+  test          - Test Istio
+EOF
+       ;;
+esac
diff --git a/deploy/istio/templates/istio-operator.yaml b/deploy/istio/templates/istio-operator.yaml
new file mode 100644 (file)
index 0000000..6390d1a
--- /dev/null
@@ -0,0 +1,38 @@
+apiVersion: install.istio.io/v1alpha1
+kind: IstioOperator
+metadata:
+  name: {{ .Release.Name }}-config
+spec:
+  profile: minimal
+  meshConfig:
+    accessLogFile: /dev/stdout
+    enableAutoMtls: true
+    defaultConfig:
+      proxyMetadata:
+        # Enable Istio agent to handle DNS
+        ISTIO_META_DNS_CAPTURE: "true"
+  components:
+    # Enable Istio Ingress gateway
+    ingressGateways:
+    - name: istio-ingressgateway
+      enabled: true
+      k8s:
+        env:
+          - name: ISTIO_META_ROUTER_MODE
+            value: "sni-dnat"
+        service:
+          type: NodePort
+          ports:
+            - port: 80
+              targetPort: 8080
+              name: http2
+            - port: 443
+              targetPort: 8443
+              name: https
+            - port: 15443
+              targetPort: 15443
+              name: tls
+              nodePort: 32001
+  values:
+    global:
+      pilotCertProvider: istiod
diff --git a/deploy/istio/values.yaml b/deploy/istio/values.yaml
new file mode 100644 (file)
index 0000000..e69de29
index 8af4436..2cd93d6 100755 (executable)
@@ -69,6 +69,13 @@ KUBECTL_VERSION="v1.20.7"
 #The yq version to use
 YQ_VERSION="v4.20.1"
 
+#Istio repository URL
+ISTIOREPO="${ISTIOREPO:-https://github.com/istio/istio.git}"
+#Path to clone the Istio repo
+ISTIOPATH="/opt/src/istio"
+#Istio version to use
+ISTIO_VERSION="1.10.3"
+
 #Addon versions
 CDI_VERSION="v1.44.1"
 CPU_MANAGER_VERSION="v1.4.1"
@@ -300,6 +307,10 @@ function clone_emco_repository {
     clone_repository ${EMCOPATH} ${EMCOREPO} ${EMCO_VERSION}
 }
 
+function clone_istio_repository {
+    clone_repository ${ISTIOPATH} ${ISTIOREPO} ${ISTIO_VERSION}
+}
+
 function fetch_image {
     if [[ "${BM_IMAGE_URL}" && "${BM_IMAGE}" ]]; then
        mkdir -p "${IRONIC_DATA_DIR}/html/images"