<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Flomesh</title>
    <description>The latest articles on DEV Community by Flomesh (@flomesh).</description>
    <link>https://dev.to/flomesh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5409%2Ffc4c6611-36e6-4cc6-a67d-b023fa91d902.jpg</url>
      <title>DEV Community: Flomesh</title>
      <link>https://dev.to/flomesh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/flomesh"/>
    <language>en</language>
    <item>
      <title>osm-edge: Using access control policies to access services with the service mesh</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Tue, 08 Nov 2022 06:46:19 +0000</pubDate>
      <link>https://dev.to/flomesh/osm-edge-using-access-control-policies-to-access-services-with-the-service-mesh-5hel</link>
      <guid>https://dev.to/flomesh/osm-edge-using-access-control-policies-to-access-services-with-the-service-mesh-5hel</guid>
      <description>&lt;p&gt;Deploying a service mesh in a complex brownfield environment is a lengthy and gradual process requiring upfront planning, or there may exist use cases where you have a specific set of services that either aren't yet ready for migration or for some reason can not be migrated to service mesh.&lt;/p&gt;

&lt;p&gt;This blog post will talk about the approaches which can be used to enable services outside of the service mesh to communicate with services within the &lt;a href="https://flomesh.io/osm-edge"&gt;osm-edge&lt;/a&gt; service mesh.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/flomesh-io/osm-edge/"&gt;osm-edge&lt;/a&gt; forked from &lt;a href="https://github.com/openservicemesh/osm"&gt;Open Service Mesh&lt;/a&gt; is a lightweight, extensible, cloud-native, SMI-compatible service mesh built purposely for Edge computing. osm-edge uses lightweight programmable proxy &lt;a href="https://flomesh.io/pipy"&gt;Pipy&lt;/a&gt; as a sidecar proxy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jcZDy-4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9jtgh3t12dmfoadxdcr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jcZDy-4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9jtgh3t12dmfoadxdcr.png" alt="Accessing services within service mesh" width="880" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;osm-edge offers two ways to allow accessing services within the service mesh:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;via Ingress

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/flomesh-io/fsm"&gt;FSM&lt;/a&gt; Ingress controller&lt;/li&gt;
&lt;li&gt;Nginx Ingress controller&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Access Control

&lt;ul&gt;
&lt;li&gt;Service&lt;/li&gt;
&lt;li&gt;IPRange&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first method to access the services in the service mesh is via Ingress controller, and treat the services outside the mesh as the services inside the cluster. The advantage of this approach is that the setup is simple and straightforward and the disadvantages are also apparent, as you cannot achieve fine-grained access control, and all services outside the mesh can access services within the mesh.&lt;/p&gt;

&lt;p&gt;This article will focus on the second approach, which allows support for fine-grained access control on who can access services within the service mesh. This feature is newly added and available in release 1.2.0 &lt;a href="https://github.com/flomesh-io/osm-edge/releases/tag/v1.2.0"&gt;osm-edge v1.2.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Access Control can be configured via two resource types: Service and IP range. In terms of data transmission, it supports plaintext transmission and mTLS-encrypted traffic.&lt;/p&gt;

&lt;p&gt;Let's get started with a demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo environment preparation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Kubernetes cluster
&lt;/h3&gt;

&lt;p&gt;Using the minimalist Kubernetes distribution &lt;a href="https://getk8e.com"&gt;k8e&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sfL&lt;/span&gt; https://getk8e.com/install.sh | &lt;span class="nv"&gt;K8E_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;k8e-mesh &lt;span class="nv"&gt;INSTALL_K8E_EXEC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"server --cluster-init --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config"&lt;/span&gt; sh -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  osm-edge CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;:upper:] &lt;span class="o"&gt;[&lt;/span&gt;:lower:]&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1.2.0
curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://github.com/flomesh-io/osm-edge/releases/download/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/osm-edge-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.tar.gz | &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-vxzf&lt;/span&gt; -
./&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/osm version
&lt;span class="nb"&gt;cp&lt;/span&gt; ./&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/osm /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install osm-edge
&lt;/h3&gt;

&lt;p&gt;Execute the following commands to install the related components of osm-edge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;osm_namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;osm-system
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;osm_mesh_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;osm

osm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--mesh-name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_mesh_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--osm-namespace&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;osm.image.pullPolicy&lt;span class="o"&gt;=&lt;/span&gt;Always
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check to make sure all pods are up and running properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the sample application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Mock target service&lt;/span&gt;
kubectl create namespace httpbin
osm namespace add httpbin
kubectl apply &lt;span class="nt"&gt;-n&lt;/span&gt; httpbin &lt;span class="nt"&gt;-f&lt;/span&gt; https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/main/manifests/samples/httpbin/httpbin.yaml

&lt;span class="c"&gt;#Mock external service&lt;/span&gt;
kubectl create namespace curl
kubectl apply &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-f&lt;/span&gt; https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/main/manifests/samples/curl/curl.yaml

&lt;span class="c"&gt;#Wait for the dependent POD to start normally&lt;/span&gt;
kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ready pod &lt;span class="nt"&gt;-n&lt;/span&gt; httpbin &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;httpbin &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;180s
kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ready pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;180s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;At this point, we send a request from service  &lt;code&gt;curl&lt;/code&gt; to target service &lt;code&gt;httpbin&lt;/code&gt; by executing the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items..metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-sI&lt;/span&gt; http://httpbin.httpbin:14001/get
&lt;span class="nb"&gt;command &lt;/span&gt;terminated with &lt;span class="nb"&gt;exit &lt;/span&gt;code 56
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The access fails because by default the services outside the mesh cannot access the services inside the mesh and we need to apply an access control policy.&lt;/p&gt;

&lt;p&gt;Before applying the policy, you need to enable the access control feature, which is disabled by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl patch meshconfig osm-mesh-config &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{"spec":{"featureFlags":{"enableAccessControlPolicy":true}}}'&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; merge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plaintext transfer
&lt;/h3&gt;

&lt;p&gt;Data can be transferred in plaintext or with two-way TLS encryption. Plaintext transfer is relatively simple, so let's demonstrate the plaintext transfer scenario first.&lt;/p&gt;

&lt;h4&gt;
  
  
  Service-based access control
&lt;/h4&gt;

&lt;p&gt;First, create a &lt;code&gt;Service&lt;/code&gt; for service &lt;code&gt;curl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: v1
kind: Service
metadata:
  name: curl
  labels:
    app: curl
    service: curl
spec:
  ports:
    - name: http
      port: 80
  selector:
    app: curl
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create an access control policy with the source &lt;code&gt;Service&lt;/code&gt; &lt;code&gt;curl&lt;/code&gt; and the target service &lt;code&gt;httpbin&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
kind: AccessControl
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
  name: httpbin
  namespace: httpbin
spec:
  backends:
  - name: httpbin
    port:
      number: 14001 # targetPort of httpbin service
      protocol: http
  sources:
  - kind: Service
    namespace: curl
    name: curl
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute the command again to send the authentication request, and you can see that this time an &lt;code&gt;HTTP 200&lt;/code&gt; response is received.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items..metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-sI&lt;/span&gt; http://httpbin.httpbin:14001/get
HTTP/1.1 200 OK
server: gunicorn/19.9.0
&lt;span class="nb"&gt;date&lt;/span&gt;: Mon, 07 Nov 2022 08:47:55 GMT
content-type: application/json
content-length: 267
access-control-allow-origin: &lt;span class="k"&gt;*&lt;/span&gt;
access-control-allow-credentials: &lt;span class="nb"&gt;true
&lt;/span&gt;osm-stats-namespace: httpbin
osm-stats-kind: Deployment
osm-stats-name: httpbin
osm-stats-pod: httpbin-69dc7d545c-qphrh
connection: keep-alive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before continuing with the rest of the demonstration, execute the command &lt;code&gt;kubectl delete accesscontrol httpbin -n httpbin&lt;/code&gt; to delete the policy you just created.&lt;/p&gt;

&lt;h4&gt;
  
  
  IP range-based access control, plaintext transfer
&lt;/h4&gt;

&lt;p&gt;First, get the pod IP address of the service &lt;code&gt;curl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;curl_pod_ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items[0].status.podIP}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access control using IP ranges is simple, just set the access source type to &lt;code&gt;IPRange&lt;/code&gt; and configure the IP address you just obtained.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
kind: AccessControl
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
  name: httpbin
  namespace: httpbin
spec:
  backends:
  - name: httpbin
    port:
      number: 14001 # targetPort of httpbin service
      protocol: http
  sources:
  - kind: IPRange
    name: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;curl_pod_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;/32
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute the command again to test if the control policy is in effect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items..metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-sI&lt;/span&gt; http://httpbin.httpbin:14001/get
HTTP/1.1 200 OK
server: gunicorn/19.9.0
&lt;span class="nb"&gt;date&lt;/span&gt;: Mon, 07 Nov 2022 09:20:57 GMT
content-type: application/json
content-length: 267
access-control-allow-origin: &lt;span class="k"&gt;*&lt;/span&gt;
access-control-allow-credentials: &lt;span class="nb"&gt;true
&lt;/span&gt;osm-stats-namespace: httpbin
osm-stats-kind: Deployment
osm-stats-name: httpbin
osm-stats-pod: httpbin-69dc7d545c-qphrh
connection: keep-alive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to execute &lt;code&gt;kubectl delete accesscontrol httpbin -n httpbin&lt;/code&gt; to clean up the policy.&lt;/p&gt;

&lt;p&gt;The previous ones we used were plaintext transfers, next we look at encrypted transfers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encrypted transfers
&lt;/h3&gt;

&lt;p&gt;The default access policy certificate feature is off, turn it on by executing the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl patch meshconfig osm-mesh-config &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{"spec":{"featureFlags":{"enableAccessCertPolicy":true}}}'&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;merge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;AccessCert&lt;/code&gt; for the access source to assign a certificate for data encryption. The controller will store the certificate information in &lt;code&gt;Secret&lt;/code&gt; &lt;code&gt;curl-mtls-secret&lt;/code&gt; under the namespace &lt;code&gt;curl&lt;/code&gt;, and here also assign SAN &lt;code&gt;curl.curl.cluster.local&lt;/code&gt; for the access source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
kind: AccessCert
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
  name: curl-mtls-cert
  namespace: httpbin
spec:
  subjectAltNames:
  - curl.curl.cluster.local
  secret:
    name: curl-mtls-secret
    namespace: curl
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redeploy &lt;code&gt;curl&lt;/code&gt; and mount the system-assigned &lt;code&gt;Secret&lt;/code&gt; to the pod.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: apps/v1
kind: Deployment
metadata:
  name: curl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: curl
  template:
    metadata:
      labels:
        app: curl
    spec:
      serviceAccountName: curl
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - image: curlimages/curl
        imagePullPolicy: IfNotPresent
        name: curl
        command: ["sleep", "365d"]
        volumeMounts:
        - name: curl-mtls-secret
          mountPath: "/certs"
          readOnly: true
      volumes:
        - name: curl-mtls-secret
          secret:
            secretName: curl-mtls-secret
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Service-based Access Control
&lt;/h4&gt;

&lt;p&gt;The next step is to create an access control policy that uses encrypted transport. When configuring the target service, enable client certificate checking by specifying &lt;code&gt;tls.skipClientCertValidation = false&lt;/code&gt;. For the access source, in addition to the &lt;code&gt;Service&lt;/code&gt; type of access source, the SAN &lt;code&gt;curl.curl.cluster.local&lt;/code&gt; should be specified via &lt;code&gt;AuthenticatedPrincipal&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
kind: AccessControl
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
  name: httpbin
  namespace: httpbin
spec:
  backends:
  - name: httpbin
    port:
      number: 14001 # targetPort of httpbin service
      protocol: http
    tls:
      skipClientCertValidation: false
  sources:
  - kind: Service
    namespace: curl
    name: curl
  - kind: AuthenticatedPrincipal
    name: curl.curl.cluster.local
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test whether the access policy is effective. When sending the request, we have to specify the CA certificate, key and certificate to be used for the &lt;code&gt;curl&lt;/code&gt; command of the access source, which will be responded to by &lt;code&gt;HTTP 200&lt;/code&gt; normally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items..metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-ksI&lt;/span&gt; https://httpbin.httpbin:14001/get &lt;span class="nt"&gt;--cacert&lt;/span&gt; /certs/ca.crt &lt;span class="nt"&gt;--key&lt;/span&gt; /certs/tls.key &lt;span class="nt"&gt;--cert&lt;/span&gt; /certs/tls.crt
HTTP/2 200
server: gunicorn/19.9.0
&lt;span class="nb"&gt;date&lt;/span&gt;: Mon, 07 Nov 2022 10:44:05 GMT
content-type: application/json
content-length: 267
access-control-allow-origin: &lt;span class="k"&gt;*&lt;/span&gt;
access-control-allow-credentials: &lt;span class="nb"&gt;true
&lt;/span&gt;osm-stats-namespace: httpbin
osm-stats-kind: Deployment
osm-stats-name: httpbin
osm-stats-pod: httpbin-69dc7d545c-qphrh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  IP Range-Based Access Control
&lt;/h4&gt;

&lt;p&gt;After service-based access control, IP range-based control is simple. You just need to specify the type of access source as &lt;code&gt;IPRange&lt;/code&gt; and specify the IP address of the access source. As the application &lt;code&gt;curl&lt;/code&gt; is redeployed, its IP address needs to be retrieved (perhaps you have discovered the drawbacks of IP range-based access control).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;curl_pod_ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items[0].status.podIP}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
kind: AccessControl
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
  name: httpbin
  namespace: httpbin
spec:
  backends:
  - name: httpbin
    port:
      number: 14001 # targetPort of httpbin service
      protocol: http
    tls:
      skipClientCertValidation: false
  sources:
  - kind: IPRange
    name: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;curl_pod_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;/32
  - kind: AuthenticatedPrincipal
    name: curl.curl.cluster.local
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send the request again for testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items..metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; curl &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-ksI&lt;/span&gt; https://httpbin.httpbin:14001/get &lt;span class="nt"&gt;--cacert&lt;/span&gt; /certs/ca.crt &lt;span class="nt"&gt;--key&lt;/span&gt; /certs/tls.key &lt;span class="nt"&gt;--cert&lt;/span&gt; /certs/tls.crt
HTTP/2 200
server: gunicorn/19.9.0
&lt;span class="nb"&gt;date&lt;/span&gt;: Mon, 07 Nov 2022 10:58:55 GMT
content-type: application/json
content-length: 267
access-control-allow-origin: &lt;span class="k"&gt;*&lt;/span&gt;
access-control-allow-credentials: &lt;span class="nb"&gt;true
&lt;/span&gt;osm-stats-namespace: httpbin
osm-stats-kind: Deployment
osm-stats-name: httpbin
osm-stats-pod: httpbin-69dc7d545c-qphrh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bingo! The access is successful, indicating that our policy has taken effect&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This blog post will talk about the approaches which can be used to enable services outside of the service mesh to communicate with services within the osm-edge service mesh. There may exist use cases where you have a specific set of services that aren't yet ready for migration to service mesh or for some reason can't be migrated yet.&lt;/p&gt;

&lt;p&gt;The access control approaches presented in this article are suitable for solving such problems, and allow you to choose the appropriate type of access source and whether to transfer data in plaintext or encrypted, depending on your needs. The control is more granular than using a unified Ingress for access.&lt;/p&gt;

