Hace justamente un año escribí tres artículos relacionados con Open Service Mesh y cómo podías instalarlo en tu clúster de Kubernetes. Por aquel entonces estaba en la versión 1.0.0. Hoy tengo que volver a retomarlo, en su versión 1.2.3, y con la integración con AKS fuera de preview. En este artículo te cuento cómo usarlo y te comparto el ejemplo de entonces actualizado y funcionando.
Crear un clúster de AKS con el add-on de OSM
Lo bueno es que a día de hoy tienes un addon fuera de preview que te facilita la instalación de OSM en AKS. Es tan sencillo como lo siguiente:
# Variables
RESOURCE_GROUP="open-service-mesh-demo"
LOCATION="northeurope"
AKS_NAME="aks-osm-addon"
# Create resource group
az group create --name $RESOURCE_GROUP --location $LOCATION
# Create AKS cluster with Open Service Mesh enabled
az aks create \
--resource-group $RESOURCE_GROUP \
--name $AKS_NAME \
--node-vm-size Standard_B4ms \
--enable-addons open-service-mesh \
--generate-ssh-keys
# Get credentials
az aks get-credentials \
--resource-group $RESOURCE_GROUP \
--name $AKS_NAME
Simplemente añadiendo el parámetro –enable-addons open-service-mesh como parte de la creación de tu clúster se instala la versión compatible con la versión de Kubernetes que hayas elegido. En este caso, al no indicar la versión de Kubernetes que queremos se instalará la última versión disponible y por lo tanto la última versión de Open Service Mesh, que es la 1.2.3.
Si quieres puedes lanzar las siguiente comprobaciones para validar que se ha instalado correctamente el add-on:
# Verify that the OSM add-on is installed on your cluster
az aks show --resource-group $RESOURCE_GROUP --name $AKS_NAME --query 'addonProfiles.openServiceMesh.enabled'
# You can also verify the version, status, and configuration of the OSM mesh that's running on your cluster.
kubectl get deployment -n kube-system osm-controller -o=jsonpath='{$.spec.template.spec.containers[:1].image}'
# Verify the status od the OSM components running on your cluster
kubectl get deployments -n kube-system --selector app.kubernetes.io/name=openservicemesh.io
kubectl get pods -n kube-system --selector app.kubernetes.io/name=openservicemesh.io
kubectl get services -n kube-system --selector app.kubernetes.io/name=openservicemesh.io
# Verify the configuration of your OSM mesh, use kubectl get meshconfig
kubectl get meshconfig osm-mesh-config -n kube-system -o yaml
Desplegar una aplicación de ejemplo
Ahora que ya tienes un clúster con Open Service Mesh con el que jugar lo siguiente que necesitas es una aplicación. Voy a utilizar la misma que hace un año, con sus paquetes actualizados y desplegadas las imágenes en Github Packages.
# Deploy demo application in AKS #
##################################
# Deploy manifests in AKS/K8s cluster
kubectl apply -f manifests/.
# Check if the pods are ready
kubectl get pods -n bookstore
kubectl get pods -n bookbuyer
kubectl get pods -n bookthief
# Check if the services are ready
kubectl get services -n bookstore
kubectl get services -n bookbuyer
kubectl get services -n bookthief
Estas las dejé con servicios del tipo Load Balancer para que comprobaras que antes de que OSM controle los namespaces donde están alojadas, y se inyecte el sidecar, puedes acceder a ellas sin problemas desde Internet.
Instalar OSM CLI
Para poder inyectar las anotaciones necesarias para OSM en los namespaces, además de otras funciones, puedes instalar el CLI de la siguiente manera:
# Install osm cli (1.2.3)
# Specify the OSM version that will be leveraged throughout these instructions
OSM_VERSION=v1.2.3
# macOS curl command only
curl -sL "https://github.com/openservicemesh/osm/releases/download/$OSM_VERSION/osm-$OSM_VERSION-darwin-amd64.tar.gz" | tar -vxzf -
# arm
curl -sL "https://github.com/openservicemesh/osm/releases/download/$OSM_VERSION/osm-$OSM_VERSION-darwin-arm64.tar.gz" | tar -vxzf -
# move the osm binary to your PATH
sudo mv ./darwin-amd64/osm /usr/local/bin/osm
# move the osm binary to your PATH - arm
sudo mv ./darwin-arm64/osm /usr/local/bin/osm
osm version
En este artículo te muestro cómo instalarlo para Mac, tanto con procesador Intel como ARM. En este enlace tienes más información para el resto de sistemas operativos.
Añadir los namespaces a OSM
Ahora que ya tienes la aplicación desplegada y funcionando, el siguiente paso es agregar los namespaces de esta bajo el control de OSM. Para ello puedes utilizar bien el CLI que te acabas de descargar:
# Now we enable osm for their namespaces
osm namespace add bookstore bookbuyer bookthief
O bien, a través del portal de Azure, si accedes a tu clúster de AKS verás un apartado llamado Open Service Mesh donde podrás ver los namespaces que acabas de agregar y/o añadir otros a través del botón Add+.
Si ahora reinicias los despliegues asociados a los componentes en estos namespaces:
# deployment restart
kubectl rollout restart deployment/bookthief -n bookthief
kubectl rollout restart deployment/bookbuyer -n bookbuyer
kubectl rollout restart deployment/bookstore -n bookstore
Comprobarás que has perdido el acceso a los mismos, a través de su IP pública, ya que a partir de ahora todo acceso está denegado por defecto.
Instalar Ingress Nginx Controller
Como comenté en el primer artículo de esta serie, lo ideal es tener un Ingress controller como punto de acceso de estos componentes y que sobre este se permita el acceso a través del recurso IngressBackend. Para instalar Nginx para este propósito puedes hacerlo de forma sencilla utilizando Helm:
# Configure nginx ingress controller
kubectl create ns ingress-nginx
# osm needs to monitor this namespace but not inject the sidecar
osm namespace add ingress-nginx --disable-sidecar-injection
# add ingress nginx helm repo
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz
Como ves, es necesario que OSM conozca de la existencia del namespace donde está el Ingress Controller pero, a través del parámetro –disable-sidecar-injection, no necesitamos inyectarle el envoy correspondiente.
Una vez desplegado necesitamos recuperar algunos valores que usaremos después:
# Get nginx ingress controller public IP
INGRESS_PUBLIC_IP=$(kubectl get svc -n ingress-nginx nginx-ingress-ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
NGINX_INGRESS_NS=ingress-nginx # replace <nginx-namespace> with the namespace where Nginx is installed
NGINX_INGRESS_SVC=nginx-ingress-ingress-nginx-controller # replace <nginx-ingress-controller-service> with the name of the nginx ingress controller service
Crear los Ingress e IngressBackend para los componentes
Para volver a tener acceso a los componentes, con el permiso de OSM, necesitamos crear por cada uno de ellos un Ingress y un IngressBackend:
#### Bookstore ingress and ingress backend ####
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bookstore-ingress
namespace: bookstore
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: bookstore.$INGRESS_PUBLIC_IP.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bookstore
port:
number: 80
---
kind: IngressBackend
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
name: bookstore-external-access
namespace: bookstore
spec:
backends:
- name: bookstore
port:
number: 3000 # targetPort of the service
protocol: http
sources:
- kind: Service
name: $NGINX_INGRESS_SVC
namespace: $NGINX_INGRESS_NS
EOF
#### Bookbuyer ingress and ingress backend ####
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: osm-ingress
namespace: bookbuyer
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: bookbuyer.$INGRESS_PUBLIC_IP.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bookbuyer
port:
number: 80
---
kind: IngressBackend
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
name: bookbuyer-external-access
namespace: bookbuyer
spec:
backends:
- name: bookbuyer
port:
number: 4000 # targetPort of the service
protocol: http
sources:
- kind: Service
name: $NGINX_INGRESS_SVC
namespace: $NGINX_INGRESS_NS
EOF
#### Bookthief ingress and ingress backend ####
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bookthief-ingress
namespace: bookthief
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: bookthief.$INGRESS_PUBLIC_IP.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bookthief
port:
number: 80
---
kind: IngressBackend
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
name: bookthief-external-access
namespace: bookthief
spec:
backends:
- name: bookthief
port:
number: 4001 # targetPort of the service
protocol: http
sources:
- kind: Service
name: $NGINX_INGRESS_SVC
namespace: $NGINX_INGRESS_NS
EOF
Una vez creados puedes acceder a cada uno de ellos con el resultado de esta consulta:
# Now you can access using this URLs
cat <<EOF
http://bookstore.$INGRESS_PUBLIC_IP.nip.io
http://bookbuyer.$INGRESS_PUBLIC_IP.nip.io
http://bookthief.$INGRESS_PUBLIC_IP.nip.io
EOF
También puedes utilizar osm verify para comprobar que los IngressBackend están configurados correctamente:
# Verify that the ingress backends are configured correctly
osm verify ingress --from-service $NGINX_INGRESS_NS/$NGINX_INGRESS_SVC \
--to-pod bookthief/$(kubectl get pods -n bookthief -l app=bookthief -o jsonpath='{.items[0].metadata.name}') \
--to-service bookthief \
--ingress-backend bookthief-external-access --to-port 4001 \
--osm-namespace kube-system
osm verify ingress --from-service $NGINX_INGRESS_NS/$NGINX_INGRESS_SVC \
--to-pod bookstore/$(kubectl get pods -n bookstore -l app=bookstore -o jsonpath='{.items[0].metadata.name}') \
--to-service bookstore \
--ingress-backend bookstore-external-access --to-port 3000 \
--osm-namespace kube-system
osm verify ingress --from-service $NGINX_INGRESS_NS/$NGINX_INGRESS_SVC \
--to-pod bookbuyer/$(kubectl get pods -n bookbuyer -l app=bookbuyer -o jsonpath='{.items[0].metadata.name}') \
--to-service bookbuyer \
--ingress-backend bookbuyer-external-access --to-port 4000 \
--osm-namespace kube-system
Por último, completando lo que conté en el artículo original, podemos limitar el acceso entre los componentes. En este punto todos pueden hablar con todos porque está habilitado el modo permisivo en Open Service Mesh. Puedes comprobarlo con este comando:
# Check permissive mode
kubectl get meshconfig osm-mesh-config -n kube-system -o jsonpath='{.spec.traffic.enablePermissiveTrafficPolicyMode}{"\n"}'
Para deshabilitarlo, puedes lanzar el siguiente patch sobre la configuración del mesh:
# Change to permissive mode to false
kubectl patch meshconfig osm-mesh-config -n kube-system -p '{"spec":{"traffic":{"enablePermissiveTrafficPolicyMode":false}}}' --type=merge
Si compruebas los diferentes componentes de nuevo verás que la comunicación no es posible de bookbuyer y bookthief a bookstore.
Para configurar la misma necesitamos definir un HTTPRouteGroup:
apiVersion: specs.smi-spec.io/v1alpha4
kind: HTTPRouteGroup
metadata:
name: bookstore-service-routes
namespace: bookstore
spec:
matches:
- name: buy-books
pathRegex: "/api/buy"
methods:
- GET
- name: steal-books
pathRegex: "/api/steal"
methods:
- GET
Y por último un TrafficTarget
kind: TrafficTarget
apiVersion: access.smi-spec.io/v1alpha3
metadata:
name: bookstore
namespace: bookstore
spec:
destination:
kind: ServiceAccount
name: bookstore
namespace: bookstore
sources:
- kind: ServiceAccount
name: bookbuyer
namespace: bookbuyer
- kind: ServiceAccount
name: bookthief
namespace: bookthief
rules:
- kind: HTTPRouteGroup
name: bookstore-service-routes
matches:
- buy-books
# - steal-books
Lo que dejaría la foto de la siguiente manera:
Estos recursos se pueden ver también a través del portal de Azure, si accedes al namespace de bookstore:

¡Saludos!