Application onboarding
Onboard Services
The following guide describes how to onboard a Kubernetes microservice to an FSM instance.
Refer to the application requirements guide before onboarding applications.
Configure and Install Service Mesh Interface (SMI) policies
FSM conforms to the SMI specification. By default, FSM denies all traffic communications between Kubernetes services unless explicitly allowed by SMI policies. This behavior can be overridden with the --set=fsm.enablePermissiveTrafficPolicy=true
flag on the fsm install
command, allowing SMI policies not to be enforced while allowing traffic and services to still take advantage of features such as mTLS-encrypted traffic, metrics, and tracing.
For example SMI policies, please see the following examples:
If an application in the mesh needs to communicate with the Kubernetes API server, the user needs to explicitly allow this either by using IP range exclusion or by creating an egress policy as outlined below.
First get the Kubernetes API server cluster IP:
$ kubectl get svc -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1d
Option 1: add the Kubernetes API server’s address to the list of Global outbound IP ranges for exclusion. The IP address could be a cluster IP address or a public IP address and should be appropriately excluded for connectivity to the Kubernetes API server.
Add this IP to the MeshConfig so that outbound traffic to it is excluded from interception by FSM’s sidecar:
$ kubectl patch meshconfig fsm-mesh-config -n <fsm-namespace> -p '{"spec":{"traffic":{"outboundIPRangeExclusionList":["10.0.0.1/32"]}}}' --type=merge
meshconfig.config.flomesh.io/fsm-mesh-config patched
Restart the relevant pods in monitored namespaces for this change to take effect.
Option 2: apply an Egress policy to allow access to the Kubernetes API server over HTTPS
Note: when using an Egress policy, the Kubernetes API service must not be in a namespace that FSM manages
- Enable egress policy if not enabled:
kubectl patch meshconfig fsm-mesh-config -n <fsm-namespace> -p '{"spec":{"featureFlags":{"enableEgressPolicy":true}}}' --type=merge
- Apply an Egress policy to allow the application’s ServiceAccount to access the Kubernetes API server cluster IP found above.
For example:
kubectl apply -f - <<EOF
kind: Egress
apiVersion: policy.flomesh.io/v1alpha1
metadata:
name: k8s-server-egress
namespace: test
spec:
sources:
- kind: ServiceAccount
name: <app pod's service account name>
namespace: <app pod's service account namespace>
ipAddresses:
- 10.0.0.1/32
ports:
- number: 443
protocol: https
EOF
Onboard Kubernetes Namespaces to FSM
To onboard a namespace containing applications to be managed by FSM, run the fsm namespace add
command:
$ fsm namespace add <namespace> --mesh-name <mesh-name>
By default, the fsm namespace add
command enables automatic sidecar injection for pods in the namespace.
To disable automatic sidecar injection as a part of enrolling a namespace into the mesh, use fsm namespace add <namespace> --disable-sidecar-injection
.
Once a namespace has been onboarded, pods can be enrolled in the mesh by configuring automatic sidecar injection. See the Sidecar Injection document for more details.
Deploy new applications or redeploy existing applications
By default, new deployments in onboarded namespaces are enabled for automatic sidecar injection. This means that when a new Pod is created in a managed namespace, FSM will automatically inject the sidecar proxy to the Pod.
Existing deployments need to be restarted so that FSM can automatically inject the sidecar proxy upon Pod re-creation. Pods managed by a Deployment can be restarted using the kubectl rollout restart deploy
command.
In order to route protocol specific traffic correctly to service ports, configure the application protocol to use. Refer to the application protocol selection guide to learn more.
Note: Removing Namespaces
Namespaces can be removed from the FSM mesh with the fsm namespace remove
command:
fsm namespace remove <namespace>
Please Note:
The fsm namespace remove
command only tells FSM to stop applying updates to the sidecar proxy configurations in the namespace. It does not remove the proxy sidecars. This means the existing proxy configuration will continue to be used, but it will not be updated by the FSM control plane. If you wish to remove the proxies from all pods, remove the pods’ namespaces from the FSM mesh with the CLI and reinstall all the pod workloads.
1 - Prerequisites
Application Requirements
Security Contexts
- Do not run applications with the user ID (UID) value of 1500. This is reserved for the Pipy proxy sidecar container injected into pods by FSM’s sidecar injector.
- If security context
runAsNonRoot
is set to true
at the pod level, a runAsUser
value must be provided either for the pod
or for each container. For example: securityContext:
runAsNonRoot: true
runAsUser: 1200
If the UID is omitted, application containers may attempt to run as root user by default, causing conflict with the pod’s security context. - Additional capabilities are not required.
Note: the FSM init container is programmed to run as root and add capability NET_ADMIN
as it requires these security
contexts to finish scheduling. These values are not changed by application security contexts.
Ports
Do not use the following ports as they are used by the Pipy sidecar.
Port | Description |
---|
15000 | Pipy Admin Port |
15001 | Pipy Outbound Listener Port |
15003 | Pipy Inbound Listener Port |
15010 | Pipy Prometheus Inbound Listener Port |
2 - Namespace addition
This section describes how and why FSM monitors Kubernetes namespaces
Overview
When setting up an FSM control plane (also referred to as a “mesh”), one can also enroll a set of Kubernetes namespaces to the mesh. Enrolling a namespace to FSM allows FSM to monitor the resources within that Namespace whether they be applications deployed in Pods, Services, or even traffic policies represented as SMI resources.
Only one mesh can monitor a namespace, so this is something to watch out for when there are multiple instances of FSM within the same Kubernetes cluster. When applying policies to applications, FSM will only assess resources in either monitored namespaces so it is important to enroll namespaces where your applications are deployed to the correct instance of FSM with the correct mesh name.
Enrolling a namespace also optionally allows for metrics to be collected for resources in the given namespace and for Pods in the namespace to be automatically injected with sidecar proxy containers. These are all features that help FSM provide functionality for traffic management and observability. Scoping this functionality at the namespace level allows teams to organize which segments of
their cluster should be part of which mesh.
Namespace monitoring, automatic sidecar injection, and metrics collection is controlled by adding certain labels and annotations to a Kubernetes namespace. This can be done manually or using the fsm
CLI although using the fsm
CLI is the recommended approach. The presence of the label flomesh.io/monitored-by=<mesh-name>
allows an FSM control plane with the given mesh-name
to monitor
all resources within that namespace. The annotation flomesh.io/sidecar-injection=enabled
enables FSM to automatically inject sidecar proxy containers in all Pods created within that namespace. The metrics annotation flomesh.io/metrics=enabled
allows FSM to collect metrics on resources within a Namespace.
See how to use the FSM CLI to manage namespace monitoring below.
Adding a Namespace to the FSM Control Plane
Add a namespace for monitoring and sidecar injection to the mesh with the following command:
fsm namespace add <namespace>
Explicitly disable sidecar injection while adding the namespace using --disable-sidecar-injection
flag as shown here.
Remove a Namespace from the FSM control plane
Remove a namespace from being monitored by the mesh and disable sidecar injection with the following command:
fsm namespace remove <namespace>
This command will remove the FSM specific labels and annotations on the namespace thus removing it from the mesh.
Enable Metrics for a Namespace
fsm metrics enable --namespace <namespace>
Ignore a Namespace
There may be namespaces in a cluster that should never be part of a mesh. To explicity exclude a namespace from FSM:
fsm namespace ignore <namespace>
List Namespaces Part of a Mesh
To list namespaces within a specific mesh:
fsm namespace list --mesh-name=<mesh-name>
Troubleshooting Guide
Policy Issues
If you’re not seeing changes in SMI policies being applied to resources in a namespace, ensure the namespace is enrolled in the correct mesh:
fsm namespace list --mesh-name=<mesh-name>
NAMESPACE MESH SIDECAR-INJECTION
<namespace> fsm enabled
If the namespace does not show up, check the labels on the namespace using kubectl
:
kubectl get namespace <namespace> --show-labels
NAME STATUS AGE LABELS
<namespace> Active 36s flomesh.io/monitored-by=<mesh-name>
If the label value is not the expected mesh-name
, remove the namespace from the mesh and add it back using the correct mesh-name
.
fsm namespace remove <namespace> --mesh-name=<current-mesh-name>
fsm namespace add <namespace> --mesh-name=<expected-mesh-name>
If the monitored-by label is not present, it was either not added to the mesh or there was an error when adding it to the mesh.
Add the namespace to the mesh either with the fsm
CLI or using kubectl:
fsm namespace add <namespace> --mesh-name=<mesh-name>
kubectl label namespace <namespace> flomesh.io/monitored-by=<mesh-name>
Issues with Automatic Sidecar Injection
If you’re not seeing your Pods being automatically injected with sidecar containers, ensure that sidecar injection is enabled:
fsm namespace list --mesh-name=<mesh-name>
NAMESPACE MESH SIDECAR-INJECTION
<namespace> fsm enabled
If the namespace does not show up, check the annotations on the namespace using kubectl
:
kubectl get namespace <namespace> -o=jsonpath='{.metadata.annotations.flomesh\.io\/sidecar-injection}'
If the output is anything other than enabled
, either add namespace using the fsm
CLI or add the annotation with kubectl
:
fsm namespace add <namespace> --mesh-name=<mesh-name> --disable-sidecar-injection=false
kubectl annotate namespace <namespace> flomesh.io/sidecar-injection=enabled --overwrite
Issues with Metrics Collection
If you’re not seeing metrics for resources in a particular namespace, ensure metrics are enabled:
kubectl get namespace <namespace> -o=jsonpath='{.metadata.annotations.flomesh\.io\/metrics}'
If the output is anything other than enabled
, enable the namespace usng the fsm
CLI or add the annotation with kubectl
:
fsm metrics enable --namespace <namespace>
kubectl annotate namespace <namespace> flomesh.io/metrics=enabled --overwrite
Other Issues
If you’re running into issues that have not been resolved with the debugging techniques above, please open a GitHub issue on the repository.
3 - Sidecar Injection
This section describes the sidecar injection workflow in FSM.
Services participating in the service mesh communicate via sidecar proxies installed on pods backing the services. The following sections describe the sidecar injection workflow in FSM.
Automatic Sidecar Injection
Automatic sidecar injection is currently the only way to inject sidecars into the service mesh. Sidecars can be automatically injected into applicable Kubernetes pods using a mutating webhook admission controller provided by FSM.
Automatic sidecar injection can be configured per namespace as a part of enrolling a namespace into the mesh, or later using the Kubernetes API. Automatic sidecar injection can be enabled either on a per namespace or per pod basis by annotating the namespace or pod resource with the sidecar injection annotation. Individual pods and namespaces can be explicitly configured to either enable or disable automatic sidecar injection, giving users the flexibility to control sidecar injection on pods and namespaces.
Enabling Automatic Sidecar Injection
Prerequisites:
- The namespace to which the pods belong must be a monitored namespace that is added to the mesh using the
fsm namespace add
command. - The namespace to which the pods belong must not be set to be ignored using the
fsm namespace ignore
command. - The namespace to which the pods belong must not have a label with key
name
and value corresponding to the FSM control plane namespace. For example, a namespace with a label name: fsm-system
where fsm-system
is the control plane namespace cannot have sidecar injection enabled for pods in this namespace. - The pod must not have
hostNetwork: true
in the pod spec. Pods with hostNetwork: true
are not injected with a sidecar since doing so can result in routing failures in the host network.
Automatic Sidecar injection can be enabled in the following ways:
While enrolling a namespace into the mesh using fsm
cli: fsm namespace add <namespace>
:
Automatic sidecar injection is enabled by default with this command.
Using kubectl
to annotate individual namespaces and pods to enable sidecar injection:
# Enable sidecar injection on a namespace
$ kubectl annotate namespace <namespace> flomesh.io/sidecar-injection=enabled
# Enable sidecar injection on a pod
$ kubectl annotate pod <pod> flomesh.io/sidecar-injection=enabled
Setting the sidecar injection annotation to enabled
in the Kubernetes resource spec for a namespace or pod:
metadata:
name: test
annotations:
'flomesh.io/sidecar-injection': 'enabled'
Pods will be injected with a sidecar ONLY if the following conditions are met:
- The namespace to which the pod belongs is a monitored namespace.
- The pod is explicitly enabled for the sidecar injection, OR the namespace to which the pod belongs is enabled for the sidecar injection and the pod is not explicitly disabled for sidecar injection.
Explicitly Disabling Automatic Sidecar Injection on Namespaces
Namespaces can be disabled for automatic sidecar injection in the following ways:
While enrolling a namespace into the mesh using fsm
cli: fsm namespace add <namespace> --disable-sidecar-injection
:
If the namespace was previously enabled for sidecar injection, it will be disabled after running this command.
Using kubectl
to annotate individual namespaces to disable sidecar injection:
# Disable sidecar injection on a namespace
$ kubectl annotate namespace <namespace> flomesh.io/sidecar-injection=disabled
Explicitly Disabling Automatic Sidecar Injection on Pods
Individual pods can be explicitly disabled for sidecar injection. This is useful when a namespace is enabled for sidecar injection but specific pods should not be injected with sidecars.
Automatic sidecar injection is implicitly disabled for a namespace when it is removed from the mesh using the fsm namespace remove
command.
4 - Application Protocol Selection
Application Protocol Selection
FSM is capable of routing different application protocols such as HTTP
, TCP
, and gRPC
differently. The following guide describes how to configure service ports to specify the application protocol to use for traffic filtering and routing.
Configuring the application protocol
Kubernetes services expose one or more ports. A port exposed by an application running the service can serve a specific application protocol such as HTTP, TCP, gRPC etc. Since FSM filters and routes traffic for different application protocols differently, a configuration on the Kubernetes service object is necessary to convey to FSM how traffic directed to a service port must be routed.
In order to determine the application protocol served by a service’s port, FSM expects the appProtocol
field on the service’s port to be set.
FSM supports the following application protocols for service ports:
http
: For HTTP based filtering and routing of traffictcp
: For TCP based filtering and routing of traffictcp-server-first
: For TCP based filtering and routing of traffic where the server initiates communication with a client, such as mySQL, PostgreSQL, and othersgRPC
: For HTTP2 based filtering and routing of gRPC traffic
The application protocol configuration described is applicable to both SMI and Permissive traffic policy modes.
Examples
Consider the following SMI traffic access and traffic specs policies:
- A
TCPRoute
resource named tcp-route
that specifies the port TCP traffic should be allowed on. - An
HTTPRouteGroup
resource named http-route
that specifies the HTTP routes for which HTTP traffic should be allowed. - A
TrafficTarget
resource named test
that allows pods in the service account sa-2
to access pods in the service account sa-1
for the specified TCP and HTTP rules.
kind: TCPRoute
metadata:
name: tcp-route
spec:
matches:
ports:
- 8080
---
kind: HTTPRouteGroup
metadata:
name: http-route
spec:
matches:
- name: version
pathRegex: "/version"
methods:
- GET
---
kind: TrafficTarget
metadata:
name: test
namespace: default
spec:
destination:
kind: ServiceAccount
name: sa-1 # There are 2 services under this service account: service-1 and service-2
namespace: default
rules:
- kind: TCPRoute
name: tcp-route
- kind: HTTPRouteGroup
name: http-route
sources:
- kind: ServiceAccount
name: sa-2
namespace: default
Kubernetes service resources should explicitly specify the application protocol being served by the service’s ports using the appProtocol
field.
A service service-1
backed by a pod in service account sa-1
serving http
application traffic should be defined as follows:
kind: Service
metadata:
name: service-1
namespace: default
spec:
ports:
- port: 8080
name: some-port
appProtocol: http
A service service-2
backed by a pod in service account sa-1
serving raw tcp
application traffic shold be defined as follows:
kind: Service
metadata:
name: service-2
namespace: default
spec:
ports:
- port: 8080
name: some-port
appProtocol: tcp