</description>
      <category>servicemesh</category>
      <category>accesscontrol</category>
      <category>osmedge</category>
      <category>pipyproxy</category>
    </item>
    <item>
      <title>Pipy: Protecting Kubernetes Apps from SQL Injection &amp; XSS Attacks</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Thu, 03 Nov 2022 13:12:06 +0000</pubDate>
      <link>https://dev.to/flomesh/pipy-protecting-kubernetes-apps-from-sql-injection-xss-attacks-dol</link>
      <guid>https://dev.to/flomesh/pipy-protecting-kubernetes-apps-from-sql-injection-xss-attacks-dol</guid>
      <description>&lt;p&gt;Injection attacks sliding down to 3rd position in 2021 have been on the &lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP Top 10&lt;/a&gt; list for many years and SQL Injection (SQLi) is a common injection technique used for attacking websites and web applications. Applications that do not cleanly separate user input from database commands are at risk of malicious input being executed as SQL commands. Successful injection attacks can lead to unauthorized access to sensitive data such as passwords, credit card details, and personal user information. Many recent high-profile data breaches have resulted from SQL injection attacks, resulting in reputational damage and regulatory fines.&lt;/p&gt;

&lt;p&gt;The common and normal workaround which you might have seen with other solutions is using a list of &lt;strong&gt;regular expressions&lt;/strong&gt; to filter out traffic, which works for some cases but falls short with some complex inputs or escaped inputs. We are not trying to bash &lt;code&gt;Regular Expressions&lt;/code&gt;, they are good and have their own use cases, but they aren't a good fit for such use cases.&lt;/p&gt;

&lt;p&gt;This blog post will demonstrate how to use &lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Pipy&lt;/a&gt; an open-source programmable proxy to harden the security by adding an extra layer of shield to your applications which might otherwise be vulnerable to such attacks.&lt;/p&gt;

&lt;p&gt;In a previous blog post announcing the latest release of &lt;a href="https://blog.flomesh.io/pipy-0-70-0-is-released-fe417b579fd2" rel="noopener noreferrer"&gt;Pipy 0.70.0&lt;/a&gt;, it was introduced that Pipy added the support of extensions called &lt;a href="https://flomesh.io/docs/en/reference/pjs/3-nmi" rel="noopener noreferrer"&gt;Native Module Interface (NMI)&lt;/a&gt; and we will be using Pipy NMI to develop a module to integrate with mature and stable open-source library &lt;a href="https://github.com/libinjection/libinjection" rel="noopener noreferrer"&gt;libinject&lt;/a&gt; to scan incoming traffic against SQLi and XSS attacks before it reaches the application.&lt;/p&gt;

&lt;p&gt;For the demo application, we will be using an open-source classical LAMP stack &lt;a href="https://hub.docker.com/r/naqvis/mamashop" rel="noopener noreferrer"&gt;Vulnerable Mama Shop (VMS)&lt;/a&gt; which is intentionally developed to have SQLi flaws. We will have fun together by first hacking the basic application to demonstrate the SQLi attacks, then we will harden the application security by adding Pipy as a sidecar to block certain SQLi attacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;This blog post assumes you have access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running Kubernetes cluster (dev box)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;kubectl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The demo source code is available on GitHub and can be downloaded from &lt;a href="https://github.com/flomesh-io/pipy-demos/tree/main/pipy-sqli-demo" rel="noopener noreferrer"&gt;pipy-sqli-demo&lt;/a&gt; repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Deploy Kubernetes cluster and Vulnerable Mama Shop App
&lt;/h2&gt;

&lt;p&gt;To run the demo locally, we recommend &lt;a href="https://k3d.io/" rel="noopener noreferrer"&gt;k3d&lt;/a&gt; a lightweight wrapper to run &lt;a href="https://github.com/rancher/k3s" rel="noopener noreferrer"&gt;k3s&lt;/a&gt; (Rancher Lab’s minimal Kubernetes distribution) in docker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;k3d cluster create my-cluster &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:30060@server:0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above command, we are creating a cluster with a single server and mapping port 30060 of the k3d container to the local 8080 port, usage of this port will become clear in the later steps of this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy Vulnerable Mama Shop App
&lt;/h2&gt;

&lt;p&gt;We are going to deploy a simple online store application that comes installed with&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apache Webserver&lt;/li&gt;
&lt;li&gt;MariaDB&lt;/li&gt;
&lt;li&gt;PHP app that runs on Apache and connects to the MariaDB database&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Use the text editor of your choice and create a YAML file called 1-app.yaml with the following contents:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;naqvis/mamashop&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30060&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Deploy the app
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; 1-app.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Confirm that pod is up and running, as indicated by the value Running in the STATUS column. It can take 30-40 seconds for them to fully deploy, so it’s useful to run the command again to confirm all pods are running before continuing to the next step.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get pods
NAME                   READY   STATUS    RESTARTS   AGE
vms-6658dd4478-hn246   1/1     Running   0          2m12s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Query the Servcice
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get svc vms
NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;        AGE
vms    NodePort   10.43.244.253   &amp;lt;none&amp;gt;        80:30060/TCP   5m43s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still remember at the beginning we did port mapping for the K3d container: &lt;code&gt;8080=&amp;gt;30060&lt;/code&gt;? Keen users may also find that we have created a NodePort service for our Vulnerable Mama Shop web application, and the node port is &lt;code&gt;30060&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the app in your browser by visiting the URL &lt;strong&gt;&lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd04tnbay6h9v6j2xjhc0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd04tnbay6h9v6j2xjhc0.jpg" alt="Vulnerable Mama Shop Welcome Page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hack the App
&lt;/h2&gt;

&lt;p&gt;Mama Shop is rather very basic, it comes with only 3 pages. The main page (shown above) is where a user can query items for sale through a drop-down box, a customer login page, and an about page. Play around with these 3 pages to see what each does and how each page works normally.&lt;/p&gt;

&lt;p&gt;Try submitting a category and see how items are listed. The following shows a listing of items from the Drinks category.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6kt3c7p6qpn2dwcn1hp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6kt3c7p6qpn2dwcn1hp.jpg" alt="Listing items in a Category"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you may have noticed, selecting a category and hitting submit doesn't change the URL, so the application is doing a &lt;code&gt;POST&lt;/code&gt; request and we will need some tool to intercept or view the traffic the web page is generating.&lt;/p&gt;

&lt;p&gt;Normally you will be using a proxy tool like Blurp suite or OWASP ZAP to intercept and modify the request to the application. But to keep things simple, we will be using Firefox browser Developer Console to view and modify the requests.&lt;/p&gt;

&lt;p&gt;Go back to your browser (Firefox in this demo) and turn on &lt;strong&gt;Web Developer Tools&lt;/strong&gt; either via &lt;code&gt;Tools | Browser Tools | Web Developer Tools&lt;/code&gt; menu option or via short-cut key &lt;code&gt;Option+Cmd+I&lt;/code&gt; on Mac or similar on your OS. Move to the &lt;code&gt;Network&lt;/code&gt; tab, and hit submit button on a web page to view the network traffic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbedwcyffbqgmdv6u1lka.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbedwcyffbqgmdv6u1lka.jpg" alt="Firefox Web Developer Tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see all of the requests along with all details, a web page makes to the webserver to display the page. Hit &lt;code&gt;Resend&lt;/code&gt; button at the top right of &lt;em&gt;Request details window&lt;/em&gt; displayed at the bottom right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d3dxv0ph9a56oajiaet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d3dxv0ph9a56oajiaet.png" alt="Web Developer Tools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Network action window shows that to browse items in a category, a URL encoded HTTP POST with a single parameter &lt;code&gt;catid&lt;/code&gt; is sent to &lt;code&gt;welcome.php&lt;/code&gt;. To test for SQL injection, it is common to modify user input and send a single quotation mark like &lt;strong&gt;&lt;code&gt;'&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modify Form Parameter
&lt;/h3&gt;

&lt;p&gt;We will find out if the input is properly escaped with a simple experiment: changing the &lt;code&gt;catid&lt;/code&gt; to a SQL query string, to see if it will cause a syntax error which may be shown on the webpage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;' or 1 = 1 ; --
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make above change and hit &lt;code&gt;send&lt;/code&gt; button at the bottom right of network action window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzhtw1k3ao5ptk5ewymj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzhtw1k3ao5ptk5ewymj.png" alt="Web Developer Tools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whoa, we are upto something, &lt;code&gt;welcome.php&lt;/code&gt; function for displaying category items have a SQL injection vulnerability. The error message also tells us the database is &lt;strong&gt;MariaDB&lt;/strong&gt;. And error is telling us that there is a syntax issue near &lt;code&gt;or 1 = 1&lt;/code&gt;. Using our imaginations, we can assume the database query is something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;item_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item_category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item_description&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;items_table&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;item_category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' or 1 = 1 ; -- ;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we were to change the &lt;code&gt;catid&lt;/code&gt; ending to &lt;code&gt;" or 1 = 1 -- ;&lt;/code&gt;, that should fix the quoting issue. It should select all rows from the database, which is useful in a hack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbbvqvtpb471jeg1h5r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbbvqvtpb471jeg1h5r4.png" alt="Retrieving all rows"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The structure of the assumed SQL query is probably correct, although it is not necessarily the exact query that the developer has used. This is sufficient for devasting attacks such as dumping customer information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extract User Data
&lt;/h3&gt;

&lt;p&gt;The customer login page tells us that the application contains customer data and this is likely stored in some sort of customer or user table.&lt;/p&gt;

&lt;p&gt;Based on our information gathered so far we can make use of the MariaDB INFORMATION_SCHEMA and the SQL Union operator to retrieve database and tables details.&lt;/p&gt;

&lt;p&gt;Change &lt;code&gt;catid&lt;/code&gt; parameter to below to retrieve database name, which will be further used to retrieve table details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;"A"&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"B"&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dual&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following shows the response from Vulnerable Mama Shop containing the database name, &lt;code&gt;appdb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgffnpi0lntqebti4hchn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgffnpi0lntqebti4hchn.png" alt="Retrieving database name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have database name, we can obtain the tables in the database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table_comment&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;table_schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'appdb'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we get a list of all tables, We can safely assume &lt;code&gt;users&lt;/code&gt; table in the database contains usernames and passwords.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95hfqfbew08v0nax2ko9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95hfqfbew08v0nax2ko9.png" alt="Retrieving list of tables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to retrieve list of columns &lt;code&gt;users&lt;/code&gt; table have and we will need to ensure that we use same number of columns as queried from products table for &lt;code&gt;UNION&lt;/code&gt; to work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COLUMN_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DATA_TYPE&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COLUMNS&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'users'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j6q1wzlufvq79ctyfxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j6q1wzlufvq79ctyfxl.png" alt="Retrieving user table structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know there are a total of six columns in the users table to contains details like firstname, lastname, nric, password, email are available from users table.&lt;/p&gt;

&lt;p&gt;We have gathered enough information to dump out a users listing. The following input can be used to dump out a listing of users with their firstname, password and email address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values for the LIMIT and offset can be worked out by observing how many item entries there are in a normal request. The offset value should remove these items. The LIMIT can be set a sufficiently large value so that customer records can be dumped out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ka41xiznqjd68a4yt4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ka41xiznqjd68a4yt4p.png" alt="Dumping all users"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Play around and use these gathered information to see if you can login with these credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Pipy Sidecar to block certain SQLi attacks
&lt;/h2&gt;

&lt;p&gt;SQL injection occurs when unvalidated user input is mixed with SQL instructions, so developers should pay more attention to escape user input (such as use of parameterized queries), but you  – the Kubernetes engineer  – can also help avoid SQL injection by preventing this attack from reaching the app. That way, even if the app is vulnerable, attacks can still be stopped.&lt;/p&gt;

