Use Apache Camel K to Create Microservice Apps with Instana
By: Rui Liu
Tags: Instana, Microservices Application, Camelk, Apache

Instana is the fully-automated Application Performance Management (APM) solution designed specifically for the challenges of managing microservices and cloud-native applications. Its extensive support of middlewares, services, products and environments ensures that Instana provides the market-leading solution in APM systems.

Apache Camel K is the popular open-source, lightweight integration framework built from Apache Camel that runs natively on Kubernetes and is specifically designed for serverless and microservice architectures. Users of Camel K can instantly run integration code written in Camel DSL on their preferred cloud (Kubernetes or OpenShift).

Instana and Apache Camel K are focused on and they are best partnered working in microservice and cloud-native environments. With Apache Camel K, you can quickly create your code to read Instana for metrics, events, and topology data, working as a web hook to receive events, and even configure and change the Instana server system, without having to create Docker images and find image repositories.

Now let’s set up Apache Camel K to work with Instana.

Set up credentials

You probably need to get credentials to access Instana unless you only want to create a Web hook to receive Instana events. Click the Settings icon, choose Team Settings > API Tokens, and then click the Add API Token link to create a new API Token.

Set appropriate permissions for the API Token in accordance with your requirements to use Instana Backend API.

To set access information (endpoint and API token) of Instana to Camel K integrations, a typical way is to use Config Map to set Camel K system properties. For example:

apiVersion: v1

kind: ConfigMap

metadata:

name: instana-config

data:

application.properties: |

instana.token=skDXGZsrQpq8sBI2_G9rpA

instana.endpoint=instanaa1-xxx.com…

You can use the following method to add Instana endpoint and API token into the Camel K integration code as system properties:



private String iToken;

(value="instana.endpoint")

private String iEndpoint; @PropertyInject ("instana.token")private String iToken; @PropertyInject (value="instana.endpoint")private String iEndpoint;

Use Instana backend REST API

Instana has a rich set of APIs to access data and configure changes. For more details, see the official online document at https://instana.github.io/openapi/.

The Instana backend REST API includes the following contents:

API for infrastructure monitoring

API for website monitoring

API for application monitoring

APIs for events

API for settings

Here is a curl command to call a simple Instana back-end service of listing all supported plugins of infrastructure monitoring:

Typical settings for TOKEN and ENDPOINT environment variables for a public Instana Server:

ENDPOINT=xxxx.instana.io

TOKEN=xxxxxxxx

Typical settings for TOKEN and ENDPOINT environment variables for a self-hosting Instana Server:

ENDPOINT=xxxx.yyyy.com

TOKEN=xxxxxxxx

Sample code of Camel K to call Instana REST API to get settings of Instana Application Perspectives (Note: we are using Java DSL):

Note: According to https://instana.github.io/openapi/#section/Backend-REST-API, a rate limit is applied to Instana REST API usage, and a maximum of 5,000 calls per hour can be made. This restriction is for each Instana API token.

More considerations of the Camel K code

For self-hosting Instana, usually we do not need to verify the certificate and key file returned by the HTTPS request to the Instana server. We just use API tokens. Here is the code:

public static void configureHttpClient(CamelContext context) {

HttpComponent httpComponent = context.getComponent("https", HttpComponent.class);

httpComponent.setHttpClientConfigurer(new HttpClientConfigurer() { @Override

public void configureHttpClient(HttpClientBuilder clientBuilder) {

SSLContext sslContext = null;

try {

sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {

return true;

}

}).build();

} catch (KeyManagementException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (NoSuchAlgorithmException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (KeyStoreException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

clientBuilder.setSSLContext(sslContext);

final HostnameVerifier hostnameVerifier = getHostnameVerifier();

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()

.register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory).build();

PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

clientBuilder.setConnectionManager(connMgr);

}

});

} public void configureHttpClient(HttpClientBuilder clientBuilder) {SSLContext sslContext = null;try {sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {return true;}).build();} catch (KeyManagementException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchAlgorithmException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (KeyStoreException e) {// TODO Auto-generated catch blocke.printStackTrace();clientBuilder.setSSLContext(sslContext);final HostnameVerifier hostnameVerifier = getHostnameVerifier();SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);Registry socketFactoryRegistry = RegistryBuilder. create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory).build();PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);clientBuilder.setConnectionManager(connMgr);}); public void configure() {

configureHttpClient(getContext());

…

}

With the code, we enable Camel Integration to retry 10 times at maximum when there is IOExeption. Collision avoidance is enabled to add some randomness to the timings. The exponential backoff is used (i.e. the time between retries increases using a backoff multiplier).

And finally, following is a sample command line to run Camel K Integration with Instana: (Note: we use Camel K version 3.2)

kamel run — name instana-controller \

— property xxx1=yyy1 \

— property xxx2=yyy2 \

— trait knative-service.enabled=false \

— trait knative-service.min-scale=1 \

— trait knative.sink-binding=false \

— configmap instana-config \

-d camel-quarkus-http \

-d camel-quarkus-kafka \

-d camel-quarkus-avro \

-d mvn:org.apache.camel.k:camel-knative-api:1.4.1 \

-d mvn:io.apicurio:apicurio-registry-rest-client:1.3.2.Final \

xxxx1.java \

xxxx2.java

Now it is time for you to create your own first Camel K integration to access Instana. Enjoy it!