Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Addon] pyroscope addon #361

Merged
merged 5 commits into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions addons/pyroscope/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: pyroscope
version: 0.17.1
description: Pyroscope is an open source platform, consisting of server and agent. It allows the user to collect, store, and query the profiling data in a CPU and disk efficient way.
url: https://github.com/pyroscope-io/pyroscope
icon: https://raw.githubusercontent.com/pyroscope-io/pyroscope/main/webapp/images/favicon.ico

tags:
- profiling tool

deployTo:
control_plane: true

dependencies:
- name: fluxcd

needNamespace:
- vela-system

invisible: false
195 changes: 195 additions & 0 deletions addons/pyroscope/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# Pyroscope

This addon is built based [Pyroscope](https://github.com/pyroscope-io/pyroscope), which consist of server and agent. It allows the user to collect, store, and query the profiling data in a CPU and disk efficient way.

## install

```shell
vela addon enable pyroscope
```

## uninstall

```shell
vela addon disable pyroscope
```

## Note
### Pyroscope for Golang applications

- To start profiling a Go application, you need to include our go module in your app
```shell
fourierr marked this conversation as resolved.
Show resolved Hide resolved
# make sure you also upgrade pyroscope server to version 0.3.1 or higher
go get github.com/pyroscope-io/client/pyroscope
```
- Then add the following code to your application:
```go
package main

import "github.com/pyroscope-io/client/pyroscope"

func main() {
pyroscope.Start(pyroscope.Config{
ApplicationName: "simple.golang.app",
// replace this with the address of pyroscope server
ServerAddress: "http://pyroscope-server:4040",
// you can disable logging by setting this to nil
Logger: pyroscope.StandardLogger,

// optionally, if authentication is enabled, specify the API key:
// AuthToken: os.Getenv("PYROSCOPE_AUTH_TOKEN"),

fourierr marked this conversation as resolved.
Show resolved Hide resolved
// by default all profilers are enabled, but you can select the ones you want to use:
ProfileTypes: []pyroscope.ProfileType{
pyroscope.ProfileCPU,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileAllocSpace,
pyroscope.ProfileInuseObjects,
pyroscope.ProfileInuseSpace,
},
})

// your code goes here
}
```
- Check out the [examples](https://github.com/pyroscope-io/pyroscope/tree/main/examples/golang-push) directory in our repository to learn more

### Pyroscope for Java applications

- Java integration is distributed as a single jar file: pyroscope.jar. It contains native async-profiler libraries
- To start profiling a Java application, run your application with pyroscope.jar javaagent:
```shell
export PYROSCOPE_APPLICATION_NAME=my.java.app
export PYROSCOPE_SERVER_ADDRESS=http://pyroscope-server:4040

# Optionally, if authentication is enabled, specify the API key.
# export PYROSCOPE_AUTH_TOKEN={YOUR_API_KEY}

java -javaagent:pyroscope.jar -jar app.jar
```
- Check out the [examples](https://github.com/pyroscope-io/pyroscope/tree/main/examples/java) folder in our repository to learn more

### Pyroscope for .net applications

- To start profiling a .NET application inside a container, you may wrap your application with pyroscope exec as an entrypoint of your image. The tricky part is that you need to copy pyroscope binary to your docker container. To do that, use COPY --from command in your Dockerfile.
The following example Dockerfile shows how to build the image:
```dockerfile
FROM mcr.microsoft.com/dotnet/sdk:5.0

WORKDIR /dotnet

COPY --from=pyroscope/pyroscope:latest /usr/bin/pyroscope /usr/bin/pyroscope
ADD my-app .
RUN dotnet publish -o . -r $(dotnet --info | grep RID | cut -b 6- | tr -d ' ')

# optionally you may set the pyroscope server address as well as the app name and other configuration options.
ENV PYROSCOPE_SERVER_ADDRESS=http://pyroscope-server:4040
ENV PYROSCOPE_APPLICATION_NAME=my.dotnet.app
ENV PYROSCOPE_LOG_LEVEL=debug

CMD ["pyroscope", "exec", "dotnet", "/dotnet/my-app.dll"]
```
- If you are using Docker Compose, you can run both pyroscope server and agent with this configuration:
```yaml
---
version: "3.9"
services:
pyroscope-server:
image: "pyroscope/pyroscope:latest"
ports:
- "4040:4040"
command:
- "server"
app:
image: "my-app:latest"
environment:
PYROSCOPE_APPLICATION_NAME: my.dotnet.app
PYROSCOPE_SERVER_ADDRESS: http://pyroscope-server:4040
PYROSCOPE_LOG_LEVEL: debug
ASPNETCORE_URLS: http://*:5000
ports:
- "5000:5000"
cap_add:
- SYS_PTRACE
```
- Check out the [examples](https://github.com/pyroscope-io/pyroscope/tree/main/examples/dotnet) folder in our repository to learn more

### Pyroscope for Python applications

- First, install pyroscope-io pip package:
```shell
pip install pyroscope-io
```
- Add the following code to your application. This code will initialize pyroscope profiler and start profiling:
```shell
import pyroscope

pyroscope.configure(
app_name = "my.python.app", # replace this with some name for your application
server_address = "http://my-pyroscope-server:4040", # replace this with the address of your pyroscope server
# auth_token = "{YOUR_API_KEY}", # optionally, if authentication is enabled, specify the API key
)
```
- Check out the [example python project in pyroscope repository](https://github.com/pyroscope-io/pyroscope/tree/main/examples/python) for examples of how you can use these features.

### Pyroscope for PHP applications

- To start profiling a PHP application in a container, you may wrap your application with pyroscope exec as an entrypoint of your image. The tricky part is that you need to copy pyroscope binary to your docker container. To do that, use COPY --from command in your Dockerfile.
The following example Dockerfile shows how to build the image:
```dockerfile
FROM php:7.3.27

WORKDIR /var/www/html

# this copies pyroscope binary from pyroscope image to your image:
COPY --from=pyroscope/pyroscope:latest /usr/bin/pyroscope /usr/bin/pyroscope
COPY main.php ./main.php

# optionally you may set the pyroscope server address as well as the app name, make sure you change these:
ENV PYROSCOPE_APPLICATION_NAME=my.php.app
ENV PYROSCOPE_SERVER_ADDRESS=http://pyroscope:4040/

# this starts your app with pyroscope profiler, make sure to change "php" and "main.php" to the actual command.
CMD ["pyroscope", "exec", "php", "main.php"]
```
- If you are using Docker Compose, you can run both pyroscope server and agent with this configuration:
```yaml
---
services:
pyroscope-server:
image: "pyroscope/pyroscope:latest"
ports:
- "4040:4040"
command:
- "server"
app:
image: "my-app:latest"
env:
PYROSCOPE_SERVER_ADDRESS: http://pyroscope-server:4040
PYROSCOPE_APPLICATION_NAME: my.php.app
cap_add:
- SYS_PTRACE
```
- Check out the [examples](https://github.com/pyroscope-io/pyroscope/tree/main/examples/php) folder in our repository to learn more

### Pyroscope for NodeJS applications

- To start profiling a NodeJS application, you need to include the npm module in your app:
```shell
npm install @pyroscope/nodejs

# or
yarn add @pyroscope/nodejs
```
- Then add the following code to your application:
```js
const Pyroscope = require('@pyroscope/nodejs');

Pyroscope.init({
serverAddress: 'http://pyroscope:4040',
appName: 'myNodeService'
});

Pyroscope.start()
```
- Check out the [examples](https://github.com/pyroscope-io/pyroscope/tree/main/examples/nodejs) directory in our repository to learn more
61 changes: 61 additions & 0 deletions addons/pyroscope/resources/parameter.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
parameter: {
// +usage=Specify image to use for deploying
"image.repository": *"pyroscope/pyroscope" | string
// +usage=Specify tag for pyroscope image to use
"image.tag": *"0.17.1" | string
// +usage=Specify image pull policy
"image.pullPolicy": *"IfNotPresent" | string
// +usage=Specify image pull secrets
"imagePullSecrets": *[] | [...string]

// +usage=Specify enables Ingress
"ingress.enabled": *false | bool
// +usage=Specify ingress accepted hostnames
"ingress.hosts": #host
// +usage=Specify ingress custom rules. Take precedence over chart built-ins.
"ingress.rules": *[] | [...string]
// +usage=Specify ingress TLS configuration
"ingress.tls": *[] | [...string]

// +usage=Specify persistence access modes
"persistence.accessModes": *"ReadWriteOnce" | string
// +usage=Specify use persistent volume to store data
"persistence.enabled": *false | bool
// +usage=Specify persistentVolumeClaim finalizers
"persistence.finalizers": *["kubernetes.io/pvc-protection"] | [...string]
// +usage=Specify size of persistent volume claim
"persistence.size": *"10Gi" | string

// +usage=Specify pyroscope server configuration. Please refer to https://pyroscope.io/docs/server-configuration
"pyroscopeConfigs":*{} | #map

// +usage=Specify extra rules for created cluster role
"rbac.clusterRole.extraRules": *[] | [...string]
// +usage=Specify cluster role name. If not set, the fully qualified app name is used
"rbac.clusterRole.name": *"" | string
// +usage=Specify cluster role binding name. If not set, the fully qualified app name is used
"rbac.clusterRoleBinding.name":*"" | string
// +usage=Specify creates Pyroscope cluster role and binds service account to it; requires service account to be created
"rbac.create": *false | bool

// +usage=Specify kubernetes port where service is exposed
"service.port": *4040 | int
// +usage=Specify service type
"service.type": *"ClusterIP" | string
// +usage=Specify create service account
"serviceAccount.create": *true | bool
// +usage=Specify service account name to use, when empty will be set to created account if serviceAccount.create is set else to default
"serviceAccount.name": * "" | string
}

#host: [...{
"host": *"chart-example.local" | string
"paths": #paths
}]

#paths: [...{
"path": *"/" | string
"pathType": *"Prefix" | string
}]

#map: [string]: string
50 changes: 50 additions & 0 deletions addons/pyroscope/resources/pyroscope.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
output: {
type: "helm"
properties: {
repoType: "helm"
url: "https://pyroscope-io.github.io/helm-chart"
chart: "pyroscope"
version: "0.2.48"
targetNamespace: "vela-system"
releaseName: "pyroscope"
values: {
image: {
repository: parameter["image.repository"]
tag: parameter["image.tag"]
pullPolicy: parameter["image.pullPolicy"]
}
imagePullSecrets: parameter["imagePullSecrets"]
ingress: {
enabled: parameter["ingress.enabled"]
hosts: parameter["ingress.hosts"]
rules: parameter["ingress.rules"]
tls: parameter["ingress.tls"]
}
persistence: {
accessModes: parameter["persistence.accessModes"]
enabled: parameter["persistence.enabled"]
finalizers: parameter["persistence.finalizers"]
size: parameter["persistence.size"]
}
pyroscopeConfigs: parameter["pyroscopeConfigs"]
rbac: {
create: parameter["rbac.create"]
clusterRoleBinding: {
name: parameter["rbac.clusterRoleBinding.name"]
}
clusterRole: {
name: parameter["rbac.clusterRole.name"]
extraRules: parameter["rbac.clusterRole.extraRules"]
}
}
service: {
port: parameter["service.port"]
type: parameter["service.type"]
}
serviceAccount: {
create: parameter["serviceAccount.create"]
name: parameter["serviceAccount.name"]
}
}
}
}
6 changes: 6 additions & 0 deletions addons/pyroscope/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: pyroscope
namespace: vela-system
spec:
18 changes: 17 additions & 1 deletion test/e2e-test/hack/addon-vela-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ for i in $ADDONS ; do
vela addon enable $i domain=abc.com || vela -n vela-system status addon-$i
elif [ $i == "model-serving" ]; then
vela addon enable ./addons/$i serviceType=ClusterIP || vela -n vela-system status addon-$i
elif [ $i != "ocm-gateway-manager-addon" ] && [ $i != "terraform-baidu" ] && [ $i != "dex" ] && [ $i != "flink-kubernetes-operator" ] && [ $i != "cert-manager" ]; then
elif [ $i != "ocm-gateway-manager-addon" ] && [ $i != "terraform-baidu" ] && [ $i != "dex" ] && [ $i != "flink-kubernetes-operator" ] && [ $i != "cert-manager" ] && [ $i != "pyroscope" ]; then
vela addon enable ./addons/$i
fi

Expand Down Expand Up @@ -49,6 +49,22 @@ vela addon enable cert-manager
vela addon enable flink-kubernetes-operator
# set back to the DEFAULT_VELA_NS
declare -x DEFAULT_VELA_NS=vela-system

# test pyroscope addon
# enable pyroscope
kubectl create ns pyroscope-system
declare -x DEFAULT_VELA_NS=pyroscope-system
vela addon enable fluxcd
vela addon enable pyroscope
wonderflow marked this conversation as resolved.
Show resolved Hide resolved
declare -x DEFAULT_VELA_NS=vela-system

# disable pyroscope
declare -x DEFAULT_VELA_NS=pyroscope-system
vela addon disable pyroscope
fourierr marked this conversation as resolved.
Show resolved Hide resolved
vela addon disable fluxcd
kubectl delete ns pyroscope-system
# set back to the DEFAULT_VELA_NS
declare -x DEFAULT_VELA_NS=vela-system
```

## Uninstall
Expand Down