diff --git a/Makefile b/Makefile index bdb97e37ab..cc91208f4c 100644 --- a/Makefile +++ b/Makefile @@ -240,3 +240,11 @@ go-fmt: .PHONY: check-license check-license: ./scripts/check-license.sh + +.PHONY: dev/up +dev/up: deploy/manifests + source ./scripts/local-dev.sh && up + +.PHONY: dev/down +dev/down: + source ./scripts/local-dev.sh && down diff --git a/Tiltfile b/Tiltfile new file mode 100644 index 0000000000..8d0906a16d --- /dev/null +++ b/Tiltfile @@ -0,0 +1,11 @@ +docker_prune_settings(num_builds=5) + +## Parca Agent + +docker_build( + 'parca.io/parca/parca-agent:dev', '', + dockerfile='Dockerfile.dev', + only=['./cmd', './pkg', './3rdparty', './go.mod', './go.sum', './parca-agent.bpf.c', './vmlinux.h', './Makefile'], +) +k8s_yaml('deploy/tilt/parca-agent-daemonSet.yaml') +k8s_resource('parca-agent', port_forwards=[7071]) diff --git a/deploy/Makefile b/deploy/Makefile index 7280ffc126..3291bc001f 100644 --- a/deploy/Makefile +++ b/deploy/Makefile @@ -1,5 +1,6 @@ JSONNET_FMT := jsonnetfmt -n 2 --max-blank-lines 2 --string-style s --comment-style s VERSION ?= $(shell git describe --exact-match --tags $$(git log -n1 --pretty='%h') 2>/dev/null || echo "$$(git rev-parse --abbrev-ref HEAD)-$$(git rev-parse --short HEAD)") +SERVER_LATEST_VERSION ?= $(shell curl -s https://api.github.com/repos/parca-dev/parca/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")' | xargs echo -n) .PHONY: vendor vendor: @@ -7,12 +8,13 @@ vendor: .PHONY: manifests manifests: vendor $(shell find . -name 'vendor' -prune -o -name '*.libsonnet' -print -o -name '*.jsonnet' -print) - rm -rf manifests - mkdir -p manifests/openshift manifests/kubernetes + rm -rf manifests tilt + mkdir -p manifests/openshift manifests/kubernetes tilt jsonnet --tla-str version="$(VERSION)" -J vendor main.jsonnet -m manifests/kubernetes | xargs -I{} sh -c 'cat {} | gojsontoyaml > {}.yaml; rm -f {}' -- {} awk 'BEGINFILE {print "---"}{print}' manifests/kubernetes/* > manifests/kubernetes/manifest.yaml jsonnet --tla-str version="$(VERSION)" -J vendor openshift.jsonnet -m manifests/openshift | xargs -I{} sh -c 'cat {} | gojsontoyaml > {}.yaml; rm -f {}' -- {} awk 'BEGINFILE {print "---"}{print}' manifests/openshift/* > manifests/openshift/manifest.yaml + jsonnet --tla-str serverVersion="$(SERVER_LATEST_VERSION)" -J vendor dev.jsonnet -m tilt | xargs -I{} sh -c 'cat {} | gojsontoyaml > {}.yaml; rm -f {}' -- {} fmt: find . -name 'vendor' -prune -o -name '*.libsonnet' -print -o -name '*.jsonnet' -print | \ diff --git a/deploy/dev.jsonnet b/deploy/dev.jsonnet index 03d65d625d..034b3c7fd3 100644 --- a/deploy/dev.jsonnet +++ b/deploy/dev.jsonnet @@ -1,7 +1,41 @@ -local agent = (import 'main.jsonnet'); +function(serverVersion='v0.4.2') + local ns = { + apiVersion: 'v1', + kind: 'Namespace', + metadata: { + name: 'parca', + }, + }; -std.manifestYamlStream([ - agent[name] - for name in std.objectFields(agent) - if agent[name] != null -]) + local server = (import 'parca/parca.libsonnet')({ + name: 'parca', + namespace: ns.metadata.name, + image: 'ghcr.io/parca-dev/parca:' + serverVersion, + version: serverVersion, + replicas: 1, + corsAllowedOrigins: '*', + }); + + local agent = (import 'parca-agent/parca-agent.libsonnet')({ + name: 'parca-agent', + namespace: ns.metadata.name, + version: 'dev', + image: 'parca.io/parca/parca-agent:dev', + stores: ['%s.%s.svc.cluster.local:%d' % [server.service.metadata.name, server.service.metadata.namespace, server.config.port]], + logLevel: 'debug', + insecure: true, + insecureSkipVerify: true, + tempDir: 'tmp', + }); + + { + '0namespace': ns, + } + { + ['parca-server-' + name]: server[name] + for name in std.objectFields(server) + if server[name] != null + } + { + ['parca-agent-' + name]: agent[name] + for name in std.objectFields(agent) + if agent[name] != null + } diff --git a/deploy/jsonnetfile.json b/deploy/jsonnetfile.json index 7c0ca1861f..c7ba924ee7 100644 --- a/deploy/jsonnetfile.json +++ b/deploy/jsonnetfile.json @@ -8,6 +8,15 @@ } }, "version": "" + }, + { + "source": { + "git": { + "remote": "https://github.com/parca-dev/parca.git", + "subdir": "deploy/lib/parca" + } + }, + "version": "main" } ], "legacyImports": true diff --git a/deploy/jsonnetfile.lock.json b/deploy/jsonnetfile.lock.json index 28f133889d..5499170db2 100644 --- a/deploy/jsonnetfile.lock.json +++ b/deploy/jsonnetfile.lock.json @@ -1,6 +1,16 @@ { "version": 1, "dependencies": [ + { + "source": { + "git": { + "remote": "https://github.com/parca-dev/parca.git", + "subdir": "deploy/lib/parca" + } + }, + "version": "7dc4a2456d95b124459fbc7661c9d9b9099f126d", + "sum": "pg6sezCvcHFY2A3OE5Ijs8AsRWw27ENvxtEdzw91JrA=" + }, { "source": { "local": { diff --git a/deploy/tilt/0namespace.yaml b/deploy/tilt/0namespace.yaml new file mode 100644 index 0000000000..d5a14e66c3 --- /dev/null +++ b/deploy/tilt/0namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: parca diff --git a/deploy/tilt/parca-agent-clusterRole.yaml b/deploy/tilt/parca-agent-clusterRole.yaml new file mode 100644 index 0000000000..3e64dacd49 --- /dev/null +++ b/deploy/tilt/parca-agent-clusterRole.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + name: parca-agent + namespace: parca +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - nodes + verbs: + - get diff --git a/deploy/tilt/parca-agent-clusterRoleBinding.yaml b/deploy/tilt/parca-agent-clusterRoleBinding.yaml new file mode 100644 index 0000000000..f0efbe2d20 --- /dev/null +++ b/deploy/tilt/parca-agent-clusterRoleBinding.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + name: parca-agent + namespace: parca +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: parca-agent +subjects: +- kind: ServiceAccount + name: parca-agent + namespace: parca diff --git a/deploy/tilt/parca-agent-daemonSet.yaml b/deploy/tilt/parca-agent-daemonSet.yaml new file mode 100644 index 0000000000..85f87d18c4 --- /dev/null +++ b/deploy/tilt/parca-agent-daemonSet.yaml @@ -0,0 +1,90 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + name: parca-agent + namespace: parca +spec: + selector: + matchLabels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + template: + metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + spec: + containers: + - args: + - /bin/parca-agent + - --log-level=debug + - --node=$(NODE_NAME) + - --kubernetes + - --store-address=parca.parca.svc.cluster.local:7070 + - --insecure + - --insecure-skip-verify + - --temp-dir=tmp + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + image: parca.io/parca/parca-agent:dev + name: parca-agent + ports: + - containerPort: 7071 + hostPort: 7071 + name: http + resources: {} + securityContext: + privileged: true + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /tmp + name: tmp + - mountPath: /run + name: run + - mountPath: /lib/modules + name: modules + - mountPath: /sys/kernel/debug + name: debugfs + - mountPath: /sys/fs/cgroup + name: cgroup + - mountPath: /sys/fs/bpf + name: bpffs + hostPID: true + nodeSelector: + kubernetes.io/arch: amd64 + kubernetes.io/os: linux + serviceAccountName: parca-agent + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists + volumes: + - emptyDir: {} + name: tmp + - hostPath: + path: /run + name: run + - hostPath: + path: /sys/fs/cgroup + name: cgroup + - hostPath: + path: /lib/modules + name: modules + - hostPath: + path: /sys/fs/bpf + name: bpffs + - hostPath: + path: /sys/kernel/debug + name: debugfs diff --git a/deploy/tilt/parca-agent-podSecurityPolicy.yaml b/deploy/tilt/parca-agent-podSecurityPolicy.yaml new file mode 100644 index 0000000000..4a757dcecb --- /dev/null +++ b/deploy/tilt/parca-agent-podSecurityPolicy.yaml @@ -0,0 +1,41 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + name: parca-agent + namespace: parca +spec: + allowPrivilegeEscalation: true + allowedCapabilities: + - '*' + allowedHostPaths: + - pathPrefix: /sys + - pathPrefix: /lib/modules + fsGroup: + rule: RunAsAny + hostIPC: true + hostNetwork: true + hostPID: true + hostPorts: + - max: 7071 + min: 7071 + privileged: true + readOnlyRootFilesystem: true + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - configMap + - emptyDir + - projected + - secret + - downwardAPI + - persistentVolumeClaim + - hostPath diff --git a/deploy/tilt/parca-agent-role.yaml b/deploy/tilt/parca-agent-role.yaml new file mode 100644 index 0000000000..5e1b125010 --- /dev/null +++ b/deploy/tilt/parca-agent-role.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + name: parca-agent + namespace: parca +rules: +- apiGroups: + - policy + resourceNames: + - parca-agent + resources: + - podsecuritypolicies + verbs: + - use diff --git a/deploy/tilt/parca-agent-roleBinding.yaml b/deploy/tilt/parca-agent-roleBinding.yaml new file mode 100644 index 0000000000..9d7bcefdc2 --- /dev/null +++ b/deploy/tilt/parca-agent-roleBinding.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + name: parca-agent + namespace: parca +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: parca-agent +subjects: +- kind: ServiceAccount + name: parca-agent diff --git a/deploy/tilt/parca-agent-serviceAccount.yaml b/deploy/tilt/parca-agent-serviceAccount.yaml new file mode 100644 index 0000000000..73c12d70bc --- /dev/null +++ b/deploy/tilt/parca-agent-serviceAccount.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca-agent + app.kubernetes.io/name: parca-agent + app.kubernetes.io/version: dev + name: parca-agent + namespace: parca diff --git a/deploy/tilt/parca-server-configmap.yaml b/deploy/tilt/parca-server-configmap.yaml new file mode 100644 index 0000000000..cadf0ea475 --- /dev/null +++ b/deploy/tilt/parca-server-configmap.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +data: + parca.yaml: |- + "debug_info": + "bucket": + "config": + "directory": "./tmp" + "type": "FILESYSTEM" + "cache": + "config": + "directory": "./tmp" + "type": "FILESYSTEM" +kind: ConfigMap +metadata: + name: parca-config + namespace: parca diff --git a/deploy/tilt/parca-server-deployment.yaml b/deploy/tilt/parca-server-deployment.yaml new file mode 100644 index 0000000000..883b73f5cb --- /dev/null +++ b/deploy/tilt/parca-server-deployment.yaml @@ -0,0 +1,67 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca + app.kubernetes.io/version: v0.5.0 + name: parca + namespace: parca +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca + template: + metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca + app.kubernetes.io/version: v0.5.0 + spec: + containers: + - args: + - /parca + - --config-path=/var/parca/parca.yaml + - --log-level=info + - --cors-allowed-origins=* + image: ghcr.io/parca-dev/parca:v0.5.0 + livenessProbe: + exec: + command: + - /grpc-health-probe + - -v + - -addr=:7070 + initialDelaySeconds: 5 + name: parca + ports: + - containerPort: 7070 + name: http + readinessProbe: + exec: + command: + - /grpc-health-probe + - -v + - -addr=:7070 + initialDelaySeconds: 10 + resources: {} + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - mountPath: /var/parca + name: parca-config + nodeSelector: + kubernetes.io/arch: amd64 + kubernetes.io/os: linux + securityContext: + fsGroup: 65534 + runAsUser: 65534 + serviceAccountName: parca + terminationGracePeriodSeconds: 120 + volumes: + - configMap: + name: parca-config + name: parca-config diff --git a/deploy/tilt/parca-server-podSecurityPolicy.yaml b/deploy/tilt/parca-server-podSecurityPolicy.yaml new file mode 100644 index 0000000000..3e1d19f27d --- /dev/null +++ b/deploy/tilt/parca-server-podSecurityPolicy.yaml @@ -0,0 +1,29 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: parca +spec: + allowPrivilegeEscalation: false + fsGroup: + ranges: + - max: 65535 + min: 1 + rule: MustRunAs + requiredDropCapabilities: + - ALL + runAsUser: + rule: MustRunAsNonRoot + seLinux: + rule: RunAsAny + supplementalGroups: + ranges: + - max: 65535 + min: 1 + rule: MustRunAs + volumes: + - configMap + - emptyDir + - projected + - secret + - downwardAPI + - persistentVolumeClaim diff --git a/deploy/tilt/parca-server-role.yaml b/deploy/tilt/parca-server-role.yaml new file mode 100644 index 0000000000..6ac3766c3f --- /dev/null +++ b/deploy/tilt/parca-server-role.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca + app.kubernetes.io/version: v0.5.0 + name: parca + namespace: parca +rules: +- apiGroups: + - policy + resourceNames: + - parca + resources: + - podsecuritypolicies + verbs: + - use diff --git a/deploy/tilt/parca-server-roleBinding.yaml b/deploy/tilt/parca-server-roleBinding.yaml new file mode 100644 index 0000000000..935fa6a6f6 --- /dev/null +++ b/deploy/tilt/parca-server-roleBinding.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca + app.kubernetes.io/version: v0.5.0 + name: parca + namespace: parca +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: parca +subjects: +- kind: ServiceAccount + name: parca diff --git a/deploy/tilt/parca-server-service.yaml b/deploy/tilt/parca-server-service.yaml new file mode 100644 index 0000000000..fb530375cb --- /dev/null +++ b/deploy/tilt/parca-server-service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca + app.kubernetes.io/version: v0.5.0 + name: parca + namespace: parca +spec: + ports: + - name: http + port: 7070 + targetPort: 7070 + selector: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca diff --git a/deploy/tilt/parca-server-serviceAccount.yaml b/deploy/tilt/parca-server-serviceAccount.yaml new file mode 100644 index 0000000000..27436b0b15 --- /dev/null +++ b/deploy/tilt/parca-server-serviceAccount.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: observability + app.kubernetes.io/instance: parca + app.kubernetes.io/name: parca + app.kubernetes.io/version: v0.5.0 + name: parca + namespace: parca diff --git a/scripts/local-dev.sh b/scripts/local-dev.sh new file mode 100644 index 0000000000..2640802d4d --- /dev/null +++ b/scripts/local-dev.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +################################################################################ +# +# This script is meant to be run from the root of this project with the Makefile +# +################################################################################ + +set -euo pipefail + +# Creates a local minikube cluster, and deploys the dev env into the cluster +function up() { + # Spin up local cluster if one isn't running + if minikube status -p parca-agent; then + echo "----------------------------------------------------------" + echo "Dev cluster already running. Skipping minikube cluster creation" + echo "----------------------------------------------------------" + else + ctlptl create registry ctlptl-registry || echo 'Registry already exists' + # kvm2, hyperkit, hyperv, vmwarefusion, virtualbox, vmware, xhyve + minikube start -p parca-agent \ + --driver=virtualbox \ + --kubernetes-version=v1.22.3 \ + --cpus=12 \ + --memory=40gb \ + --disk-size=120gb \ + --docker-opt dns=8.8.8.8 \ + --docker-opt default-ulimit=memlock=9223372036854775807:9223372036854775807 + fi + + # Deploy all services into the cluster + deploy + + echo "Now run \"tilt up\" to start developing!" +} + +# Tears down a local minikube cluster +function down() { + minikube delete -p parca-agent +} + +# Deploys the dev env into the minikube cluster +function deploy() { + # Deploy all generated manifests + kubectl apply -R -f ./deploy/tilt +}