diff --git a/charts/_templates.gotmpl b/charts/_templates.gotmpl index c040322c..919ed349 100644 --- a/charts/_templates.gotmpl +++ b/charts/_templates.gotmpl @@ -9,7 +9,7 @@ R and Python packages that Data Scientists need to create and share data product Data Scientists use [RStudio Workbench](https://www.rstudio.com/products/workbench/) to analyze data and create data products using R and Python. {{- else if eq .Name "posit-chronicle" -}} -IT Administrators and Business Users use [Posit Chronicle](https://www.rstudio.com/products/chronicle/) to aggregate and monitor +IT Administrators and Business Users use Posit Chronicle](https://www.rstudio.com/chronicle/) to aggregate and monitor posit product usage. {{- end -}} {{- end }} diff --git a/charts/posit-chronicle/Chart.yaml b/charts/posit-chronicle/Chart.yaml index 7604481e..0f808817 100644 --- a/charts/posit-chronicle/Chart.yaml +++ b/charts/posit-chronicle/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -name: chronicle +name: posit-chronicle description: Helm chart for the Chronicle Server version: 0.1.0 appVersion: 2023.11.0 diff --git a/charts/posit-chronicle/LICENSE b/charts/posit-chronicle/LICENSE index 37860924..e4c8f535 100644 --- a/charts/posit-chronicle/LICENSE +++ b/charts/posit-chronicle/LICENSE @@ -1,6 +1,6 @@ # MIT License -Copyright (c) 2023 Posit PBC +Copyright (c) 2023 Posit Software PBC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/charts/posit-chronicle/Makefile b/charts/posit-chronicle/Makefile index 27be6352..64cf85ed 100644 --- a/charts/posit-chronicle/Makefile +++ b/charts/posit-chronicle/Makefile @@ -1,9 +1,7 @@ lint: helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/empty-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/simple-values.yaml . + helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/complex-values.yaml . template: - helm template -f ci/simple-values.yaml . - -template-debug: - helm template -f ci/simple-values.yaml --debug . + helm template -f ci/complex-values.yaml . --debug diff --git a/charts/posit-chronicle/NEWS.md b/charts/posit-chronicle/NEWS.md index 9d2a212f..b653dcac 100644 --- a/charts/posit-chronicle/NEWS.md +++ b/charts/posit-chronicle/NEWS.md @@ -1,4 +1,5 @@ # 0.1.0 - Initial release -- Migrated from a private repo, and integrated with rstudio helm shared libraries \ No newline at end of file +- Migrated from a private repo, and integrated with rstudio helm shared libraries +- Add ci components and starting documentation diff --git a/charts/posit-chronicle/README.md b/charts/posit-chronicle/README.md new file mode 100644 index 00000000..aa25fc87 --- /dev/null +++ b/charts/posit-chronicle/README.md @@ -0,0 +1,204 @@ +# Posit Chronicle + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![AppVersion: 2023.11.0](https://img.shields.io/badge/AppVersion-2023.11.0-informational?style=flat-square) + +#### _Helm chart for the Chronicle Server_ + +IT Administrators and Business Users use Posit Chronicle](https://docs.posit.co/chronicle) to aggregate and monitor +posit product usage. + +## For Production + +To ensure a stable production deployment, please: + +* Ensure you "pin" the version of the Helm chart that you are using. You can do + this using the `helm dependency` command and the associated "Chart.lock" files + or the `--version` flag. **IMPORTANT: This protects you from breaking changes** +* Before upgrading, to avoid breaking changes, use `helm diff upgrade` to check + for breaking changes +* Pay close attention to [`NEWS.md`](./NEWS.md) for updates on breaking + changes, as well as documentation below on how to use the chart + +## Installing the Chart + +To install the chart with the release name `my-release` at version 0.1.0: + +```bash +helm repo add rstudio https://helm.rstudio.com +helm upgrade --install my-release rstudio/posit-chronicle --version=0.1.0 +``` + +To explore other chart versions, take a look at: +``` +helm search repo rstudio/posit-chronicle -l +``` + +## Usage + +The Chronicle chart is meant to be used in tandem with other workbench and connect instances. +To enable the chronicle agent, additional values will have to be passed to your +workbench and connect values. + +Here's some example agent helm values to run the agent sidecar in workbench: + +```yaml +pod: + ... + sidecar: + - name: chronicle-agent + image: posit-chronicle:latest + volumeMounts: + - name: CHRONICLE_PRODUCT_CLUSTER_ID + value: "posit-cluster-1" + - name: logs + mountPath: "/var/lib/rstudio-server/audit" + env: + - name: CHRONICLE_SERVER_ADDRESS + value: "http://chronicle-server.default.svc.cluster.local" +... +``` + +And here's some example agent helm values for connect, where we utilize an api key stored as a k8s secret +to scrape the connect rest server: + +```yaml +pod: + ... + sidecar: + - name: chronicle-agent + image: posit-chronicle:latest + env: + - name: CHRONICLE_PRODUCT_CLUSTER_ID + value: "posit-cluster-1" + - name: CHRONICLE_SERVER_ADDRESS + value: "http://chronicle-server.default.svc.cluster.local" + - name: CONNECT_API_KEY + valueFrom: + secretKeyRef: + name: connect + key: apikey +``` + +Note that it will be up to the user to provision that connect api key Kubernetes secret. + +## Storage Configuration + +Chronicle can be configured to store its data in a local kubernetes volime, in S3, +or in both. + +The default configuration uses a local volume, which is suitable if you'd like to +access and analyze the data within your cluster: + +``` yaml +config: + localStorage: + enabled: true + location: "./chronicle-data" + retentionPeriod: "30d" +``` + +RetentionPeriod accepts a duration string input. 0 implies infinite retention, disabling file expiration. +For example: +1s for 1 second, 5m for 5 minutes, 12h for 12 hours, 7d for one week, 365d for one year, 0 for unbound retention. +Units shorter than seconds or longer than days, such as milliseconds and weeks, are not supported. + +You can disable local storage by setting `localStorage.enabled` to `false`, and you can enable S3 +storage by setting `S3Storage.enabled` to `true`. Enabling both is also acceptable, +and the server will store to both places. When using S3, you must also set the `S3Storage.Bucket` +parameter, like so: + +``` yaml +config: + s3Storage: + enabled: true + bucket: "posit-chronicle" + prefix: "" + profile: "" + region: "us-east-2" +``` + +If you are running on EKS, we strongly suggest using [IAM Roles for Service +Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) +to manage the credentials needed to access S3. In this scenario, once you have +[created an IAM +role](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html), +you can use this role as an annotation on the existing Service Account: + +``` yaml +serviceaccount: + enabled: false + # -- Additional annotations to add to the chronicle-server serviceaccount + annotations: { + eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here + } + # -- Additional labels to add to the chronicle-server serviceaccount + labels: {} +``` + +If you are unable to use IAM Roles for Service Accounts, there are any number of +alternatives for injecting AWS credentials into a container. As a fallback, the +s3 storage config allows specifying a profile: + +``` yaml +config: + s3Storage: + enabled: true + bucket: "posit-chronicle" + prefix: "" + profile: "my-aws-account" + region: "us-east-2" +``` + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| config.http.listen | string | `":5252"` | | +| config.https.certificate | string | `""` | | +| config.https.enabled | bool | `false` | | +| config.https.key | string | `""` | | +| config.https.listen | string | `":443"` | | +| config.localStorage.enabled | bool | `true` | | +| config.localStorage.location | string | `"./chronicle-data"` | | +| config.localStorage.retentionPeriod | string | `"30d"` | | +| config.logging.serviceLog | string | `"STDOUT"` | | +| config.logging.serviceLogFormat | string | `"TEXT"` | | +| config.logging.serviceLogLevel | string | `"INFO"` | | +| config.metrics.enabled | bool | `true` | | +| config.profiling.enabled | bool | `false` | | +| config.profiling.listen | string | `":3030"` | | +| config.s3Storage.bucket | string | `"posit-chronicle"` | | +| config.s3Storage.compactionEnabled | bool | `false` | | +| config.s3Storage.enabled | bool | `false` | | +| config.s3Storage.prefix | string | `""` | | +| config.s3Storage.profile | string | `""` | | +| config.s3Storage.region | string | `"us-east-2"` | | +| config.tracing.address | string | `""` | | +| config.tracing.enabled | bool | `false` | | +| image.imagePullPolicy | string | `"Always"` | | +| image.repository | string | `"935931255537.dkr.ecr.us-east-2.amazonaws.com/chronicle"` | | +| image.tag | string | `"latest"` | | +| pod.affinity | object | `{}` | A map used verbatim as the pod's "affinity" definition | +| pod.annotations | object | `{}` | Additional annotations to add to the chronicle-server pods | +| pod.args[0] | string | `"start"` | | +| pod.args[1] | string | `"-c"` | | +| pod.args[2] | string | `"/opt/chronicle/config.gcfg"` | | +| pod.command | string | `"/chronicle"` | | +| pod.env | list | `[]` | Optional environment variables | +| pod.labels | object | `{}` | Additional labels to add to the chronicle-server pods | +| pod.nodeSelector | object | `{}` | A map used verbatim as the pod's "nodeSelector" definition | +| pod.rest.port | int | `5252` | | +| pod.tolerations | list | `[]` | An array used verbatim as the pod's "tolerations" definition | +| replicas | int | `1` | The number of replica pods to maintain for this service | +| service.rest.annotations | object | `{}` | Additional annotations to add to the chronicle-server service | +| service.rest.labels | object | `{}` | Additional labels to add to the chronicle-server service | +| service.rest.port | int | `80` | The port to use for the REST service | +| service.rest.targetPort | int | `5252` | The port to forward REST requests to on the pod. Also see pod.port | +| serviceaccount.annotations | object | `{}` | Additional annotations to add to the chronicle-server serviceaccount | +| serviceaccount.enabled | bool | `false` | | +| serviceaccount.labels | object | `{}` | Additional labels to add to the chronicle-server serviceaccount | +| storage.persistentVolumeSize | string | `"1Gi"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3) + diff --git a/charts/posit-chronicle/README.md.gotmpl b/charts/posit-chronicle/README.md.gotmpl index 9b70101b..9b2d38cc 100644 --- a/charts/posit-chronicle/README.md.gotmpl +++ b/charts/posit-chronicle/README.md.gotmpl @@ -8,12 +8,124 @@ {{ template "rstudio.install" . }} -# Usage +## Usage -The chronicle chart is meant to be used in tandem with other workbench and connect instances. +The Chronicle chart is meant to be used in tandem with other workbench and connect instances. To enable the chronicle agent, additional values will have to be passed to your workbench and connect values. +Here's some example agent helm values to run the agent sidecar in workbench: + +```yaml +pod: + ... + sidecar: + - name: chronicle-agent + image: posit-chronicle:latest + volumeMounts: + - name: CHRONICLE_PRODUCT_CLUSTER_ID + value: "posit-cluster-1" + - name: logs + mountPath: "/var/lib/rstudio-server/audit" + env: + - name: CHRONICLE_SERVER_ADDRESS + value: "http://chronicle-server.default.svc.cluster.local" +... +``` + +And here's some example agent helm values for connect, where we utilize an api key stored as a k8s secret +to scrape the connect rest server: + +```yaml +pod: + ... + sidecar: + - name: chronicle-agent + image: posit-chronicle:latest + env: + - name: CHRONICLE_PRODUCT_CLUSTER_ID + value: "posit-cluster-1" + - name: CHRONICLE_SERVER_ADDRESS + value: "http://chronicle-server.default.svc.cluster.local" + - name: CONNECT_API_KEY + valueFrom: + secretKeyRef: + name: connect + key: apikey +``` + +Note that it will be up to the user to provision that connect api key Kubernetes secret. + +## Storage Configuration + +Chronicle can be configured to store its data in a local kubernetes volime, in S3, +or in both. + +The default configuration uses a local volume, which is suitable if you'd like to +access and analyze the data within your cluster: + +``` yaml +config: + localStorage: + enabled: true + location: "./chronicle-data" + retentionPeriod: "30d" +``` + +RetentionPeriod accepts a duration string input. 0 implies infinite retention, disabling file expiration. +For example: +1s for 1 second, 5m for 5 minutes, 12h for 12 hours, 7d for one week, 365d for one year, 0 for unbound retention. +Units shorter than seconds or longer than days, such as milliseconds and weeks, are not supported. + + +You can disable local storage by setting `localStorage.enabled` to `false`, and you can enable S3 +storage by setting `S3Storage.enabled` to `true`. Enabling both is also acceptable, +and the server will store to both places. When using S3, you must also set the `S3Storage.Bucket` +parameter, like so: + +``` yaml +config: + s3Storage: + enabled: true + bucket: "posit-chronicle" + prefix: "" + profile: "" + region: "us-east-2" +``` + +If you are running on EKS, we strongly suggest using [IAM Roles for Service +Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) +to manage the credentials needed to access S3. In this scenario, once you have +[created an IAM +role](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html), +you can use this role as an annotation on the existing Service Account: + +``` yaml +serviceaccount: + enabled: false + # -- Additional annotations to add to the chronicle-server serviceaccount + annotations: { + eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here + } + # -- Additional labels to add to the chronicle-server serviceaccount + labels: {} +``` + +If you are unable to use IAM Roles for Service Accounts, there are any number of +alternatives for injecting AWS credentials into a container. As a fallback, the +s3 storage config allows specifying a profile: + +``` yaml +config: + s3Storage: + enabled: true + bucket: "posit-chronicle" + prefix: "" + profile: "my-aws-account" + region: "us-east-2" +``` + + {{ template "chart.valuesSection" . }} {{ template "helm-docs.versionFooter" . }} diff --git a/charts/posit-chronicle/ci/complex-values.yaml b/charts/posit-chronicle/ci/complex-values.yaml new file mode 100644 index 00000000..1b979eaa --- /dev/null +++ b/charts/posit-chronicle/ci/complex-values.yaml @@ -0,0 +1,77 @@ +image: + tag: "latest" + imagePullPolicy: "IfNotPresent" + +serviceaccount: + enabled: false + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::123123123123123:role/chronicle-serviceaccount-role + +service: + rest: + # -- The port to use for the REST service + port: 12345 + # -- The port to forward REST requests to on the pod. Also see pod.port + targetPort: 12346 + annotations: + test-annotation: test-service-annotation + labels: + test-label: test-service-label + test-label2: test-service-label2 + selectorLabels: + test-selector-label: test-service-selectorLabel + test-selector-label2: test-service-selectorLabel2 + +pod: + replicas: 4 + command: "/bash" + args: ["echo", "hello word"] + rest: + port: 12345 + # -- Optional environment variables + env: + - name: "TEST_ENV_VAR" + value: "test-value" + annotations: + test-annotation: test-service-annotation + labels: + test-label: test-service-label + test-label2: test-service-label2 + selectorLabels: + test-selector-label: test-service-selectorLabel + test-selector-label2: test-service-selectorLabel2 + +storage: + persistentVolumeSize: 10Gi + +config: + https: + # If https.enabled=true, we will ignore any http + # values and enable https in our config instead + enabled: true + listen: ":443" + key: "" + certificate: "" + localStorage: + enabled: true + location: "./chronicle-data" + retentionPeriod: "5m" + s3Storage: + enabled: true + bucket: "posit-chronicle" + prefix: "" + profile: "" + region: "us-east-2" + compactionEnabled: false + metrics: + enabled: true + profiling: + enabled: true + listen: :3030 + tracing: + enabled: true + address: "" + logging: + serviceLog: "STDOUT" + serviceLogLevel: "DEBUG" + serviceLogFormat: "JSON" diff --git a/charts/posit-chronicle/ci/simple-values.yaml b/charts/posit-chronicle/ci/simple-values.yaml index 7b3954f3..33a774ef 100644 --- a/charts/posit-chronicle/ci/simple-values.yaml +++ b/charts/posit-chronicle/ci/simple-values.yaml @@ -1,26 +1,26 @@ image: - tag: "latest" + tag: "latest" serviceaccount: - enabled: false - annotations: { - eks.amazonaws.com/role-arn: arn:aws:iam::123123123123123:role/chronicle-serviceaccount-role - } + enabled: false + annotations: { + eks.amazonaws.com/role-arn: arn:aws:iam::123123123123123:role/chronicle-serviceaccount-role + } -config: - localStorage: - enabled: true - retentionPeriod: "7d" - logging: - serviceLog: "STDOUT" - serviceLogLevel: "DEBUG" - serviceLogFormat: "JSON" - profiling: - enabled: true - s3Storage: - enabled: true - bucket: "posit-chronicle-dev" - compactionEnabled: true storage: - persistentVolumeSize: 10Gi + persistentVolumeSize: 10Gi + +config: + localStorage: + enabled: true + retentionPeriod: "7d" + logging: + serviceLog: "STDOUT" + serviceLogLevel: "DEBUG" + serviceLogFormat: "JSON" + profiling: + enabled: true + s3Storage: + enabled: true + bucket: "posit-chronicle-dev" diff --git a/charts/posit-chronicle/templates/_helpers.tpl b/charts/posit-chronicle/templates/_helpers.tpl index 4616a9f9..1552c1f5 100644 --- a/charts/posit-chronicle/templates/_helpers.tpl +++ b/charts/posit-chronicle/templates/_helpers.tpl @@ -46,10 +46,8 @@ Generate labels for various resources {{- range $key,$value := $.Values.service.labels -}} {{ $key }}: {{ $value | quote }} {{ end }} -app: chronicle-server {{- end -}} - {{/* Generate selector labels for various resources */}} @@ -62,7 +60,7 @@ app: chronicle-server {{- end -}} {{- define "posit-chronicle.service.selectorLabels" -}} -{{- range $key,$value := $.Values.serviceaccount.selectorLabels -}} +{{- range $key,$value := $.Values.service.selectorLabels -}} {{ $key }}: {{ $value | quote }} {{ end }} app: chronicle-server diff --git a/charts/posit-chronicle/templates/configmap.yaml b/charts/posit-chronicle/templates/configmap.yaml index 9a01be84..f0a36be1 100644 --- a/charts/posit-chronicle/templates/configmap.yaml +++ b/charts/posit-chronicle/templates/configmap.yaml @@ -21,7 +21,7 @@ data: Enabled = {{ .Values.config.localStorage.enabled }} Location = {{ .Values.config.localStorage.location }} RetentionPeriod = {{ .Values.config.localStorage.retentionPeriod }} - + [S3Storage] Enabled = {{ .Values.config.s3Storage.enabled }} Bucket = {{ .Values.config.s3Storage.bucket }} @@ -29,14 +29,14 @@ data: Profile = {{ .Values.config.s3Storage.profile }} Region = {{ .Values.config.s3Storage.region }} CompactionEnabled = {{ .Values.config.s3Storage.compactionEnabled }} - + [Metrics] Enabled = {{ .Values.config.metrics.enabled }} - + [Profiling] Enabled = {{ .Values.config.profiling.enabled }} Listen = {{ .Values.config.profiling.listen }} - + [Tracing] Enabled = {{ .Values.config.tracing.enabled }} Address = {{ .Values.config.tracing.address }} diff --git a/charts/posit-chronicle/templates/stateful-set.yaml b/charts/posit-chronicle/templates/stateful-set.yaml index 48060b4f..13f6dbe8 100644 --- a/charts/posit-chronicle/templates/stateful-set.yaml +++ b/charts/posit-chronicle/templates/stateful-set.yaml @@ -9,14 +9,14 @@ spec: replicas: {{ .Values.replicas }} selector: matchLabels: - {{- include "posit-chronicle.pod.selectorLabels" . | nindent 6 }} + {{- include "posit-chronicle.pod.selectorLabels" . | trim | nindent 6 }} template: metadata: labels: - {{- include "posit-chronicle.pod.labels" . | nindent 8 }} - {{- include "posit-chronicle.pod.selectorLabels" . | indent 8 }} + {{- include "posit-chronicle.service.labels" . | trim | nindent 8 }} + {{- include "posit-chronicle.service.selectorLabels" . | trim | nindent 8 }} annotations: - {{- include "posit-chronicle.pod.annotations" . | indent 8 }} + {{- include "posit-chronicle.service.annotations" . | trim | nindent 8 }} spec: {{- with .Values.pod.affinity }} affinity: @@ -37,7 +37,7 @@ spec: - name: chronicle-server image: {{ .Values.image.repository }}:{{ .Values.image.tag }} imagePullPolicy: {{ .Values.image.imagePullPolicy }} - command: + command: - {{ .Values.pod.command }} {{- if .Values.pod.args }} args: @@ -53,7 +53,7 @@ spec: mountPath: /opt/chronicle/config.gcfg subPath: server {{- if .Values.pod.env }} - env: + env: {{- toYaml .Values.pod.env | nindent 8 }} {{- end }} volumes: diff --git a/charts/posit-chronicle/templates/svc.yaml b/charts/posit-chronicle/templates/svc.yaml index 2f1b0db0..cada2581 100644 --- a/charts/posit-chronicle/templates/svc.yaml +++ b/charts/posit-chronicle/templates/svc.yaml @@ -4,13 +4,13 @@ kind: Service metadata: name: chronicle-server labels: - {{- include "posit-chronicle.service.labels" . | nindent 4 }} - {{- include "posit-chronicle.service.selectorLabels" . | indent 4 }} + {{- include "posit-chronicle.service.labels" . | trim | nindent 4 }} + {{- include "posit-chronicle.service.selectorLabels" . | trim | nindent 4 }} annotations: - {{ include "posit-chronicle.service.annotations" . | indent 4 }} + {{- include "posit-chronicle.service.annotations" . | trim | nindent 4 }} spec: selector: - {{- include "posit-chronicle.service.selectorLabels" . | indent 4 }} + {{- include "posit-chronicle.service.selectorLabels" . | trim | nindent 4 }} ports: - port: {{ .Values.service.rest.port }} targetPort: {{ .Values.service.rest.targetPort }}