&lt;p&gt;There are multiple options for protecting your apps, but for this blog post we will focus on &lt;strong&gt;injecting a sidecar container&lt;/strong&gt; to proxy all of the traffic and deny any request that is detected as SQLi attacks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For demonstration purposes, we are following the approach of manually injecting sidecar, but in reality, &lt;strong&gt;manually deploying proxies as sidecars isn’t the best solution&lt;/strong&gt;. The complexity of your apps and architecture might require more fine–grain control. If your organization requires &lt;strong&gt;Zero Trust&lt;/strong&gt; and has a need for &lt;strong&gt;end–to–end encryption&lt;/strong&gt;, consider a service mesh like &lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;osm-edge&lt;/a&gt; a light weight, ultra fast, low resources, highly extensible,  Service Mesh Interface (SMI) compatible, built for edge and cloud computing service mesh.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Deploying Pipy Sidecar
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a YAML file called 2-app-sidecar.yaml with the contents below, and check out these noteworthy components:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;A sidecar container running Pipy is started on port 8000.&lt;/li&gt;
&lt;li&gt;The Pipy process forwards all traffic to the app.&lt;/li&gt;
&lt;li&gt;Requests URI or &lt;code&gt;POST&lt;/code&gt; body containing SQLi is declined&lt;/li&gt;
&lt;li&gt;The service for the app routes all traffic to the Pipy sidecar container first.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;naqvis/mamashop&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pipy&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- sidecar&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;naqvis/pipy-nmi&lt;/span&gt;
          &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PIPY_CONFIG_FILE&lt;/span&gt;
              &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/pipy/nmi/nmi.js&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8000&lt;/span&gt;
          &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/pipy/nmi&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pipy-pjs&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pipy-pjs&lt;/span&gt;
          &lt;span class="na"&gt;configMap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sidecar&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8000&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- the traffic is routed to the proxy&lt;/span&gt;
      &lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30060&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vms&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConfigMap&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sidecar&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nmi.js&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
    &lt;span class="s"&gt;pipy({&lt;/span&gt;
      &lt;span class="s"&gt;_rejected: undefined,&lt;/span&gt;
    &lt;span class="s"&gt;})&lt;/span&gt;
      &lt;span class="s"&gt;.import({&lt;/span&gt;
        &lt;span class="s"&gt;__is_sqli: 'lib-inject',&lt;/span&gt;
        &lt;span class="s"&gt;__is_xss: 'lib-inject',&lt;/span&gt;
        &lt;span class="s"&gt;__sqli_fingerprint: 'lib-inject',&lt;/span&gt;
      &lt;span class="s"&gt;})&lt;/span&gt;
      &lt;span class="s"&gt;.listen(8000)&lt;/span&gt;
      &lt;span class="s"&gt;.demuxHTTP().to(&lt;/span&gt;
        &lt;span class="s"&gt;$=&amp;gt;$&lt;/span&gt;
            &lt;span class="s"&gt;.use('/etc/pipy/modules/inject-nmi.so')&lt;/span&gt;
            &lt;span class="s"&gt;.handleMessage(() =&amp;gt; _rejected = (__is_sqli || __is_xss))&lt;/span&gt;
            &lt;span class="s"&gt;.branch(&lt;/span&gt;
                &lt;span class="s"&gt;() =&amp;gt; _rejected === true, (&lt;/span&gt;
                &lt;span class="s"&gt;$=&amp;gt;$&lt;/span&gt;
                &lt;span class="s"&gt;.handleMessageStart(_ =&amp;gt;&lt;/span&gt;
                  &lt;span class="s"&gt;console.log(`SQL Injection found with Fingerprint: ${__sqli_fingerprint}`))&lt;/span&gt;
                &lt;span class="s"&gt;.replaceMessage(new Message({ status: 403 }, 'Forbidden'))&lt;/span&gt;
                &lt;span class="s"&gt;),&lt;/span&gt;
                &lt;span class="s"&gt;() =&amp;gt; _rejected === false, (&lt;/span&gt;
                  &lt;span class="s"&gt;$=&amp;gt;$.muxHTTP().to(&lt;/span&gt;
                      &lt;span class="s"&gt;$=&amp;gt;$.connect('localhost:80')&lt;/span&gt;
                  &lt;span class="s"&gt;)&lt;/span&gt;
                &lt;span class="s"&gt;)&lt;/span&gt;
            &lt;span class="s"&gt;)&lt;/span&gt;
      &lt;span class="s"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Deploy the side
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; 2-app-sidecar.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for pods to be up and ready&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
vms-945f6f85c-8v7sb   2/2     Running   0          8m48s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test the Sidecar
&lt;/h3&gt;

&lt;p&gt;Test whether the sidecar is filtering traffic by returning to the app and trying the SQL injection again. Pipy sidecar blocks the request before it reaches the app!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumwww30b1jbj8mfhmql2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumwww30b1jbj8mfhmql2.png" alt="Sidecar blocking SQLi traffic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sidecar is blocking the traffic by returning &lt;strong&gt;403 Forbidden&lt;/strong&gt;. Run few more requests with any of the previous SQLi attempts we made and we will be getting 403 back in response.&lt;br&gt;
We can validate that by looking at the logs of Pipy side car.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48b2h76sp13xqur33npn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48b2h76sp13xqur33npn.png" alt="Sidecar logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The purpose of learning about offensive techniques is to enable developers, defenders and security professionals to protect the confidentiality, the integrity and availability of critical information assets and services.&lt;/p&gt;

&lt;p&gt;Kubernetes is not secure by default. This blog post made use of Vulnerable Mama Shop, a simple application based on LAMP stack to demonstrate SQL injection attacks and how one can use techniques like SideCar to protect against them.&lt;/p&gt;

&lt;p&gt;But as the complexity of your apps and architecture grows, you might require more fine–grain control over your services. And if your organization requires Zero Trust and has a need for end–to–end encryption like mTLS, you should consider a service mesh like &lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;osm-edge&lt;/a&gt; a light weight, ultra fast, low resources, highly extensible,  Service Mesh Interface (SMI) compatible, built for edge and cloud computing service mesh. When you have communication between services (east–west traffic), a service mesh allows you to control traffic at that level.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>protection</category>
      <category>pipy</category>
      <category>sqlinjection</category>
    </item>
    <item>
      <title>Pipy 0.70.0 is released!</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Fri, 21 Oct 2022 15:26:06 +0000</pubDate>
      <link>https://dev.to/flomesh/pipy-0700-is-released-13mj</link>
      <guid>https://dev.to/flomesh/pipy-0700-is-released-13mj</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;a href="https://flomesh.io"&gt;&lt;code&gt;Pipy&lt;/code&gt;&lt;/a&gt; 0.70.0&lt;/strong&gt; is now available. This release consists of 170+ commits and comes with improvements to several areas including support for writing Pipy modules using C via Pipy Native Module Interface (NMI), PJS language extensions like looping construct, Map, Set, etc, protocols like Thrift, PROXY, TPROXY, Output UDP with Ephemeral ports, Encoder/Decoder for DNS protocol,  and more. This version of Pipy comes with a fresh and new design of modules/plugin system, enhanced Pipy unique Admin Console, IDE is now more robust and supports more features like Intellisense, parameters highlighting, hints, etc.&lt;br&gt;
This release continues on the great work of previous releases and optimization is done for PipyJS and code readability, better documentation, and some bug fixes.&lt;/p&gt;

&lt;p&gt;This release was indeed a community effort and could not have been made possible without all of the hard work from everyone involved in active discussions and the Pipy project on GitHub.The Pipy community provides code submissions covering new functionality and bug fixes, documentation improvements, quality assurance testing, continuous integration environments, bug reports, and more. Everyone has done their part to make this release possible! If you’d like to join this amazing community, you can find it on GitHub, Slack, and the Pipy discussion groups.&lt;/p&gt;

&lt;p&gt;Below we list the most remarkable changes in the Core API and PipyJS. For a detailed change log, refer to &lt;a href="https://github.com/flomesh-io/pipy/releases/tag/0.70.0-2"&gt;Pipy Release Page&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Core
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;NMI (Native Module Interface) for dynamically loaded modules written in C&lt;/li&gt;
&lt;li&gt;New module/plugin system by using chain() filters&lt;/li&gt;
&lt;li&gt;Support loop logic in pipelines by using the new replay() filter&lt;/li&gt;
&lt;li&gt;Builtin GUI frontend greatly reduced in size by using Brotli compression&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Protocols
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Support Thrift protocol&lt;/li&gt;
&lt;li&gt;Support the Proxy protocol proposed by HAProxy&lt;/li&gt;
&lt;li&gt;Support outbound UDP with ephemeral local ports&lt;/li&gt;
&lt;li&gt;Support TPROXY on UDP&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Implementation of the standard ECMAScript builtin objects Map and Set&lt;/li&gt;
&lt;li&gt;Encode and decode DNS messages&lt;/li&gt;
&lt;li&gt;Logging API now supports HTTPS receivers and Syslog&lt;/li&gt;
&lt;li&gt;Expose subject alternative names of a certificate&lt;/li&gt;
&lt;li&gt;Mux filters to support limit of maximum messages per session&lt;/li&gt;
&lt;li&gt;Netmask API now supports IPv6&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Documentation &amp;amp; Samples
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Renovation of the documentation system by using TypeScript&lt;/li&gt;
&lt;li&gt;All new tutorials with complete API reference&lt;/li&gt;
&lt;li&gt;New samples for HTTP proxy common use cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We would like to thank each and every contributor who was involved in this release.&lt;/p&gt;

</description>
      <category>proxy</category>
      <category>pipy</category>
      <category>kubernetes</category>
      <category>programming</category>
    </item>
    <item>
      <title>Flomesh Ingress Controller with Kubernetes Multi-tenancy</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Mon, 03 Oct 2022 13:10:34 +0000</pubDate>
      <link>https://dev.to/flomesh/flomesh-ingress-controller-with-kubernetes-multi-tenancy-1n09</link>
      <guid>https://dev.to/flomesh/flomesh-ingress-controller-with-kubernetes-multi-tenancy-1n09</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;It's very rare for organizations to have or provide a dedicated Kubernetes cluster to each tenant, as it's generally more cost-effective to share a cluster. Sharing clusters reduces expenses and streamlines management. Sharing clusters, however, also comes with difficulties like managing noisy neighbors and ensuring security.&lt;/p&gt;

&lt;p&gt;Clusters can be shared in many ways. In some cases, different applications may run in the same cluster. In other cases, multiple instances of the same application may run in the same cluster, one for each end user. All these types of sharing are frequently described using the umbrella term &lt;em&gt;multi-tenancy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;While Kubernetes does not have first-class concepts of end users or tenants, it provides several features to help manage different tenancy requirements. These are discussed below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A common form of multi-tenancy is to share a cluster between multiple teams within an organization, each of whom may operate one or more workloads.  In this scenario, members of the teams often have direct access to Kubernetes resources via tools such as kubectl, or indirect access through GitOps controllers or other types of release automation tools. There is often some level of trust between members of different teams, but Kubernetes policies such as RBAC, quotas, and network policies are essential to safely and fairly share clusters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The other major form of multi-tenancy frequently involves a Software-as-a-Service (SaaS) vendor running multiple instances of a workload for customers. This business model is so strongly associated with this deployment style that many people call it "SaaS tenancy." In this scenario, the customers do not have access to the cluster; Kubernetes is invisible from their perspective and is only used by the vendor to manage the workloads. Cost optimization is frequently a critical concern, and Kubernetes policies are used to ensure that the workloads are strongly isolated from each other.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tenant Isolation
&lt;/h3&gt;

&lt;p&gt;There are several ways to design and build multi-tenant solutions with Kubernetes at its control plane, data plane, or at both levels. Each of these methods comes with its own set of tradeoffs that impact the isolation level, implementation effort, operational complexity, and cost of service.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kubernetes Control plane isolation ensures that different tenants cannot access or affect each other's Kubernetes API resources, and Flomesh Service Mesh (FSM) Ingress controller provides isolated Ingress controllers for Kubernetes Namespaces.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Kubernetes, a &lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces" rel="noopener noreferrer"&gt;Namespace&lt;/a&gt; provides a mechanism for isolating groups of API resources within a single cluster. This isolation has two key dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Object names within a namespace can overlap with names in other namespaces, similar to files in folders. This allows tenants to name their resources without having to consider what other tenants are doing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Many Kubernetes security policies are scoped to namespaces. For example, RBAC Roles and Network Policies are namespace-scoped resources. Using RBAC, Users and Service Accounts can be restricted to a namespace.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a multi-tenant environment, a Namespace helps segment a tenant's workload into a logical and distinct management unit. A common practice is to isolate every workload in its namespace, even if multiple workloads are operated by the same tenant. This ensures that each workload has its own identity and can be configured with an appropriate security policy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this article, we will learn how to use the Flomesh Service Mesh Ingress controller to create physical isolation of Ingress controllers when hosting multiple tenants in your Kubernetes cluster.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Flomesh Service Mesh (FSM)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/flomesh-io/fsm" rel="noopener noreferrer"&gt;FSM&lt;/a&gt; is an open-source product from &lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Flomesh&lt;/a&gt; for Kubernetes north-south traffic, gateway API controller, and multi-cluster management. FSM uses &lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Pipy&lt;/a&gt;, a programmable proxy at its core, and provides an Ingress controller, &lt;em&gt;Gateway API&lt;/em&gt; controller, load balancer, cross-cluster service registration discovery, and more.&lt;/p&gt;

&lt;p&gt;FSM Ingress Controller supports a multi-tenancy model via its concept of &lt;code&gt;NamespacedIngress&lt;/code&gt; CRD where it deploys a physically isolated &lt;strong&gt;Ingress Controller&lt;/strong&gt; for requested &lt;strong&gt;Namespace&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, the YAML below defines an Ingress Controller that monitors on port 100 and also creates a LoadBalancer type service for it that listens on port 100.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flomesh.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NamespacedIngress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;namespaced-ingress-100&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-100&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;serviceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LoadBalancer&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4o3bjzdc85h7je19drl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4o3bjzdc85h7je19drl.png" alt="FSM NamespacedIngress"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install FSM
&lt;/h3&gt;

&lt;p&gt;FSM provides a standard Helm chart, which can be installed via the Helm CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;helm repo add fsm https://flomesh-io.github.io/fsm
&lt;span class="nv"&gt;$ &lt;/span&gt;helm repo update

&lt;span class="nv"&gt;$ &lt;/span&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;fsm fsm/fsm &lt;span class="nt"&gt;--namespace&lt;/span&gt; flomesh &lt;span class="nt"&gt;--create-namespace&lt;/span&gt; &lt;span class="nt"&gt;--set&lt;/span&gt; fsm.ingress.namespaced&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that all pods are up and running properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get po &lt;span class="nt"&gt;-n&lt;/span&gt; flomesh
NAME                                          READY   STATUS    RESTARTS   AGE
fsm-manager-6857f96858-sjksm                  1/1     Running   0          55s
fsm-repo-59bbbfdc5f-w7vg6                     1/1     Running   0          55s
fsm-bootstrap-8576c5ff4f-7qr7k                1/1     Running   0          55s
fsm-cluster-connector-local-8f8fb87f6-h7z9j   1/1     Running   0          32s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Sample Application
&lt;/h3&gt;

&lt;p&gt;In this demo, we will be deploying &lt;code&gt;httpbin&lt;/code&gt; service under a namespace &lt;code&gt;httpbin&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create Namespace&lt;/span&gt;
kubectl create ns httpbin

&lt;span class="c"&gt;# Deploy sample&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/main/manifests/samples/httpbin/httpbin.yaml &lt;span class="nt"&gt;-n&lt;/span&gt; httpbin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating a standalone Ingress Controller&lt;/p&gt;

&lt;p&gt;The next step is to create a separate Ingress Controller for the namespace &lt;code&gt;httpbin&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;$ kubectl apply -f - &amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flomesh.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NamespacedIngress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;namespaced-ingress-httpbin&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpbin&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;serviceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LoadBalancer&lt;/span&gt;
  &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;81&lt;/span&gt;
      &lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30081&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;500m&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;200Mi&lt;/span&gt;
    &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100m&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;20Mi&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After executing the above command, you will see an Ingress Controller running successfully under the namespace httpbin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get po &lt;span class="nt"&gt;-n&lt;/span&gt; httpbin &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsm-ingress-pipy
NAME                                        READY   STATUS    RESTARTS   AGE
fsm-ingress-pipy-httpbin-5594ffcfcc-zl5gl   1/1     Running   0          58s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, there should be a corresponding Service under this namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get svc &lt;span class="nt"&gt;-n&lt;/span&gt; httpbin &lt;span class="nt"&gt;-l&lt;/span&gt; app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;controller
NAME                       TYPE           CLUSTER-IP     EXTERNAL-IP    PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;        AGE
fsm-ingress-pipy-httpbin   LoadBalancer   10.43.62.120   192.168.1.11   81:30081/TCP   2m49s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have the Ingress Controller, it's time to create the Ingress resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;kubectl apply -f - &amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpbin&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpbin&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ingressClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pipy&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpbin.org&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httpbin&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14001&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have created Ingress resource, let's do a quick &lt;code&gt;curl&lt;/code&gt; to see if things are working as expected.&lt;/p&gt;

&lt;p&gt;For my local setup demo, LoadBalancer IP is &lt;code&gt;192.168.1.11&lt;/code&gt;, your IP might be different. So ensure you are performing a &lt;code&gt;curl&lt;/code&gt; against your setup ExternalIP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; http://192.168.1.11:81/get &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: httpbin.org"&lt;/span&gt;
HTTP/1.1 200 OK
server: gunicorn/19.9.0
&lt;span class="nb"&gt;date&lt;/span&gt;: Mon, 03 Oct 2022 12:02:04 GMT
content-type: application/json
content-length: 239
access-control-allow-origin: &lt;span class="k"&gt;*&lt;/span&gt;
access-control-allow-credentials: &lt;span class="nb"&gt;true
&lt;/span&gt;connection: keep-alive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog post, you learned about Kubernetes multi-tenancy, features provided by Kubernetes, tenancy isolation levels, and how to use Flomesh Service Mesh (FSM) Ingress controller to set up isolated Ingress controller for namespaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/flomesh-io/fsm" rel="noopener noreferrer"&gt;Flomesh Service Mesh(FSM)&lt;/a&gt; from &lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Flomesh&lt;/a&gt; is Kubernetes North-South traffic manager, provides Ingress controllers, Gateway API, Load Balancer, and cross-cluster service registration and service discovery. FSM uses &lt;a href="https://github.com/flomesh-io/pipy" rel="noopener noreferrer"&gt;Pipy&lt;/a&gt; - a programmable network proxy, as its data plane and is suitable for cloud, edge, and IoT.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ingresscontroller</category>
      <category>pipy</category>
      <category>ingress</category>
    </item>
    <item>
      <title>Using FSM Ingress controller with osm-edge service mesh</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Thu, 18 Aug 2022 15:18:11 +0000</pubDate>
      <link>https://dev.to/flomesh/using-fsm-ingress-controller-with-osm-edge-service-mesh-4moe</link>
      <guid>https://dev.to/flomesh/using-fsm-ingress-controller-with-osm-edge-service-mesh-4moe</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;The Kubernetes Ingress API is designed with a separation of concerns, where the Ingress implementation provides an entry feature infrastructure managed by operations staff; it also allows application owners to control the routing of requests to the backend through rules.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/flomesh-io/osm-edge"&gt;osm-edge&lt;/a&gt; supports multiple Ingress implementations to manage ingress traffic and provides the &lt;code&gt;IngressBackend&lt;/code&gt; API to configure back-end services to receive access from trusted ingress points. This article focuses on the integration of osm-edge with &lt;a href="https://github.com/flomesh-io/fsm"&gt;FSM&lt;/a&gt; to manage ingress traffic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RiatVQWC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s49fww6fvf1r8rkiueoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RiatVQWC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s49fww6fvf1r8rkiueoc.png" alt="FSM" width="880" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction to FSM
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/flomesh-io/fsm"&gt;FSM&lt;/a&gt; is another open-source product from &lt;a href="https://flomesh.io"&gt;Flomesh&lt;/a&gt; for Kubernetes north-south traffic, gateway api contoller, and multi-cluster management. FSM uses &lt;a href="https://flomesh.io"&gt;Pipy&lt;/a&gt;, a programmable proxy at its core, and provides an Ingress controller, &lt;em&gt;Gateway API&lt;/em&gt; controller, load balancer, cross-cluster service registration discovery, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration with FSM
&lt;/h2&gt;

&lt;p&gt;FSM is already integrated inside osm-edge and can be enabled during osm-edge installation; it can also be installed independently via helm for existing osm-edge mesh.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster, version 1.19.0 and higher&lt;/li&gt;
&lt;li&gt;Helm 3 CLI for standalone installation of FSM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Download the osm-edge CLI at&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;:upper:] &lt;span class="o"&gt;[&lt;/span&gt;:lower:]&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1.1.1
curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://github.com/flomesh-io/osm-edge/releases/download/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/osm-edge-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.tar.gz | &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-vxzf&lt;/span&gt; -
&lt;span class="nb"&gt;.&lt;/span&gt; /&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/osm version
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; /&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/osm /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrated installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;osm_namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;osm-system 
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;osm_mesh_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;osm 

