This tutorial will be divided into two parts, due to necessary complexity involved in both using the service mesh itself for east-west traffic and the endpoint ingress for NGINX ingress controller with support for DNS and certificates.
- Part 1
- Cloud Resources
- Google Kubernetes Engine
- Google Contianer Registry
- Kubernetes Resources
- o11y (observability)
- Jaeger
- OpenTelemetry Collector
- Prometheus
- Grafana
- nsm (NGINX service mesh)
- o11y (observability)
- Cloud Resources
- Part 2
- Cloud Resources
- Google Cloud DNS zone
- Kubenetes Components
- external-dns
- cert-manager
- kubernetes-ingress (NGINX ingress controller)
- Cloud Resources
- Observability
- NGINX service mesh in strict mode
- Dgraph demo
- show that non-mesh traffic doesn't work
- show that mesh traffic works
- Install Kubernetes addons in the following order:
- CertManager - automates installing certificates
- NGINX+ Ingress Controller - integrates into NSM, requires NGINX+ license
- ExternalDNS - automates updating DNS records
- Access Endpoint Demo
- demonstrate access with
grpcurlandcurl - demonstrate visualization with Ratel
- demonstrate access with
The following tools are needed:
nginx-meshctlkubectlhelmhelmfilegcloud
- Configure appropriate
env.shand source it. See./scripts/part_1/example.env.sh - Setup project structure:
./scripts/part_1/setup.sh - Enable Projects:
./scripts/part_1/project.sh - Create GKE cluster:
./scripts/part_1/gke.sh - Enabled GCR:
./scripts/part_1/gcr.sh - Deploy NSM with observability:
pushd o11y && ./fetch_manifests.sh && popd helmfile --file ./o11y/helmfile.yaml apply export NSM_ACCESS_CONTROL_MODE=allow # deny causes problems helmfile --file ./nsm/helmfile.yaml apply
- Deploy Dgraph database service with manual injection:
kubectl get namespace "dgraph" > /dev/null 2> /dev/null \ || kubectl create namespace "dgraph" \ && kubectl label namespaces "dgraph" name="dgraph" helmfile --file dgraph/helmfile.yaml template \ | nginx-meshctl inject \ --ignore-incoming-ports 5080,7080 \ --ignore-outgoing-ports 5080,7080 \ | kubectl apply --namespace "dgraph" --filename -
- Build-Publish Containers:
pushd ./clients bash /fetch_scripts.sh pushd ./examples/pydgraph make build make push popd popd
- Deploy pygraph-client that is part of Mesh (positive test)
kubectl get namespace "pydgraph-client" > /dev/null 2> /dev/null \ || kubectl create namespace "pydgraph-client" \ && kubectl label namespaces "pydgraph-client" name="pydgraph-client" helmfile --file ./clients/examples/pydgraph/helmfile.yaml template \ | nginx-meshctl inject \ | kubectl apply --namespace "pydgraph-client" --filename -
- Deploy pygraph-client that is NOT PART OF MESH (negative test)
helmfile \ --file ./clients/examples/pydgraph/helmfile.yaml \ --namespace "pydgraph-no-mesh" \ apply - Negative Test: Execute into Container
export CLIENT_NAMESPACE="pydgraph-no-mesh" # Exec into pydgraph-client PYDGRAPH_POD=$( kubectl get pods --namespace $CLIENT_NAMESPACE --output name ) kubectl exec -ti \ --container "pydgraph-client" \ --namespace $CLIENT_NAMESPACE \ ${PYDGRAPH_POD} -- bash
- Run Negative Test
# test gRPC (should fail) grpcurl -plaintext -proto api.proto \ ${DGRAPH_ALPHA_SERVER}:9080 \ api.Dgraph/CheckVersion # test HTTP connection (should fail) curl --silent ${DGRAPH_ALPHA_SERVER}:8080/health echo $? curl --silent ${DGRAPH_ALPHA_SERVER}:8080/state echo $? # Load Data with pydgraph-client (should fail) python3 load_data.py \ --plaintext \ --alpha ${DGRAPH_ALPHA_SERVER}:9080 \ --files ./sw.nquads.rdf \ --schema ./sw.schema logout
- Positive Test: Execute into Container
export CLIENT_NAMESPACE="pydgraph-client" # Exec into pydgraph-client PYDGRAPH_POD=$( kubectl get pods --namespace $CLIENT_NAMESPACE --output name ) kubectl exec -ti \ --container "pydgraph-client" \ --namespace $CLIENT_NAMESPACE \ ${PYDGRAPH_POD} -- bash
- Run Postive Test
# test gRPC connection grpcurl -plaintext -proto api.proto \ ${DGRAPH_ALPHA_SERVER}:9080 \ api.Dgraph/CheckVersion # test HTTP connection curl --silent ${DGRAPH_ALPHA_SERVER}:8080/health | jq curl --silent ${DGRAPH_ALPHA_SERVER}:8080/state | jq ####################### # Load Data with pydgraph-client ########################################## python3 load_data.py \ --plaintext \ --alpha ${DGRAPH_ALPHA_SERVER}:9080 \ --files ./sw.nquads.rdf \ --schema ./sw.schema
- Configure appropriate
env.shand source it. See./scripts/part_2/example.env.sh - Setup project structure:
./scripts/part_2/setup.sh - Enable Projects:
./scripts/part_1/project.sh - Setup Workload Identity :
./scripts/part_1/wi.sh - Install CertManager
helmfile --file ./kube_addons/cert_manager/helmfile.yaml apply helmfile --file ./kube_addons/cert_manager/issuers.yaml apply
- Republish NGINX+ Ingress Controller images
source env.sh PRIV_REG="private-registry.nginx.com" if [[ "$(uname -s)" == "Linux" ]]; then DOCKER_CERTS_PATH="/etc/docker/certs.d/$PRIV_REG" sudo mkdir -p $DOCKER_CERTS_PATH elif [[ "$(uname -s)" == "Darwin" ]]; then DOCKER_CERTS_PATH="$HOME/.docker/certs.d/$PRIV_REG" mkdir -p $DOCKER_CERTS_PATH fi if [[ -f nginx-repo.crt || -f nginx-repo.key ]]; then cp nginx-repo.crt $DOCKER_CERTS_PATH/client.cert cp nginx-repo.key $DOCKER_CERTS_PATH/client.key fi NGINX_IC_NAP_IMAGE="$PRIV_REG/nginx-ic-nap/nginx-plus-ingress" docker pull $NGINX_IC_NAP_IMAGE:2.3.0 docker tag $NGINX_IC_NAP_IMAGE:2.3.0 gcr.io/$GCR_PROJECT_ID/nginx-plus-ingress:2.3.0 docker push gcr.io/$GCR_PROJECT_ID/nginx-plus-ingress:2.3.0
- Install NGINX+ Ingress Controller
export NGINX_APP_PROTECT=true helmfile --file ./kube_addons/nginx_ic/helmfile.yaml apply - Install ExternalDNS
helmfile --file ./kube_addons/external_dns/helmfile.yaml apply
- Install Ratel
kubectl get namespace "ratel" > /dev/null 2> /dev/null \ || kubectl create namespace "ratel" \ && kubectl label namespaces "ratel" name="ratel" helmfile --file ratel/helmfile.yaml template \ | nginx-meshctl inject \ | kubectl apply --namespace "ratel" --filename -
- Deploy Virtual Server
helmfile --file ./ratel/vs.yaml apply export MY_IP_ADDRESS=$(curl --silent ifconfig.me) helmfile --file ./dgraph/vs.yaml apply
- Test Virtual Server
curl dgraph.${DNS_DOMAIN}/health | jq curl dgraph.${DNS_DOMAIN}/state | jq curl -sOL https://raw.githubusercontent.com/dgraph-io/pydgraph/master/pydgraph/proto/api.proto api.proto grpcurl -proto api.proto grpc.$DNS_DOMAIN:443 api.Dgraph/CheckVersion
This is experimental and under development
- Patch NSM to deny all traffic
export NSM_ACCESS_CONTROL_MODE=deny helmfile --file ./nsm/helmfile.yaml apply kubectl delete --namespace "nginx-mesh" \ $(kubectl get pods --namespace "nginx-mesh" --selector "app.kubernetes.io/name=nginx-mesh-api" --output name) nginx-meshctl config | jq -r .accessControlMode
- Exec into Client Container
export CLIENT_NAMESPACE="pydgraph-client" PYDGRAPH_POD=$(kubectl get pods --namespace $CLIENT_NAMESPACE --output name) kubectl exec -ti \ --container "pydgraph-client" \ --namespace $CLIENT_NAMESPACE \ ${PYDGRAPH_POD} -- bash
- Negative Test:
# SHOULD FAIL (but does not) grpcurl -plaintext -proto api.proto \ ${DGRAPH_ALPHA_SERVER}:9080 \ api.Dgraph/CheckVersion # SHOULD FAIL curl --silent ${DGRAPH_ALPHA_SERVER}:8080/health curl --silent ${DGRAPH_ALPHA_SERVER}:8080/state logout
- Patch Ratel
NSM_ACCESS_CONTROL_MODE=$(nginx-meshctl config | jq -r .accessControlMode) helmfile --file ratel/vs.yaml apply - Patch Dgraph Server (Dgraph Needs ServiceAccount Support - NOT YET IMPLEMENTED)
NSM_ACCESS_CONTROL_MODE=$(nginx-meshctl config | jq -r .accessControlMode) helmfile --file ./dgraph/vs.yaml apply - Patch Pydgraph Client (NOT YET IMPLEMENTED)
NSM_ACCESS_CONTROL_MODE=$(nginx-meshctl config | jq -r .accessControlMode) helmfile --file access.yaml apply