osm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--set&lt;/span&gt; fsm.enabled&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--mesh-name&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_mesh_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--osm-namespace&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Standalone installation
&lt;/h3&gt;

&lt;p&gt;If osm-edge is installed without FSM enabled, you can use a standalone installation to install it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add fsm https://charts.flomesh.io

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;fsm_namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;osm-system 
helm &lt;span class="nb"&gt;install &lt;/span&gt;fsm fsm/fsm &lt;span class="nt"&gt;--namespace&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$fsm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--create-namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that all pods are up and running properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; osm-system
NAME READY STATUS RESTARTS AGE
repo-8756f76fb-2f78g 1/1 Running 0 5m53s
manager-866585bbd5-pbg7q 1/1 Running 0 5m53s
osm-bootstrap-7c6689ff57-47ksk 1/1 Running 0 5m53s
osm-controller-57888cfc7c-tnqxl 2/2 Running 0 5m52s
osm-injector-5f77898899-45f65 1/1 Running 0 5m53s
bootstrap-fd5894bcc-nr7hf 1/1 Running 0 5m53s
cluster-connector-local-68c7584c8b-qf7xm 1/1 Running 0 2m43s
ingress-pipy-6fb8c8b794-pgthl 1/1 Running 0 5m53s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;In order to authorize clients by restricting access to backend traffic, we will configure &lt;code&gt;IngressBackend&lt;/code&gt; so that only ingress traffic from the &lt;code&gt;ingress-pipy-controller&lt;/code&gt; endpoint can be routed to the backend service. In order to discover the &lt;code&gt;ingress-pipy-controller&lt;/code&gt; endpoint, we need the &lt;code&gt;osm-edge controller&lt;/code&gt; and the corresponding namespace to monitor it. However, to ensure that the FSM functions properly, it cannot be injected with sidecar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl label namespace &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; openservicemesh.io/monitored-by&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_mesh_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the external IP address and port of the entry gateway, which will be used later to test access to the backend application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ingress_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; get service ingress-pipy-controller &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.loadBalancer.ingress[0].ip}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ingress_port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; get service ingress-pipy-controller &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.ports[? (@.name=="http")].port}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$ingress_host&lt;/span&gt;:&lt;span class="nv"&gt;$ingress_port&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying the sample service
&lt;/h2&gt;

&lt;p&gt;The next step is to deploy the sample &lt;code&gt;httpbin&lt;/code&gt; service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## Create namespace kubectl create ns httpbin&lt;/span&gt;
kubectl create ns httpbin

&lt;span class="c"&gt;# Add the namespace to the grid&lt;/span&gt;
osm namespace add httpbin

&lt;span class="c"&gt;# Deploy the application&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
  namespace: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
  - name: http
    port: 14001
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      serviceAccountName: httpbin
      containers:
      - image: kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "-b", "0.0.0.0:14001", "httpbin:app", "-k", "gevent"]
        ports:
        - containerPort: 14001
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that the pod and service are created and the application is running successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods,services &lt;span class="nt"&gt;-n&lt;/span&gt; httpbin
NAME READY STATUS RESTARTS AGE
pod/httpbin-54cc8cf5d-7vclc 2/2 Running 0 14s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
service/httpbin ClusterIP 10.43.105.166 &amp;lt;none&amp;gt; 14001/TCP 14s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure entry rules
&lt;/h2&gt;

&lt;p&gt;Next we want to access the deployed &lt;code&gt;httpbin&lt;/code&gt; service from outside the cluster and need to provide the ingress configuration rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpbin
  namespace: httpbin
  annotations:
    pipy.ingress.kubernetes.io/rewrite-target-from: /httpbin
    pipy.ingress.kubernetes.io/rewrite-target-to: /httpbin
spec:
  ingressClassName: pipy
  rules:
  - host: httpbin.org
    http:
      paths:
      - path: /httpbin
        pathType: Prefix
        backend:
          service:
            name: httpbin
            port:
              number: 14001
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accessing the &lt;code&gt;httpbin&lt;/code&gt; service using the IP address and port recorded above will result in the following &lt;code&gt;502 Bad Gateway&lt;/code&gt; error response. This is because we have not set the ingress of the FSM as a trusted portal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; http://&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ingress_host&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ingress_port&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;/httpbin/get &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: httpbin.org"&lt;/span&gt;
HTTP/1.1 502 Bad Gateway
content-length: 0
connection: keep-alive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute the following command to set the FSM ingress as a trusted entry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
kind: IngressBackend
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
  name: httpbin
  namespace: httpbin
spec:
  backends:
  - name: httpbin
    port:
      number: 14001 # targetPort of httpbin service
      protocol: http
  sources:
  - kind: Service
    namespace: "&lt;/span&gt;&lt;span class="nv"&gt;$osm_namespace&lt;/span&gt;&lt;span class="sh"&gt;"
    name: ingress-pipy-controller
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try requesting the &lt;code&gt;httpbin&lt;/code&gt; service again, and you will be able to access it successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; http://&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ingress_host&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ingress_port&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;/httpbin/get &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: httpbin.org"&lt;/span&gt;
HTTP/1.1 200 OK
server: gunicorn/19.9.0
&lt;span class="nb"&gt;date&lt;/span&gt;: Thu, 18 Aug 2022 05:18:50 GMT
content-type: application/json
content-length: 241
access-control-allow-origin: &lt;span class="k"&gt;*&lt;/span&gt;
access-control-allow-credentials: &lt;span class="nb"&gt;true
&lt;/span&gt;osm-stats-namespace: httpbin
osm-stats-kind: Deployment
osm-stats-name: httpbin
osm-stats-pod: httpbin-54cc8cf5d-7vclc
connection: keep-alive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;FSM Ingress exposes the application access points within the Kubernetes cluster for easy management of portal traffic. osm-edge's IngressBackend API provides an additional line of defense against accidental data leakage by exposing services within the mesh to the public.&lt;/p&gt;

</description>
      <category>ingress</category>
      <category>servicemesh</category>
      <category>pipy</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Benchmarking osm and osm-edge data planes</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Sun, 07 Aug 2022 04:51:14 +0000</pubDate>
      <link>https://dev.to/flomesh/benchmarking-osm-and-osm-edge-data-planes-3c65</link>
      <guid>https://dev.to/flomesh/benchmarking-osm-and-osm-edge-data-planes-3c65</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/flomesh-io/osm-edge"&gt;osm-edge&lt;/a&gt; is built on top of &lt;a href="https://github.com/openservicemesh/osm/tree/release-v1.1"&gt;Open Service Mesh (OSM) v1.1.0&lt;/a&gt; codebase and is a lightweight service mesh for resource-sensitive cloud environments and edge computing scenarios. It uses osm as the control plane and &lt;a href="https://flomesh.io"&gt;Pipy&lt;/a&gt; as the data plane and features high performance, low resources, simplicity, ease of use, scalability, and compatibility (x86/arm64 support).&lt;/p&gt;

&lt;p&gt;osm-edge is a simple, complete, and standalone &lt;a href="https://en.wikipedia.org/wiki/Service_mesh"&gt;service mesh&lt;/a&gt; and ships out-of-the-box with all the necessary components to deploy a complete service mesh. As a lightweight and &lt;a href="https://smi-spec.io/"&gt;SMI&lt;/a&gt;-compatible Service Mesh, osm-edge is designed to be intuitive and scalable.&lt;/p&gt;

&lt;p&gt;For detailed introduction and documentation, refer to &lt;a href="https://osm-edge-docs.flomesh.io"&gt;osm-edge documentation&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;In this experiment, benchmarks were conducted for osm-edge(pipy) (v1.1.0) and osm(envoy) (v1.1.0). The main focus is on service TPS, latency distribution when using two different meshes, and monitoring the resource overhead of the data plane.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;osm-edge uses Pipy as the data plane; osm uses Envoy as the data plane.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Testing Environment
&lt;/h2&gt;

&lt;p&gt;The benchmark was performed in a Kubernetes cluster running on Cloud. Cluster comprised of 2 worker nodes and one load generator node. Software and hardware configurations as below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes: k3s v1.20.14+k3s2&lt;/li&gt;
&lt;li&gt;OS: Ubuntu 20.04&lt;/li&gt;
&lt;li&gt;Nodes: 16c32g * 2&lt;/li&gt;
&lt;li&gt;Load Generator: 8c16g&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What features were tested?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Both meshes had permissive traffic mode enabled&lt;/li&gt;
&lt;li&gt;Both meshes had mutual TLS enabled and were encrypting traffic and validating identity between all application pods.&lt;/li&gt;
&lt;li&gt;Both meshes were reporting metrics, including L7 metrics, though these metrics were not consumed in this experiment.&lt;/li&gt;
&lt;li&gt;Both meshes logged various messages at the INFO level by default. We did not configure logging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What application was used for testing?
&lt;/h3&gt;

&lt;p&gt;The test application uses the common SpringCloud microservices architecture. The application code is taken from &lt;a href="https://github.com/flomesh-io/flomesh-bookinfo-demo/"&gt;flomesh-bookinfo-demo&lt;/a&gt;, which is a SpringCloud implementation of bookinfo application using SpringCloud. In the tests, not all services were used, but rather the API gateway and the Bookinfo Ratings service were selected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iR7MhVlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178288704-3aa44151-4c57-4538-9a0a-55310bb4f200.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iR7MhVlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178288704-3aa44151-4c57-4538-9a0a-55310bb4f200.png" alt="applications" width="880" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;External access to the service is provided through Ingress; the load generator uses the common Apache Jmeter 5.5.&lt;/p&gt;

&lt;p&gt;For the tests, 2 paths were chosen: one is the direct access to the Bookinfo Ratings service via Ingress (hereafter ratings), and the other passes through the API Gateway (hereafter gateway-ratings) in the middle. The reason for choosing these two paths is to cover both single-sidecar and multiple-sidecar scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Procedure
&lt;/h2&gt;

&lt;p&gt;We start the test with a non-mesh (i.e., no sidecar injection, hereafter referred to as non-mesh), and then test with osm-edge(pipy) and osm(envoy) mesh, respectively.&lt;/p&gt;

&lt;p&gt;To simulate the resource-constrained scenario of the edge, the CPU used by the sidecar is limited when using the mesh, and the 1 core and 2 core scenarios are tested respectively.&lt;/p&gt;

&lt;p&gt;Thus, there are 5 rounds of testing, with 2 different tests in each round.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Jmeter uses 200 threads during the test and runs the test for 5 minutes. Each round of testing is preceded by a 2-minute warm-up.&lt;/p&gt;

&lt;p&gt;For sake of verbosity, only the results of the gateway-ratings paths are shown below with different sidecar resource constraints.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The sidecar in the table refers to the API Gateway sidecar&lt;/em&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;mesh&lt;/th&gt;
&lt;th&gt;sidecar max CPU&lt;/th&gt;
&lt;th&gt;TPS&lt;/th&gt;
&lt;th&gt;90th&lt;/th&gt;
&lt;th&gt;95th&lt;/th&gt;
&lt;th&gt;99th&lt;/th&gt;
&lt;th&gt;sidecar CPU usage&lt;/th&gt;
&lt;th&gt;sidecar memory usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;non-mesh&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;3283&lt;/td&gt;
&lt;td&gt;87&lt;/td&gt;
&lt;td&gt;89&lt;/td&gt;
&lt;td&gt;97&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;osm-edge(pipy)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3395&lt;/td&gt;
&lt;td&gt;77&lt;/td&gt;
&lt;td&gt;79&lt;/td&gt;
&lt;td&gt;84&lt;/td&gt;
&lt;td&gt;130%&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;osm(envoy)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2189&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;td&gt;200%&lt;/td&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;osm-edge(pipy)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2839&lt;/td&gt;
&lt;td&gt;76&lt;/td&gt;
&lt;td&gt;77&lt;/td&gt;
&lt;td&gt;79&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;osm(envoy)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1097&lt;/td&gt;
&lt;td&gt;201&lt;/td&gt;
&lt;td&gt;203&lt;/td&gt;
&lt;td&gt;285&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;105&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Sidecar with 2 CPU core limitations
&lt;/h3&gt;

&lt;p&gt;In the sidecar 2-core scenario, using the osm-edge(pipy) mesh gives a small TPS improvement over not using the mesh, and also improves latency. Improvement of TPS and latency is due the fact that Java NIO uses reactor pattern, while Pipy is built on C++ ASIO which uses the proactor pattern and the connection from Pipy to Java are long duplex connections. The sidecar for both API Gateway and Bookinfo Ratings is still not running out of 2 cores (only 65%), when the Bookinfo Ratings service itself is at its performance limit.&lt;/p&gt;

&lt;p&gt;The TPS of the osm(envoy) mesh was down nearly 30%, and the API Gateway sidecar CPU was running full, which was the bottleneck.&lt;/p&gt;

&lt;p&gt;In terms of memory, the memory usage of osm-edge(pipy) and osm(envoy) sidecar is 50 MiB and 105 MiB respectively, meaning osm-edge(pipy) was utilizing 52% less memory than osm(envoy).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TPS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--znxT7lq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294418-d3d63aef-8c54-49e4-a40e-8bacdec26f74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--znxT7lq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294418-d3d63aef-8c54-49e4-a40e-8bacdec26f74.png" alt="TPS" width="880" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency distribution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jGZq9Pno--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294471-b8e1b3c6-a8fd-47cb-872a-0c40418b0da7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jGZq9Pno--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294471-b8e1b3c6-a8fd-47cb-872a-0c40418b0da7.png" alt="Latency distribution" width="880" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API gateway sidecar CPU usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3VlO71Rn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294732-73aaa9f4-e159-4b8e-ab12-521985313358.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3VlO71Rn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294732-73aaa9f4-e159-4b8e-ab12-521985313358.png" alt="API gateway sidecar cpu usage" width="880" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API gateway sidecar memory footprint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uY0s485n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294829-9d2f0794-12e7-4cd6-827d-11af8b632db9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uY0s485n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178294829-9d2f0794-12e7-4cd6-827d-11af8b632db9.png" alt="API gateway sidecar memory footprint" width="880" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bookinfo Ratings sidecar CPU usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uZFqg4r_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178295086-6380004f-369d-4f6b-afeb-71b48c0e3053.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uZFqg4r_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178295086-6380004f-369d-4f6b-afeb-71b48c0e3053.png" alt="Bookinfo Ratings sidecar CPU usage" width="880" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bookinfo Ratings sidecar memory usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N2s4Z553--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178295267-004e7676-04b5-4fef-8e5d-ca196bd7dedc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N2s4Z553--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178295267-004e7676-04b5-4fef-8e5d-ca196bd7dedc.png" alt="Bookinfo Ratings sidecar memory usage" width="880" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sidecar with 1 CPU core limitation
&lt;/h3&gt;

&lt;p&gt;The difference is particularly noticeable in tests that limit the sidecar to 1 core CPU. At this point, the API Gateway sidecar becomes the performance bottleneck, with both the osm-edge and osm sidecar running out of CPU.&lt;/p&gt;

&lt;p&gt;In terms of TPS, osm-edge(Pipy) drops by 12% and osm(Envoy)'s TPS drops by a staggering 65%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TPS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8nC49CDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178295573-8be92413-d499-476e-b3e1-a23d0bcbcda3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8nC49CDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178295573-8be92413-d499-476e-b3e1-a23d0bcbcda3.png" alt="1 CPU TPS" width="880" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency distribution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y0Dj7VtV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178296728-c7ea9a12-d9d4-4be0-9c8d-32bb91724f36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y0Dj7VtV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178296728-c7ea9a12-d9d4-4be0-9c8d-32bb91724f36.png" alt="1c Latency distribution" width="880" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API gateway sidecar CPU usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--21a8TOOH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300176-0a76080b-3bcb-48f4-a506-4a105ad8c4a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--21a8TOOH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300176-0a76080b-3bcb-48f4-a506-4a105ad8c4a8.png" alt="1c API gateway sidecar CPU usage" width="880" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API gateway sidecar memory footprint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zkdihj_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300241-95917e41-5857-4a80-8234-ff6533310ef5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zkdihj_W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300241-95917e41-5857-4a80-8234-ff6533310ef5.png" alt="1c API gateway sidecar memory footprint" width="880" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bookinfo Ratings sidecar CPU usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eqVkarur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300596-2f767c75-6872-4aa5-b943-a3eeae84c55e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eqVkarur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300596-2f767c75-6872-4aa5-b943-a3eeae84c55e.png" alt="1c Bookinfo Ratings sidecar CPU usage" width="880" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bookinfo Ratings sidecar memory usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i8RWD5rl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300658-53bdf00d-6f2f-484a-8c3f-0399f9b683ed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i8RWD5rl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2224492/178300658-53bdf00d-6f2f-484a-8c3f-0399f9b683ed.png" alt="1c Bookinfo Ratings sidecar memory usage" width="880" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The focus of this experiment was to benchmark the performance and resource consumption of both meshes in a resource-constrained environment. Experiment results revealed that osm-edge maintained high performance and made efficient use of allocated resources. This experiment proves that complete service mesh functionalities can be used and utilized for resource-constrained edge scenarios.&lt;/p&gt;

&lt;p&gt;osm-edge is well-suited and ready for both cloud and resource-sensitive environments.&lt;/p&gt;

</description>
      <category>benchmark</category>
      <category>osm</category>
      <category>osmedge</category>
      <category>servicemesh</category>
    </item>
    <item>
      <title>Announcing osm-edge 1.1: ARM support and more</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Thu, 28 Jul 2022 13:19:04 +0000</pubDate>
      <link>https://dev.to/flomesh/announcing-osm-edge-11-arm-support-and-more-49j2</link>
      <guid>https://dev.to/flomesh/announcing-osm-edge-11-arm-support-and-more-49j2</guid>
      <description>&lt;p&gt;We're very happy to announce the release of &lt;a href="https://github.com/flomesh-io/osm-edge"&gt;osm-edge 1.1&lt;/a&gt;. This release is the culmination of months of effort from the &lt;a href="https://flomesh.io"&gt;flomesh.io&lt;/a&gt; team and we are very excited to unveil it today. osm-edge is built on top of &lt;a href="https://github.com/openservicemesh/osm/tree/release-v1.1"&gt;Open Service Mesh v1.1.0&lt;/a&gt; codebase and is built purposely for edge computing and uses lightweight, high-performant, cloud native, and programmable proxy &lt;a href="https://flomesh.io"&gt;Pipy&lt;/a&gt; as its data plane and sidecar proxy.&lt;/p&gt;

&lt;p&gt;osm-edge is a simple, complete, and standalone &lt;a href="https://en.wikipedia.org/wiki/Service_mesh"&gt;service mesh&lt;/a&gt; and ships out-of-the-box with all the necessary components to deploy a complete service mesh. As a lightweight and &lt;a href="https://smi-spec.io/"&gt;SMI&lt;/a&gt;-compatible Service Mesh, osm-edge is designed to be intuitive and scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why osm-edge?
&lt;/h2&gt;

&lt;p&gt;In practice, we have encountered users from a variety of industries with similar requirements for service mesh. These industry users and scenarios include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Energy and power companies. They want to build simple server rooms at each substation or gas station to deploy computing and storage capacity for the processing of data generated by devices within the coverage area of that location. They want to push traditional data center applications to these simple rooms and take full advantage of data center application management and operation capabilities&lt;/li&gt;
&lt;li&gt;Telematics service providers. They want to build their simple computing environments in non-data center environments for data collection and service delivery to cars and vehicle owners. These environments may be near highway locations, parking lots, or high-traffic areas&lt;/li&gt;
&lt;li&gt;Retailers. They want to build a minimal computing environment in each store, and in addition to supporting traditional capabilities such as inventory, sales, and payment collection, they also hope to introduce new capabilities of data collection, processing, and transmission&lt;/li&gt;
&lt;li&gt;Medical institutions. They want to provide network capabilities at every hospital, or a simple point of care, so that in addition to providing digital service capability for patients, they can also complete data collection and data linkage with higher management departments at the same time&lt;/li&gt;
&lt;li&gt;Teaching institutions, hospitals, and campuses alike. These campuses are characterized by a relatively regular and dense flow of people. They want to deploy computing resources near more crowd gathering points for delivering digital services, as well as collecting and processing data in real-time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are typical edge computing scenarios, and they have similar needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users want to bring the traditional data center computing model, especially microservices, and the related application delivery, management operation, and maintenance capabilities to the edge side&lt;/li&gt;
&lt;li&gt;In terms of the working environment, users have to deal with factors such as power supply, limited computing power, and unstable network. Therefore, computing platforms are required to be more robust and can be deployed quickly or recover a computing environment completely in extreme situations&lt;/li&gt;
&lt;li&gt;The number of locations (we call &lt;strong&gt;POP&lt;/strong&gt;=&lt;code&gt;Point of Presence&lt;/code&gt;) that usually need to be deployed is large and constantly evolving and expanding. The cost of a POP point, the price of maintenance, and the price of expansion are all important cost considerations.&lt;/li&gt;
&lt;li&gt;Common, or low-end, PC servers are more often used in these scenarios to replace cloud-standard servers; low-power technology-based computing power such as ARM is further replacing low-end PC servers. On these hardware platforms, which are not comparable to cloud-standard servers, users still want to have enough computing power to handle the growth in functionality and data volume. The conflicting demands of computing moving closer to where the data is generated, the growth in data volume and functional requirements at the edge, and the limited computing resources at the edge require edge-side computing platforms to have better computing power efficiency ratios, i.e., running more applications and supporting larger data volumes with as little power and as few servers as possible&lt;/li&gt;
&lt;li&gt;The fragility and a large number of POP points require better application support for multi-cluster, cross-POP failover. For example, if a POP point fails, the neighboring POP points can quickly share or even temporarily take over the computing tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compared with the cloud data center computing scenario, the three core and main differences and difficulties of edge computing are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edge computing requires support for heterogeneous hardware architectures. We see non-x86 computing power being widely used at the edge, often with the advantage of low power consumption and low cost&lt;/li&gt;
&lt;li&gt;Edge computing POP points are fragile. This fragility is reflected in the fact that they may not have an extremely reliable power supply, or the power supply is not as powerful as a data center; they may operate in a worse environment than the constant temperature and ventilation of a data center; their networks may be narrowband and unstable&lt;/li&gt;
&lt;li&gt;Edge computing is naturally distributed computing. In almost all edge computing scenarios, there are multiple POP points, and the number of POP points is continuously increasing. the POP points can disaster-proof each other and migrate to adjacent POP points in case of failure, which is a fundamental capability of edge computing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The evolution of Kubernetes to the edge side solves the difficulties of edge computing to a certain extent, especially against fragility; while the development of service mesh to the edge side focuses on network issues in edge computing, against network fragility, as well as providing basic network support for distributed, such as fault migration. In practice, container platforms, as today's de facto quasi-standard means of application delivery, are rapidly evolving to the edge side,  with a large number of releases targeting edge features, such as &lt;a href="https://k3s.io"&gt;k3s&lt;/a&gt;; but service mesh, as an important network extension for container platforms, are not quickly keeping up with this trend. It is currently difficult for users to find service mesh for edge computing scenarios, so we started the &lt;a href="https://github.com/flomesh-io/osm-edge"&gt;osm-edge&lt;/a&gt; an open source project with several important considerations and goals, namely&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support and compatibility with the SMI specification, so that it can meet users' needs for standardization of service mesh management&lt;/li&gt;
&lt;li&gt;Full support for the ARM ecosystem, which is the "first-class citizen" or even the preferred computing platform for edge computing, and the Service Mesh should be fully adapted to meet this trend. &lt;a href="https://github.com/flomesh-io/osm-edge"&gt;osm-edge&lt;/a&gt; follows the &lt;strong&gt;ARM First&lt;/strong&gt; strategy, which means that all features are developed, tested, and delivered on the ARM platform first&lt;/li&gt;
&lt;li&gt;High performance and low resources. The service mesh as infrastructure should use fewer resources (CPU/MEM) while delivering higher performance (TPS/Latency) at the edge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Light-weight, high-performant, cloud-native, extensible&lt;/li&gt;
&lt;li&gt;Out-of-the-box supports x86, ARM architectures&lt;/li&gt;
&lt;li&gt;Easily and transparently configure traffic shifting for deployments&lt;/li&gt;
&lt;li&gt;Secure service-to-service communication by enabling mutual TLS&lt;/li&gt;
&lt;li&gt;Define and execute fine-grained access control policies for services&lt;/li&gt;
&lt;li&gt;Observability and insights into application metrics for debugging and monitoring services&lt;/li&gt;
&lt;li&gt;Integrate with external certificate management services/solutions with a pluggable interface&lt;/li&gt;
&lt;li&gt;Onboard applications onto the mesh by enabling automatic sidecar injection of Pipy proxy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ARM Support
&lt;/h2&gt;

&lt;p&gt;osm-edge 1.1 brings the oft-requested support for ARM (both for development &amp;amp; production use), Whether you’re focused on cost reduction with ARM-based compute such as AWS Graviton or simply want to run service mesh on your Raspberry Pi cluster, now you can!&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-cluster Kubernetes the Kubernetes way
&lt;/h2&gt;

&lt;p&gt;osm-edge 1.1 comes bundled with &lt;a href="https://github.com/flomesh-io/fsm"&gt;Flomesh Service Mesh (FSM)&lt;/a&gt; a Kubernetes North-South traffic manager, provides Ingress controllers, Gateway API, Load Balancer, and cross-cluster service registration and service discovery.&lt;/p&gt;

&lt;p&gt;With the help of FSM, osm-edge can now connect Kubernetes services across cluster boundaries in a way that’s secure, fully transparent to the application, and independent of network topology. Automated fail-over ability to automatically redirect all traffic from a failing or inaccessible service to one or more replicas of that service—including replicas on other clusters. &lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple Sidecar Proxy support
&lt;/h2&gt;

&lt;p&gt;To break the tight coupling on Pipy and open doors for 3rd parties to develop or make use of their data plane or sidecar proxies, we have refactored the &lt;code&gt;OSM v1.1.0&lt;/code&gt; codebase to make it generic and provide extension points. We strongly believe in and support open source and our &lt;a href="https://github.com/openservicemesh/osm/issues/4874"&gt;proposal&lt;/a&gt; for this refactoring have been submitted to upstream for their review, discussion, and/or utilization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f1ZcRxqf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/95846930/175471277-30c65994-af30-4eef-ab15-f9ac1f9ace64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f1ZcRxqf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/95846930/175471277-30c65994-af30-4eef-ab15-f9ac1f9ace64.png" alt="multiple sidecar proxy support" width="880" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  And lot more
&lt;/h2&gt;

&lt;p&gt;osm-edge 1.1 also has a tremendous list of other improvements, performance enhancements, and bug fixes, for a detailed change log, please refer to the Release page on &lt;a href="https://github.com/flomesh-io/osm-edge/releases"&gt;Github&lt;/a&gt;. Below are some of the notable changes included in this release:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactoring of Proxy Control Plane component to stay generic and allow interaction with new sidecar proxy implementation&lt;/li&gt;
&lt;li&gt;Added new &lt;code&gt;driver.Driver&lt;/code&gt; interface that needs to be implemented by 3rd party vendors wishing to provide sidecar proxy for control plane&lt;/li&gt;
&lt;li&gt;Added new &lt;code&gt;driver.HealthProbes&lt;/code&gt;, &lt;code&gt;driver.HealthProbe&lt;/code&gt;, &lt;code&gt;driver.InjectorContext&lt;/code&gt;, &lt;code&gt;driver.controllerContext&lt;/code&gt; struct to use with new sidecar proxy driver implementation&lt;/li&gt;
&lt;li&gt;Refactored Envoy based proxy sidecar integration to a separate Driver, so that it works as an implementation of &lt;code&gt;driver.Driver&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;Added &lt;a href="https://github.com/flomesh-io/pipy"&gt;pipy&lt;/a&gt; implementation as a new Proxy Control Plane component proxy Driver&lt;/li&gt;
&lt;li&gt;Refactors Helm chart &lt;code&gt;values.yaml&lt;/code&gt; and added items &lt;code&gt;osm.sidecarClass&lt;/code&gt;, &lt;code&gt;osm.sidecarImage&lt;/code&gt;, &lt;code&gt;osm.sidecarWindowsImage&lt;/code&gt;, &lt;code&gt;osm.sidecarDrivers&lt;/code&gt; List to allow configuring the proxy sidecar driver.&lt;/li&gt;
&lt;li&gt;Pipy driver is the default driver of osm-edge distribution, but can be configured via cli flag &lt;code&gt;--set=osm.sidecarClass=XXX&lt;/code&gt; where &lt;code&gt;XXX&lt;/code&gt; refers to sidecar Driver.&lt;/li&gt;
&lt;li&gt;osm-edge control plane images are now multi-architecture, built for Linux/amd64 and Linux/arm64&lt;/li&gt;
&lt;li&gt;osm-edge test suite used images are now multi-architecture, built for Linux/amd64 and Linux/arm64&lt;/li&gt;
&lt;li&gt;Optimization of scripts&lt;/li&gt;
&lt;li&gt;Added Makefile targets for easier installation/setup&lt;/li&gt;
&lt;li&gt;Updated scripts to setup a development environment on amd64 and arm64 architectures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next and where to learn more?
&lt;/h2&gt;

&lt;p&gt;For more documentation, a quick-start guide, and step-by-step tutorials please visit &lt;a href="https://osm-edge-docs.flomesh.io/docs/getting_started/"&gt;osm-edge-docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;osm-edge is a fork of &lt;a href="https://github.com/openservicemesh/osm/tree/release-v1.1"&gt;open service mesh&lt;/a&gt; and we will strive to keep this fork in sync with its upstream and propose back major changes and/or feature proposals to upstream for broader benefits of the community. Both &lt;a href="https://github.com/openservicemesh/osm"&gt;OSM&lt;/a&gt; and &lt;a href="https://github.com/flomesh-io/osm-edge"&gt;osm-edge&lt;/a&gt; are hosted on Github. If you have any feature request, question, or comment, we’d love to have you join the rapidly-growing community via &lt;a href="https://github.com/flomesh-io/osm-edge/issues"&gt;Github Issues&lt;/a&gt;, &lt;a href="https://github.com/flomesh-io/osm-edge/pulls"&gt;Pull Requests&lt;/a&gt;, or &lt;a href="https://cloud-native.slack.com/archives/C018794NV1C"&gt;osm slack channel&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>osm</category>
      <category>servicemesh</category>
      <category>smi</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>MQTT policy enforcement with Pipy</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Fri, 17 Jun 2022 16:23:25 +0000</pubDate>
      <link>https://dev.to/flomesh/mqtt-policy-enforcement-with-pipy-24i6</link>
      <guid>https://dev.to/flomesh/mqtt-policy-enforcement-with-pipy-24i6</guid>
      <description>&lt;p&gt;If you play in the IoT space, you may have heard of the MQTT. &lt;a href="https://mqtt.org/" rel="noopener noreferrer"&gt;MQTT&lt;/a&gt; is an OASIS standard messaging protocol for the Internet of Things (IoT) that is becoming the defacto standard and is already in use in a wide variety of industries like automotive, manufacturing, telecommunications, oil, and gas.&lt;/p&gt;

&lt;p&gt;The Internet of Things (IoT) can be loosely defined as a system of sensors and other devices interacting with industry systems all to enhance business operations. Industries like manufacturing, automotive, telecommunication, and oil &amp;amp; gas to name just a few, deploy massive numbers of sensors. These sensors in turn send critical telemetry data to analytics engines, where the data is analyzed for trends and/or anomalies, enabling organizations to better understand and improve their operations.&lt;/p&gt;

&lt;p&gt;Although IoT contributes many novel applications to our daily life, one of its main concerns refers to IoT device security. Recent cyber-security incidents exposed the security pitfalls and vulnerabilities in IoT devices.&lt;/p&gt;

&lt;p&gt;The purpose of this tutorial is to demonstrate how to enforce custom policies on devices communicating via MQTT by using Pipy as a &lt;a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack" rel="noopener noreferrer"&gt;MITM&lt;/a&gt; that sits between MQTT Providers &amp;amp; Consumers and MQTT servers (previously known as brokers).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Pipy&lt;/a&gt; is an open-source, lightweight, high-performance, programmable network proxy for cloud, edge, and IoT. Pipy versatile nature allows it to be used in a variety of use-cases ranging from (but not limited to) edge routers, load balancers &amp;amp; proxy solutions, API gateways, static HTTP servers, service mesh sidecars, admission controllers, policy engines, and other applications.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pipy comes with built-in support for MQTT protocol versions 5.0 and 3.1.1 (aka version 4).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Having Pipy in the middle allows us to perform authentication, and authorization, applying rules like content validation, content replacement, allowing/denying consumers subscribing to particular topics, invoking business rules validations either inside Pipy or invoking already existing business domain services, etc. This list of policies and rules can be adapted or modified per your business case.&lt;/p&gt;

&lt;p&gt;For demonstration purposes and simplicity's sake, we will be defining some simple rules in JSON format and have them applied at Pipy proxy, working with a single MQTT server, which won't be dealing with TLS support. But for more complex rules and/or policies you can expand the rules, and policies and update the Pipy script or integrate them with your existing systems. Pipy comes with built-in support for load balancing, routing, TLS termination/offloading, and much more. For more details and step-by-step tutorials, please refer to &lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Pipy's Website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Demo code is accompanied by a Docker Compose file which configures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eclipse Mosquitto&lt;/strong&gt; as MQTT server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipy&lt;/strong&gt; proxy &lt;/li&gt;
&lt;li&gt;Expose MQTT port &lt;strong&gt;1883&lt;/strong&gt; and Pipy Admin GUI port &lt;strong&gt;6060&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sample policy and rules are defined in &lt;a href="https://github.com/flomesh-io/pipy-demos/blob/main/pipy-mqtt-policy-engine/pipy/config/policy.json" rel="noopener noreferrer"&gt;policy.json&lt;/a&gt; where we define 4 test accounts and some rules on which clients are allowed to subscribe/publish to which topics. Pipy proxy script will read this configuration file and enforce them before routing traffic to the upstream MQTT server. Refer to Publisher workflow and Subscriber workflow.&lt;/p&gt;

&lt;p&gt;Source code is made available and can be downloaded from Github repository &lt;a href="https://github.com/flomesh-io/pipy-demos/tree/main/pipy-mqtt-policy-engine" rel="noopener noreferrer"&gt;pipy-mqtt-policy-engine&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below diagrams details the architecture and flows between the various components:&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxovwv8d8iq8zamr7fkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxovwv8d8iq8zamr7fkv.png" alt="Architecture Overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Publisher workflow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya8h3rrorocjoz8l922s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya8h3rrorocjoz8l922s.jpg" alt="Publisher workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Subscriber workflow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0px4nk61pmkjvvymypwu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0px4nk61pmkjvvymypwu.jpg" alt="Subscriber workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Demo Project
&lt;/h2&gt;

&lt;p&gt;First, download the &lt;a href="https://github.com/flomesh-io/pipy-demos/tree/main/pipy-mqtt-policy-engine" rel="noopener noreferrer"&gt;tutorial code&lt;/a&gt; and initialize the components by calling Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/flomesh-io/pipy-demos.git
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;pipy-mqtt-policy-engine
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brings up a complete environment, including the Pipy, Eclipse Mosquitto MQTT server. Feel free to adjust the &lt;code&gt;docker-compose.yaml&lt;/code&gt; or &lt;code&gt;pipy/config/policy.json&lt;/code&gt; according to your specific needs.&lt;/p&gt;

&lt;p&gt;For viewing Pipy proxy scripts, statistics, and other demos you can open Pipy GUI admin console by pointing your browser to &lt;a href="http://localhost:6060" rel="noopener noreferrer"&gt;http://localhost:6060&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4of3lx1lgyp6q2q4o9g6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4of3lx1lgyp6q2q4o9g6.png" alt="Pipy Admin Panel GUI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;You can use the MQTT client of your choice which supports MQTT protocol version either 5.0 or 3.1.1 (aka 4). If you don't have any choice then you try an all-round MQTT client &lt;a href="http://mqtt-explorer.com/" rel="noopener noreferrer"&gt;MQTT Explorer&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This tutorial showed how you can leverage Pipy to enforce custom policies and rules without requiring any change in IoT devices and MQTT server.&lt;/p&gt;

&lt;p&gt;Pipy from &lt;a href="https://flomesh.io/" rel="noopener noreferrer"&gt;Flomesh&lt;/a&gt; is an open-source, extremely fast, and lightweight network traffic processor which can be used in a variety of use cases ranging from edge routers, load balancing &amp;amp; proxying (forward/reverse), API gateways, Static HTTP Servers, Service mesh sidecars, , admission controller, policy engine and other applications. Pipy is in active development and maintained by full-time committers and contributors, though still an early version, it has been battle-tested and in production use by several commercial clients.&lt;/p&gt;

</description>
      <category>mqtt</category>
      <category>programming</category>
      <category>security</category>
      <category>policy</category>
    </item>
    <item>
      <title>What &amp; Why of programmable proxy</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Tue, 12 Apr 2022 15:42:57 +0000</pubDate>
      <link>https://dev.to/flomesh/what-why-of-programmable-proxy-joc</link>
      <guid>https://dev.to/flomesh/what-why-of-programmable-proxy-joc</guid>
      <description>&lt;p&gt;Question which gets asked too often is &lt;em&gt;"When you say programmable proxy, what is a programmable proxy, and why do you need a programmable proxy?"&lt;/em&gt;. This article tries to answer this question from different perspective. We will start with brief definition of what is a proxy? then move forward our discussion of evolution, proxy went through its development process, explaining the need for those stages and what benefits each stage provide and why such stage improvements were required. In end we will discuss several aspects of &lt;em&gt;"programmability"&lt;/em&gt; and provide a summary of "why we need programmable proxy".&lt;/p&gt;

&lt;p&gt;A proxy server is usually deployed in the middle of two isolated networks where it has access to both sides of the network and transfers data from one side to the other to achieve network connectivity. Proxy is a kind of serial network device, which has existed since the birth of computer networks. Proxy acts not only as a network connector, but it also opens a path to new functionality and usage scenarios like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routing. The proxy forwards data to different destinations according to the characteristics of the data defined.&lt;/li&gt;
&lt;li&gt;Load balancing. During forwarding, data is distributed to different destinations to improve throughput and avoid destination single point of failure. Load balancing is becoming an area of proxy segmentation functionality&lt;/li&gt;
&lt;li&gt;Fail over. In the forwarding process, when the destination fails, the proxy can forward the data to an alternate destination, providing uninterrupted service to the requester&lt;/li&gt;
&lt;li&gt;Access control. Proxy can decide what traffic is allowed through and what needs to be blocked. Web Application Firewall (WAF) is a typical proxy application example&lt;/li&gt;
&lt;li&gt;Identity management. Access control is often based on identity information, so proxies often have identity management capabilities as well&lt;/li&gt;
&lt;li&gt;Network acceleration. proxy accelerates network access by caching data&lt;/li&gt;
&lt;li&gt;Metrics collection. Proxy captures data statistics and summarizes it to NPM software for network optimization and network planning&lt;/li&gt;
&lt;li&gt;Information security. In addition to access control, proxies can also be used for security auditing, TLS/SSL offloading, and data encryption to meet security requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to proxying, routers provide the functionality of bridging two networks. Routers work at layer 3 of the network while Proxies work at layers above 3, like  layer 4 and layer 7.&lt;/p&gt;

&lt;p&gt;Proxy servers have gone through following evolutions during its development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configurations file era. Proxy software (mostly open source software), which makes up the majority of network infrastructure software, provides different functions in different domains, such as proxy for different protocols, proxy for load balancing, proxy for cache acceleration. This generation of proxy is all configuration based. User sets parameters, configures rules in the configuration file, and then starts the service process to execute the rules&lt;/li&gt;
&lt;li&gt;Configuration DSL. Static configuration files are difficult to express complex logic, so many proxies introduced thin scripting capabilities on top of configuration, commonly referred to as &lt;em&gt;"configuration languages"&lt;/em&gt; or Domain specific languages (DSL for short), such as Haprxoy's ACL or Varnish's VCL&lt;/li&gt;
&lt;li&gt;Scripting language era. As the logic becomes more complex, it becomes more difficult to express that via configuration languages; At the same time, when the number of configuration languages reaches a certain extent, the management of configuration languages itself becomes difficult. Shell scripts, for example, one can write simple logic, but when the shell code reaches a certain level, it is often a step toward more structured scripting languages like Perl or Python. Proxy supports scripting language, which has both the convenience of scripting language and the structural advantage of programming language. Examples of this are OpenResty (Nginx + Lua) and Nginx Plus(Nginx + NJS). These examples also include proxy servers implemented by a number of application programming languages, such as Node.js based StrongLoop and Spring Gateway, which often have scripting capabilities of their own&lt;/li&gt;
&lt;li&gt;Cluster age. Script language solves the difficulties in modularization and structuring of complex logic in proxy server. A further requirement at this point is to integrate proxies with other administrative control tools, hence the need for a REST or alike interface. The external control plane can dynamically update the logic in the script through the REST or alike interface. At the same time, the use of proxies has moved from single instances to cluster of proxies, so proxy software like Envoy and OpenResty based Kong often support clustering capabilities themselves, implementing clustering capabilities in some centralized or shared way, while providing REST interfaces. For proxies of type #4 mentioned above, cluster management is generally possible through configuration management; Configuration management tools can also expose REST interfaces. For example, the Ansible + Nginx solution implements similar capabilities to #5. In contrast, scheme #4 requires more components to form the scheme, while scheme #5 is more convergent&lt;/li&gt;
&lt;li&gt;Cloud era. In this era, proxies are deployed in a distributed manner. The most common scenario is to deploy one proxy for each application process e.g Sidecar Proxy pattern. Adoption of distributed proxies, opened the doors for using different rules and policies for different upstream services, that is, multi-tenant capability. The various upstream services not only have logically independent rules and policies; Physical isolation is also  provided, allowing granular management at the process and interface level. If we consider the control plane and data plane of the service mesh as a whole, then the service mesh is representative of this domain, typical examples are Istio+Envoy, Linkerd + Linkerd proxy. &lt;a href="https://flomesh.io"&gt;Pipy&lt;/a&gt; is a product of this age and falls under this category.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the above evolution stages, each stage is an improvement over the previous one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;#2 adds basic scripting capabilities over #1. This basic scripting capability is augmented by dynamic capabilities on top of configuration files. For example, get the characteristics of the request at run time (such as HTTP headers), and then make dynamic logical decisions based on those characteristics to perform specific actions&lt;/li&gt;
&lt;li&gt;#3 adds full scripting capabilities over #2, allowing scripting logic to be structured and modular. In the #2 stage, when logic becomes complex, the volume of scripts increases dramatically, and structured scripting capabilities become a necessity&lt;/li&gt;
&lt;li&gt;#4 has more REST interfaces and clustering capabilities than #3. To horizontally expand the proxy capacity, you need to cluster multiple proxy instances. Instances in the cluster share configurations and scripts, and users can manage configurations and scripts through the REST interfaces&lt;/li&gt;
&lt;li&gt;#5 has more distributed capabilities than #4, mainly because different instances within the same cluster run different scripts and configurations. In #4 mode, there are usually different configurations and policies for different upstream services, such as different authentication modes and access control mechanisms. As upstream services grow, the configurations of these different upstream services are logically separated but physically run in the same proxy process. This logically separated configuration and policy scripts running in the same physical process has some disadvantages: the more logic running in one process brings the more complexity; different upstream services share resources such as CPU and memory, affecting each other. If a script of an upstream service has a security vulnerability, the configurations of other upstream services may be leaked, resulting in security risks. #5 stage is an improvement over the #4 in that the proxy processes for each upstream service are independent and isolated from each other. They are managed by the same cluster manager, but the configuration and scripts at work are separated and isolated. This isolation is a strong requirement in a multi-tenant environment -- different upstream services belong to different tenants, and tenants should not affect each other or know each other's configurations. #5 can be thought of as the extreme mode of "#4 multi-clustering "-- at its most extreme, each process has its own configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets take another look at the evolution of proxies -- &lt;em&gt;The Evolution of Requirements&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first generation of proxies mainly implemented proxy functionality and provided basic configurable capabilities. At that time, network equipment, especially Serial network equipment, required proxy to be highly reliable; The real-time transmission of massive data requires high throughput, low latency and low resources. Like all software, proxy also required to support modularity and extensibility. Proxy in this stage was mainly developed in C language, and the corresponding development of extension modules were also developed in C language. Extension modules get loaded dynamically at the start of the process. To summarize, proxy requirements at this stage are: &lt;strong&gt;connectivity&lt;/strong&gt; (network capabilities), &lt;strong&gt;ease of use&lt;/strong&gt; (configurable via configuration files), &lt;strong&gt;reliability&lt;/strong&gt; (requirements for cross-linking devices), &lt;strong&gt;high performance&lt;/strong&gt;, &lt;strong&gt;scalability&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The second generation of proxies got further improvements in extensibility and flexibility, such as some dynamic data acquisition and making logical judgment. The introduction of scripts further enhanced the &lt;strong&gt;ease of use&lt;/strong&gt;. Support for combinatorial logic and dynamic data retrieval provided &lt;strong&gt;flexibility&lt;/strong&gt; while improving &lt;strong&gt;scalability&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The main improvements of the 3rd generation proxies over the 2nd generation proxies are &lt;strong&gt;manageability&lt;/strong&gt;, &lt;strong&gt;developer friendliness&lt;/strong&gt; and &lt;strong&gt;programmability&lt;/strong&gt;. Scripting capabilities are widely used, mainly because it is difficult to develop and maintain extensions using C language, while scripting languages are easier to learn and provide fast turnarounds in developments when compared to compiled languages counterparts. Developers' development efficiency and the difficulty of massive script maintenance require this generation of proxies to use a more structured scripting language, and to maintain performance, resource utilization and other core capabilities of the previous generation. The use of structured and modular scripting language, opened the era of &lt;strong&gt;programmable&lt;/strong&gt; proxies and required proxies to provide two level of possibilities, one is to use C language for development of &lt;em&gt;core modules&lt;/em&gt;, and scripts to be used to program &lt;em&gt;dynamic logic&lt;/em&gt;; In other words &lt;strong&gt;programmable&lt;/strong&gt; includes the meaning of giving its user the power of development of &lt;em&gt;core modules&lt;/em&gt; and &lt;em&gt;dynamic logic&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The fourth generation of proxies starts with cluster support capabilities, which are improvements to &lt;strong&gt;manageability&lt;/strong&gt;. With the support of REST interfaces, proxies become part of network infrastructure implementation, and a landing place for &lt;em&gt;infra as code&lt;/em&gt;. REST interface capabilities improved proxies &lt;strong&gt;ability to be managed&lt;/strong&gt; and considered a part of the ease of administration. &lt;em&gt;External interfaces&lt;/em&gt; are also an important feature of &lt;strong&gt;programmable&lt;/strong&gt;, and REST, as the most common form of interface, is also widely used in the proxy server world. At this point, &lt;strong&gt;programmable&lt;/strong&gt; consists of three layers: programmable &lt;em&gt;core modules&lt;/em&gt; as described in #3, programmable &lt;em&gt;dynamic logic&lt;/em&gt; , and programmable &lt;em&gt;external interfaces&lt;/em&gt;. The emergence of proxy server cluster reflects the change of &lt;strong&gt;scalability&lt;/strong&gt; from &lt;em&gt;function expansion&lt;/em&gt; to &lt;em&gt;resource expansion&lt;/em&gt;. The emergence of REST interfaces provides the technical foundation for further &lt;strong&gt;self-service&lt;/strong&gt; and &lt;strong&gt;managed services&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The evolution of the fifth generation of proxy is driven by the popularity and rapid development of cloud computing. The elasticity, self-service, tenant, isolation, and metering of the cloud require that the proxy service software have the best capability of the &lt;strong&gt;cloud native&lt;/strong&gt;. If the fourth generation of agents is for &lt;em&gt;system administrators&lt;/em&gt;, the fifth generation of agents is for &lt;em&gt;cloud services&lt;/em&gt;. While fully maintaining the characteristics of previous generations of proxy software, &lt;strong&gt;Cloud Ready&lt;/strong&gt; is further incorporated. With the expansion of cloud computing to the edge, the fifth generation of proxies are also toward the development of heterogeneous hardware, heterogeneous software, low energy consumption, so this generation of proxies began to show the ability to optimize the integration of &lt;strong&gt;cloud and edge&lt;/strong&gt;. The fifth generation of proxies in the &lt;strong&gt;programmable&lt;/strong&gt; further evolution, from the &lt;em&gt;core module&lt;/em&gt;, &lt;em&gt;dynamic logic&lt;/em&gt;, &lt;em&gt;external interface&lt;/em&gt;, increased &lt;em&gt;cloud&lt;/em&gt; ability; Supports distributed, multi-tenant, and metering. Metering is a derivative requirement of multi-tenancy, which requires isolation on the one hand, and resources that can be measured at the smallest possible granularity on the other&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's summarize the above discussion into a tabular format, with the first column identifying a specific requirement that the proxy meets; Header row represents proxies at different stages, with the typical examples or known software in parentheses. In each cell, we use &lt;strong&gt;*&lt;/strong&gt; to indicate whether such capabilities are available and to what extent (1-5 *, 5 * for full support, and 1 * for basic support).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SN&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Configuration (squid, httpd, nginx)&lt;/th&gt;
&lt;th&gt;Configuration Language (varnish, haproxy)&lt;/th&gt;
&lt;th&gt;Scripting support (nginx+lua, nginx+js)&lt;/th&gt;
&lt;th&gt;Clustering (kong, envoy)&lt;/th&gt;
&lt;th&gt;Cloud (istio+envoy, linkerd, pipy)&lt;/th&gt;
&lt;th&gt;Remarks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1.&lt;/td&gt;
&lt;td&gt;Connectivity&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;Connectivity in the cloud era began using kernel technologies such as iptables and ebpf; Previously, there was only user Space process mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.&lt;/td&gt;
&lt;td&gt;reliability&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;Reliability has always been the most important fundamental capability of proxy server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.&lt;/td&gt;
&lt;td&gt;high performance&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;Performance includes throughput, latency, error rate, and deviation from the mean. Latency metrics P99, P999 and other. Early proxy software has a long tail effect, so the indicators above P99 are not as good as later software. Proxy with high-performance scripts often perform better than their predecessors when returning the same content. Agents using proactive technology are more stable (with less deviation from the mean) while providing the same performance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4.&lt;/td&gt;
&lt;td&gt;flexibility&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;Compared with the fourth generation, the fifth-generation proxies significantly enhances the multi-protocol support capability, so we give this generation a five-star evaluation. Moreover, the processing model of the fifth generation can adapt to various protocols and has universality, which is better than that of the fourth generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.&lt;/td&gt;
&lt;td&gt;scalability&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;Similar to &lt;em&gt;Flexibility&lt;/em&gt;, the 5th generation proxies supports multiple protocols in addition to core function extension development, 7-layer logic extension development, so we give it one star more than the 4th generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.&lt;/td&gt;
&lt;td&gt;hardware compatibility&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;Proxies developed in C or C++ generally have better hardware compatibility and a more active community to migrate applications to new hardware architectures. Proxies developed using Rust, Go, and Lua have been relatively slow to migrate for hardware compatibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.&lt;/td&gt;
&lt;td&gt;system compatibility&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;system&lt;/em&gt; mainly includes two aspects, one is the operating system, the other is the cloud platform. In terms of operating system compatibility, each generation of proxies is similar; However, in terms of cloud platform compatibility, both the fourth and fifth generation proxies have more fully considered and realized cloud compatibility. In contrast, the significant difference between the fifth generation and the fourth generation is the ability to support multi-tenant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.&lt;/td&gt;
&lt;td&gt;ease of management&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;ease of management is a function of the system operations &amp;amp; administrator roles. The first and second generations mainly use configuration files, based on which the use of configuration management tools to achieve automatic and batch management. In the third generation, in addition to managing configuration files, we need to further manage source files. But in essence, there is no significant difference from the first and second generation of ease of management. The fourth generation provides REST interfaces, which greatly improves the ease of management. In addition to REST, the fifth generation usually provides a control plane for the cloud to manage proxies; It also provides multiple external interfaces to meet other management requirements, such as monitoring, auditing, and statistics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.&lt;/td&gt;
&lt;td&gt;ease of use&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;The primary users of the first three generations of proxies are ops &amp;amp; sys administrators. In the fourth generation, administrators began to provide some functions to users, and the as-a-service mode began to appear. The fifth generation takes into account more user scenarios and provides more rent-oriented capabilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.&lt;/td&gt;
&lt;td&gt;ease of development&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;The development around the proxies includes two aspects, one is inside the proxy to achieve the functionality, another is outside the proxy to achieve the management ability of the proxy. The first three generations provide an interface for internal development; The latter two generations provide both internal and external interfaces. The significant improvement of the fifth generation compared with the fourth generation is the cloud interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11.&lt;/td&gt;
&lt;td&gt;core interface is programmable&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Each generation of proxies provides the ability to extend core interfaces, but these interfaces are too low-level and difficult to master&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12.&lt;/td&gt;
&lt;td&gt;functionality extension is programmable&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;Providing the ability to extend functions more efficiently is part of the process that gets better with each generation of proxies. It is the core metric of programmable proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13.&lt;/td&gt;
&lt;td&gt;protocol extensions are programmable&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;The first three generations are mainly for single agreements, or fixed agreements. Starting with the fourth generation, users began to seek support for multiple protocols and custom protocols. In the fifth generation, protocol extension is considered as a core capability in the design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14.&lt;/td&gt;
&lt;td&gt;modular scripting&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;Third generation proxies are beginning to pay more attention to script structuring; The fourth and fifth generations attempt to prepare for more structured programming, such as Envoy's attempt to provide multilingual support through WASM; Pipy introduces high-performance JS scripts for better structuring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15.&lt;/td&gt;
&lt;td&gt;configuration management is programmable&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;The first three generations of proxy configuration are mainly for ops management personnel, and external configuration management tools are based on this premise. The fourth generation supports REST management interfaces. The fifth generation further provides a standard cloud interface for configuration management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16.&lt;/td&gt;
&lt;td&gt;resource extensions are programmable&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;* *&lt;/td&gt;
&lt;td&gt;* * * *&lt;/td&gt;
&lt;td&gt;In the first three generations, proxy capacity expansion is mainly to increase the number of threads or processes. The fourth generation provides scale-out capability for processes, known as clustering capability. On the basis of the fourth generation, the fifth generation on the one hand provides horizontal expansion capabilities, on the other hand provides capabilities under smaller resources to support more fine-grained metering and billing; That is, it not only supports incremental scaling, but also provides the ability to reduce scaling, and all of these capabilities provide programming interfaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17.&lt;/td&gt;
&lt;td&gt;tenant extension programmable&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;* * *&lt;/td&gt;
&lt;td&gt;The cloud is something that has emerged at the same time as the fourth generation of proxy, and &lt;em&gt;tenant&lt;/em&gt;, as a core feature of the cloud, is not well supported in the fourth generation. The fifth generation is designed on the premise of cloud, considering and providing tenants with the possibility of programming their own extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;rows #11 to #17 in the table above are the specific aspects of &lt;strong&gt;Programmable Proxy&lt;/strong&gt;. These aspects also constitute the answer to the question of &lt;strong&gt;Why Programmable Proxy&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The internal functions of the proxy need to be expanded, including the extension of the underlying core capabilities, the extension of supporting more protocols, and Layer7 processing capabilities (forwarding, routing, judgment, access control, etc.); These Layer7 processing power require a more convenient way of programming, that is, scripting and structured programming ability&lt;/li&gt;
&lt;li&gt;Proxies need to provide interfaces externally to integrate into larger management systems (such as cloud platforms), including configuration management, resource management, and so on&lt;/li&gt;
&lt;li&gt;Proxies need to provide extensible capabilities for different roles, including operations, administrators, resource providers, and tenants, all of which require the capability of &lt;strong&gt;Programmable&lt;/strong&gt; to some extent&lt;/li&gt;
&lt;li&gt;Also, like any &lt;strong&gt;programmable&lt;/strong&gt; component, &lt;strong&gt;Programmable Proxy&lt;/strong&gt; requires accompanying documentation, development manuals, code management, dependency management, build and deployment tools, and preferably a visual development and debugging environment. Only when these requirements are fully met can users better manage network traffic and the services carried on the traffic&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>javascript</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Pipy + Redis + Sentinel = High available Redis</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Mon, 04 Apr 2022 13:04:02 +0000</pubDate>
      <link>https://dev.to/flomesh/pipy-redis-sentinel-high-available-redis-2p18</link>
      <guid>https://dev.to/flomesh/pipy-redis-sentinel-high-available-redis-2p18</guid>
      <description>&lt;p&gt;&lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Pipy&lt;/a&gt; is an open source programmable proxy for cloud, edge, and IoT. Pipy versatile nature allow it be used in multiple use cases. The main purpose of this article is to demonstrate the implementation of Pipy as TCP load balancer in front of a Redis master and slave (agent) replication to ensure that client and application connections are always entertained.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our goals
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We want to implement and achieve &lt;strong&gt;automatic failover capability&lt;/strong&gt; in cases when designated Redis master node stop responding because of process termination, hardware failure, network hiccups or some uknown reasons, and Sentinel automatically fails over the master to one of the remaining agent nodes.&lt;/li&gt;
&lt;li&gt;We want clients and application connecting to Redis are not impacted by failover mechanism.&lt;/li&gt;
&lt;li&gt;We want whole failover mechanism to be fully transparent without requiring any change in client and applications configuration/settings.&lt;/li&gt;
&lt;li&gt;We want all write (Redis SET or other user configured commands) requests are handled by master node without client and application knowing the topology in place.&lt;/li&gt;
&lt;li&gt;We want all our requests are distributed equally to available nodes for making better use of allocated resources and high throuput.&lt;/li&gt;
&lt;li&gt;....&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Load balancing, proxying TCP connections, ensuring SET (or other user configured) redis commands are always routed to master node, health probing, logging to console, recording metrics etc is achieved by Pipy.&lt;/p&gt;

&lt;p&gt;High availability for Redis deployment including master and agent implementation is achieved by implementing Redis Sentinel, which continuously performs monitoring, notification, and automatic failover if a master becomes unresponsive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick introduction to technologies used
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Pipy&lt;/a&gt; is an open source programmable proxy for cloud, edge, and IoT.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt; is an open source, in-memory data store, benchmarked as the world’s fastest. Redis powers cutting edge applications and is known to enhance use cases such as real-time analytics, fast high-volume transactions, in-app social functionality, application job management, queuing and caching.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://redis.io/docs/manual/sentinel/" rel="noopener noreferrer"&gt;Redis Sentinel&lt;/a&gt; provides high availability for Redis when not using Redis Cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo high-level deployment architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2ydi02011qmb9gddlhl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2ydi02011qmb9gddlhl.png" alt="high-level deployment architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One Pipy proxy server to act as a TCP load balancer and keeping track of which Redis servers are available and ready to serve requests.&lt;/li&gt;
&lt;li&gt;Three Redis servers provide the master-agent replication.&lt;/li&gt;
&lt;li&gt;Three Sentinel instances for a robust deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;For demonstration purposes, demo code comes with Docker Compose script to spin up containers.&lt;/p&gt;

&lt;p&gt;Full source of demo is available and can be downloaded from &lt;a href="https://github.com/flomesh-io/pipy-demos/tree/main/pipy-redis-sentinel" rel="noopener noreferrer"&gt;https://github.com/flomesh-io/pipy-demos/tree/main/pipy-redis-sentinel&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/install" rel="noopener noreferrer"&gt;docker-compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://redis.io/topics/rediscli" rel="noopener noreferrer"&gt;redis-cli&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Clone &lt;a href="https://github.com/flomesh-io/pipy-demos.git" rel="noopener noreferrer"&gt;Pipy Demos Repo&lt;/a&gt; or download demo code from &lt;a href="https://github.com/flomesh-io/pipy-demos/tree/main/pipy-redis-sentinel" rel="noopener noreferrer"&gt;pipy-redis-sentinel&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Spin up Pipy proxy, Redis, Sentinel containers&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Make sure all containers are up and running:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps

CONTAINER ID   IMAGE                       COMMAND                  CREATED         STATUS         PORTS                                                 NAMES
0db7eba4f91d   sentinel                    &lt;span class="s2"&gt;"sentinel-entrypoint…"&lt;/span&gt;   6 seconds ago   Up 6 seconds   6379/tcp, 26379/tcp                                   redis_sentinel_3
e4a7b6b99074   sentinel                    &lt;span class="s2"&gt;"sentinel-entrypoint…"&lt;/span&gt;   6 seconds ago   Up 6 seconds   6379/tcp, 26379/tcp                                   redis_sentinel_2
4ec87846b1e3   naqvis/pipy-pjs:0.22.0-31   &lt;span class="s2"&gt;"/docker-entrypoint.…"&lt;/span&gt;   6 seconds ago   Up 5 seconds   6000/tcp, 0.0.0.0:6379-&amp;gt;6379/tcp, :::6379-&amp;gt;6379/tcp   pipy-proxy
8e81ddc5eb07   sentinel                    &lt;span class="s2"&gt;"sentinel-entrypoint…"&lt;/span&gt;   6 seconds ago   Up 4 seconds   6379/tcp, 26379/tcp                                   redis_sentinel_1
f1a533de6d41   redis:alpine                &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   8 seconds ago   Up 6 seconds   6379/tcp                                              redis-slave2
a522c208b236   redis:alpine                &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   8 seconds ago   Up 7 seconds   6379/tcp                                              redis-slave1
8065dec93c3d   redis:alpine                &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   8 seconds ago   Up 7 seconds   6379/tcp                                              redis-master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pipy is listening on TCP port &lt;strong&gt;6379&lt;/strong&gt; on the docker host which is the standard Redis port and load balance across the 3 Redis containers (one Master &amp;amp; two Slave). Three Redis Sentinel contaners for a robust deployment and providing high availability for Redis.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check that Pipy service is routing traffic to all Redis nodes by executing below commands. You don't need to provide docker host IP and port information, as Pipy is exposing Redis default port of 6379.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli info replication | &lt;span class="nb"&gt;grep &lt;/span&gt;role
role:master
&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli info replication | &lt;span class="nb"&gt;grep &lt;/span&gt;role
role:slave
&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli info replication | &lt;span class="nb"&gt;grep &lt;/span&gt;role
role:slave
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pipy comes with load balancing algorithms and demo script is configured to use &lt;a href="https://flomesh.io/docs/en/reference/api/algo/RoundRobinLoadBalancer" rel="noopener noreferrer"&gt;RoundRobinLoadBalancer&lt;/a&gt; and you can see from above output that Pipy is sending requests to all configured Redis nodes in roundrobin fashion.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Now try some more Redis commands
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli &lt;span class="nb"&gt;set &lt;/span&gt;hello world
OK

&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli get hello
&lt;span class="s2"&gt;"world"&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli &lt;span class="nb"&gt;set &lt;/span&gt;foo bar
OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have configured proxy to use roundrobin algorithms, but we have seen that all &lt;code&gt;SET&lt;/code&gt; requests are executed successfully. If we have simply followed the roundrobin algorithm to forward requests equally to each nodes, then our &lt;code&gt;SET&lt;/code&gt; requests reaching out to slave nodes would have failed with error like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(error) READONLY You can't write against a read only slave.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Failover Testing
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Let's &lt;strong&gt;pause&lt;/strong&gt; &lt;code&gt;redis-master&lt;/code&gt; container to test automatic failover
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker pause redis-master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sentinel will automatically detect that the master is missing, and it will choose a slave to promote that as &lt;strong&gt;master&lt;/strong&gt;. Pipy during health-checks will detect that master node is down, it will mark that as unhealthy and will no longer send requests to that node until node become accessible again. Pipy will detect new master node and will forward all &lt;code&gt;SET&lt;/code&gt; commands to newly promoted &lt;code&gt;master node&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run again some Redis commands to see if can access Redis without any problems.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli &lt;span class="nb"&gt;set &lt;/span&gt;abc 1234
OK

&lt;span class="nv"&gt;$ &lt;/span&gt;redis-cli get abc
&lt;span class="s2"&gt;"1234"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Bring back pause container, and Sentinel will mark that as slave node
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker unpause redis-master

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, You should now have everything You need to setup a fault tolerant and high available Redis when not using &lt;a href="https://redis.io/docs/manual/scaling" rel="noopener noreferrer"&gt;Redis Cluster&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance test
&lt;/h2&gt;

&lt;p&gt;We performed  various testes with pipy, haproxy, twemproxy, and single redis instance to find out the drop in through by applying proxy before redis. &lt;br&gt;
following are the test result performed on our VM with 4C8G with OS 20.04.4 LTS (Focal Fossa) ARM64 running on our Mac M1 Max.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay3bhsz28du9jp9hh868.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay3bhsz28du9jp9hh868.png" alt="Benchmark"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is clear that adding any proxy before Redis is going to cause performance penalty, but that's the cost which one had to pay to achieve the benefits proxy brings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You can achieve Redis high availability and maximum protection against any failure and disaster for Redis replication by combining the infrastructure services with the software configuration. With propery infrastructure setup and design, we can achieve high availability for Redis replication between master and slave by using different availability zones. Redis Sentinel monitors and performs the failover of Redis replication from master to slave. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://flomesh.io" rel="noopener noreferrer"&gt;Pipy&lt;/a&gt; is an &lt;a href="https://github.com/flomesh-io/pipy" rel="noopener noreferrer"&gt;open-source&lt;/a&gt;, extremely fast, and lightweight network traffic processor which can be used in a variety of use cases ranging from edge routers, load balancing &amp;amp; proxying (forward/reverse), API gateways, Static HTTP Servers, Service mesh sidecars, and many other applications. Pipy is in active development and maintained by full-time committers and contributors, though still an early version, it has been battle-tested and in production use by several commercial clients.&lt;/p&gt;

</description>
      <category>pipy</category>
      <category>redis</category>
      <category>sentinel</category>
      <category>highavailability</category>
    </item>
    <item>
      <title>Pipy proxy helps improve SpringBoot REST Service QPS &amp; Latency</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Wed, 30 Mar 2022 12:25:06 +0000</pubDate>
      <link>https://dev.to/flomesh/pipy-proxy-helps-improve-springboot-rest-service-qps-latency-3o48</link>
      <guid>https://dev.to/flomesh/pipy-proxy-helps-improve-springboot-rest-service-qps-latency-3o48</guid>
      <description>&lt;p&gt;Spring and SpringBoot development platforms are one of the most popular development platform among Java developers. &lt;/p&gt;

&lt;p&gt;We performed a simple benchmark of SpringBoot starter application running with default configurations with and without a sidecar &lt;a href="https://flomesh.io"&gt;Pipy&lt;/a&gt; proxy and measured &lt;strong&gt;QPS&lt;/strong&gt; and &lt;strong&gt;Latency&lt;/strong&gt; indicators. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Our results shows that deploying &lt;a href="https://flomesh.io"&gt;&lt;strong&gt;Pipy proxy&lt;/strong&gt;&lt;/a&gt; as sidecar &lt;strong&gt;improved QPS and reduced latency by almost 10%&lt;/strong&gt; in our testing environment&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Test Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;QPS&lt;/th&gt;
&lt;th&gt;Latency P50&lt;/th&gt;
&lt;th&gt;P90&lt;/th&gt;
&lt;th&gt;P99&lt;/th&gt;
&lt;th&gt;P99.9&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;ubuntu&lt;/td&gt;
&lt;td&gt;ab&lt;/td&gt;
&lt;td&gt;springboot&lt;/td&gt;
&lt;td&gt;46102&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ubuntu&lt;/td&gt;
&lt;td&gt;ab&lt;/td&gt;
&lt;td&gt;pipy--&amp;gt;springboot&lt;/td&gt;
&lt;td&gt;50303&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ubuntu&lt;/td&gt;
&lt;td&gt;wrk&lt;/td&gt;
&lt;td&gt;springboot&lt;/td&gt;
&lt;td&gt;71840&lt;/td&gt;
&lt;td&gt;1.30ms&lt;/td&gt;
&lt;td&gt;2.04ms&lt;/td&gt;
&lt;td&gt;4.27ms&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;ubuntu&lt;/td&gt;
&lt;td&gt;wrk&lt;/td&gt;
&lt;td&gt;pipy--&amp;gt;springboot&lt;/td&gt;
&lt;td&gt;73055&lt;/td&gt;
&lt;td&gt;1.35ms&lt;/td&gt;
&lt;td&gt;2.09ms&lt;/td&gt;
&lt;td&gt;2.49ms&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;ubuntu&lt;/td&gt;
&lt;td&gt;fortio&lt;/td&gt;
&lt;td&gt;springboot&lt;/td&gt;
&lt;td&gt;62249&lt;/td&gt;
&lt;td&gt;0.0015217&lt;/td&gt;
&lt;td&gt;0.00293947&lt;/td&gt;
&lt;td&gt;0.00428543&lt;/td&gt;
&lt;td&gt;0.00777612&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;ubuntu&lt;/td&gt;
&lt;td&gt;fortio&lt;/td&gt;
&lt;td&gt;pipy--&amp;gt;springboot&lt;/td&gt;
&lt;td&gt;69233&lt;/td&gt;
&lt;td&gt;0.0014350&lt;/td&gt;
&lt;td&gt;0.00249741&lt;/td&gt;
&lt;td&gt;0.00296226&lt;/td&gt;
&lt;td&gt;0.00362949&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;From the test results, we observed: Accessing Springboot service via Pipy proxy results in &lt;strong&gt;higher QPS&lt;/strong&gt; and &lt;strong&gt;lower latency&lt;/strong&gt; as compared to directly accessing the SpringBoot service.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For detailed test reports along with benchmark procedure, software used, load testing tools, and scripts used refer to Pipy wiki link below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/flomesh-io/pipy/wiki/BENCHMARK-:-Pipy-sidecar-proxy-SpringBoot"&gt;BENCHMARK：Pipy as proxy for SpringBoot REST service&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pipy</category>
      <category>pipyproxy</category>
      <category>microservices</category>
      <category>programming</category>
    </item>
    <item>
      <title>Announcing Pipy 0.30.0</title>
      <dc:creator>Ali Naqvi</dc:creator>
      <pubDate>Fri, 25 Mar 2022 05:45:26 +0000</pubDate>
      <link>https://dev.to/flomesh/announcing-pipy-0300-4ccm</link>
      <guid>https://dev.to/flomesh/announcing-pipy-0300-4ccm</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GRmc1up6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/baht1nr568fvt547qkg9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GRmc1up6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/baht1nr568fvt547qkg9.jpeg" alt="Pipy 0.30.0 release" width="880" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flomesh.io"&gt;&lt;code&gt;Pipy&lt;/code&gt;&lt;/a&gt; 0.30 is now available. It adds improvements to a number of areas including better documentation, more core controls, new filters, enhanced Cache and Metrics API, and some bug fixes. The Pipy Runtime API has expanded its coverage of SSL engines, asynchronus file read/write operations.&lt;/p&gt;

&lt;p&gt;This release was truly a community effort and could not have been made possible without all of the hard work from everyone involved in active discussions and the Pipy project on GitHub.The Pipy community provides code submissions covering new functionality and bug fixes, documentation improvements, quality assurance testing, continuous integration environments, bug reports, and much more. Everyone has done their part to make this release possible! If you’d like to join this amazing community, you can find it on GitHub, Slack, and the Pipy discussion groups.&lt;/p&gt;

&lt;p&gt;In the following sections, you will find a full list of changes included in this version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add flow control mechanism for throttling any types of input&lt;/li&gt;
&lt;li&gt;Add asynchronous file operations&lt;/li&gt;
&lt;li&gt;Support OpenSSL engines&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Filters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;New filter tee&lt;/li&gt;
&lt;li&gt;New filter &lt;code&gt;throttleConcurrency&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;New filter &lt;code&gt;demux&lt;/code&gt; (legacy &lt;code&gt;demux/mux&lt;/code&gt; filters are renamed to &lt;code&gt;demuxQueue/muxQueue&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Filter &lt;code&gt;decodeMQTT&lt;/code&gt; to support &lt;code&gt;protocolLevel&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt;Throttle filters support weak references as the account keys&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Support &lt;em&gt;TTL option&lt;/em&gt; for &lt;code&gt;algo.Cache&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;New method &lt;code&gt;stats.Metric.valueOf()&lt;/code&gt; for querying current metric value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Data.from()&lt;/code&gt; rejects input types other than strings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Major bug fixes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fixed a bug where TLS requests could be stuck in the buffer&lt;/li&gt;
&lt;li&gt;Fixed a dead loop when trying to read folders in codebases&lt;/li&gt;
&lt;li&gt;Fixed some crashes when null is given to some cypto APIs&lt;/li&gt;
&lt;li&gt;Fixed a crash when retrieving stats.Histogram sub-metrics&lt;/li&gt;
&lt;li&gt;Fixed a bug where an &lt;em&gt;HTTP 304&lt;/em&gt; response would lead to forever waiting on the connection&lt;/li&gt;
&lt;li&gt;Fixed a bug in &lt;code&gt;Data::shift_while()&lt;/code&gt; that caused Dubbo decoding failures&lt;/li&gt;
&lt;li&gt;The size of Data wasn't changed accordingly in some cases when packing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Support static linking to &lt;code&gt;libc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Support linking to external &lt;code&gt;zlib&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;Tremendous growth in documentation coverage has been done since the last release in English, Chinese and Japanese.&lt;/p&gt;

&lt;p&gt;We would like to thank each and every contributor who was involved in this release.&lt;/p&gt;

</description>
      <category>pipy</category>
      <category>pipyproxy</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
