From 4af666685375105b131d6bbd040c1d7cab4b0a5d Mon Sep 17 00:00:00 2001 From: Derek Brown Date: Mon, 25 Sep 2023 11:56:11 -0700 Subject: [PATCH 1/7] feat: add helm chart Signed-off-by: Derek Brown --- .github/workflows/helm-publish.yaml | 24 +++ .github/workflows/helm-test.yaml | 74 ++++++++ README.md | 17 +- Tiltfile | 30 ++++ charts/goldpinger/.helmignore | 23 +++ charts/goldpinger/Chart.yaml | 8 + charts/goldpinger/templates/_helpers.tpl | 62 +++++++ charts/goldpinger/templates/clusterrole.yaml | 12 ++ .../templates/clusterrolebinding.yaml | 16 ++ charts/goldpinger/templates/configmap.yaml | 8 + charts/goldpinger/templates/daemonset.yaml | 103 ++++++++++++ charts/goldpinger/templates/ingress.yaml | 61 +++++++ .../goldpinger/templates/prometheusrule.yaml | 19 +++ charts/goldpinger/templates/role.yaml | 20 +++ charts/goldpinger/templates/rolebinding.yaml | 16 ++ charts/goldpinger/templates/service.yaml | 26 +++ .../goldpinger/templates/serviceaccount.yaml | 8 + .../goldpinger/templates/servicemonitor.yaml | 28 +++ charts/goldpinger/values.yaml | 159 ++++++++++++++++++ extras/check_reachability.sh | 84 +++++++++ kind.yaml | 18 ++ 21 files changed, 813 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/helm-publish.yaml create mode 100644 .github/workflows/helm-test.yaml create mode 100644 Tiltfile create mode 100644 charts/goldpinger/.helmignore create mode 100644 charts/goldpinger/Chart.yaml create mode 100644 charts/goldpinger/templates/_helpers.tpl create mode 100644 charts/goldpinger/templates/clusterrole.yaml create mode 100644 charts/goldpinger/templates/clusterrolebinding.yaml create mode 100644 charts/goldpinger/templates/configmap.yaml create mode 100644 charts/goldpinger/templates/daemonset.yaml create mode 100644 charts/goldpinger/templates/ingress.yaml create mode 100644 charts/goldpinger/templates/prometheusrule.yaml create mode 100644 charts/goldpinger/templates/role.yaml create mode 100644 charts/goldpinger/templates/rolebinding.yaml create mode 100644 charts/goldpinger/templates/service.yaml create mode 100644 charts/goldpinger/templates/serviceaccount.yaml create mode 100644 charts/goldpinger/templates/servicemonitor.yaml create mode 100644 charts/goldpinger/values.yaml create mode 100755 extras/check_reachability.sh create mode 100644 kind.yaml diff --git a/.github/workflows/helm-publish.yaml b/.github/workflows/helm-publish.yaml new file mode 100644 index 0000000..bf67114 --- /dev/null +++ b/.github/workflows/helm-publish.yaml @@ -0,0 +1,24 @@ +name: Helm Publish +on: + push: + branches: + - master +jobs: + helm_publish: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.6.0 + with: + charts_dir: helm + token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/helm-test.yaml b/.github/workflows/helm-test.yaml new file mode 100644 index 0000000..971a461 --- /dev/null +++ b/.github/workflows/helm-test.yaml @@ -0,0 +1,74 @@ +name: Helm Test +on: + pull_request: +jobs: + helm_test: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.16 + + - name: Install Tools + shell: bash + id: tool-versions + env: + TILT_TOOL_CTLPTL_VERSION: "0.8.21" + TILT_TOOL_KIND_VERSION: "0.20.0" + TILT_TOOL_KUBECTL_VERSION: "1.27.3" + TILT_TOOL_HELM_VERSION: "3.12.2" + TILT_TOOL_TILT_VERSION: "0.33.3" + run: | + + # Create Tools Directory + TOOLS_DIR=/opt/helm_tools + mkdir -p "${TOOLS_DIR}" + + # Download ctlptl + echo "Downloading ctlptl" + curl -fsSL https://github.com/tilt-dev/ctlptl/releases/download/v${TILT_TOOL_CTLPTL_VERSION}/ctlptl.${TILT_TOOL_CTLPTL_VERSION}.linux.x86_64.tar.gz | sudo tar -xzv -C "${TOOLS_DIR}" ctlptl + + # Download kind + echo "Downloading kind" + curl -fsSL https://kind.sigs.k8s.io/dl/v${TILT_TOOL_KIND_VERSION}/kind-linux-amd64 -o "${TOOLS_DIR}/kind" + + # Download kubectl + echo "Downloading kubectl" + curl -fsSL https://dl.k8s.io/release/v${TILT_TOOL_KUBECTL_VERSION}/bin/linux/amd64/kubectl -o "${TOOLS_DIR}/kubectl" + + # Download helm + echo "Downloading helm" + curl -fsSL https://get.helm.sh/helm-v${TILT_TOOL_HELM_VERSION}-linux-amd64.tar.gz | tar -xzv -C "${TOOLS_DIR}" --strip-components=1 linux-amd64/helm + + # Download tilt + echo "Downloading tilt" + curl -fsSL https://github.com/tilt-dev/tilt/releases/download/v${TILT_TOOL_TILT_VERSION}/tilt.${TILT_TOOL_TILT_VERSION}.linux.x86_64.tar.gz | tar -xzv -C "${TOOLS_DIR}" tilt + + # Make the binaries runnable + echo "Making binaries executable" + sudo chmod -R +x "${TOOLS_DIR}" + + # Add tools to path + echo "PATH=${PATH}:${TOOLS_DIR}" >> $GITHUB_ENV + + - name: Start Kind Cluster + shell: bash + run: | + ctlptl apply -f kind.yaml + + - name: Run Tilt Tests + shell: bash + run: | + tilt ci --debug --output-snapshot-on-exit=/tmp/tilt-snapshot.json + + - name: Upload Tilt Snapshot + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: tilt-snapshot + path: | + /tmp/tilt-snapshot.json diff --git a/README.md b/README.md index 985c41a..f9d0328 100644 --- a/README.md +++ b/README.md @@ -101,14 +101,25 @@ docker push $(namespace="docker.io/myhandle/" make version) ``` ## Installation - `Goldpinger` works by asking `Kubernetes` for pods with particular labels (`app=goldpinger`). While you can deploy `Goldpinger` in a variety of ways, it works very nicely as a `DaemonSet` out of the box. -### Authentication with Kubernetes API +### Helm Installation +Goldpinger can be installed via [Helm](https://helm.sh/) using the following: + +``` +helm repo add goldpinger https://bloomberg.github.io/goldpinger +helm repo update +helm install goldpinger goldpinger/goldpinger +``` + +### Manual Installation +`Goldpinger` can be installed manually via configuration similar to the following: + +#### Authentication with Kubernetes API `Goldpinger` supports using a `kubeconfig` (specify with `--kubeconfig-path`) or service accounts. -### Example YAML +#### Example YAML Here's an example of what you can do (using the in-cluster authentication to `Kubernetes` apiserver). diff --git a/Tiltfile b/Tiltfile new file mode 100644 index 0000000..43ac1d1 --- /dev/null +++ b/Tiltfile @@ -0,0 +1,30 @@ +# -*- mode: bazel-starlark -*- + +# Build the image +docker_build('goldpinger-local', '.') + +# Deploy with Helm +k8s_yaml( + helm( + 'charts/goldpinger', + set = [ + # Set the image to the one built by Tilt + 'image.repository=goldpinger-local', + ], + ) +) + +# Track Goldpinger Resource +k8s_resource( + 'chart-goldpinger', + port_forwards = [8080], +) + +# Validate that all 2 nodes can talk to eachother +local_resource( + 'check_reachability', + cmd='./extras/check_reachability.sh 2', + resource_deps = [ + 'chart-goldpinger', + ], +) diff --git a/charts/goldpinger/.helmignore b/charts/goldpinger/.helmignore new file mode 100644 index 0000000..825c007 --- /dev/null +++ b/charts/goldpinger/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj + +OWNERS diff --git a/charts/goldpinger/Chart.yaml b/charts/goldpinger/Chart.yaml new file mode 100644 index 0000000..94a7ef9 --- /dev/null +++ b/charts/goldpinger/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +name: goldpinger +appVersion: "v3.7.0" +version: 1.0.0 +description: Goldpinger is a tool to help debug, troublshoot and visualize network connectivity and slowness issues. +home: https://github.com/bloomberg/goldpinger +sources: + - https://github.com/bloomberg/goldpinger diff --git a/charts/goldpinger/templates/_helpers.tpl b/charts/goldpinger/templates/_helpers.tpl new file mode 100644 index 0000000..c9a0eb6 --- /dev/null +++ b/charts/goldpinger/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "goldpinger.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "goldpinger.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "goldpinger.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "goldpinger.labels" -}} +helm.sh/chart: {{ include "goldpinger.chart" . }} +{{ include "goldpinger.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "goldpinger.selectorLabels" -}} +app.kubernetes.io/name: {{ include "goldpinger.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "goldpinger.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "goldpinger.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/goldpinger/templates/clusterrole.yaml b/charts/goldpinger/templates/clusterrole.yaml new file mode 100644 index 0000000..8404c64 --- /dev/null +++ b/charts/goldpinger/templates/clusterrole.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.rbac.create .Values.rbac.clusterscoped }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "goldpinger.fullname" . }}-clusterrole + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["list"] +{{- end }} diff --git a/charts/goldpinger/templates/clusterrolebinding.yaml b/charts/goldpinger/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..3ba52c3 --- /dev/null +++ b/charts/goldpinger/templates/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.rbac.create .Values.rbac.clusterscoped }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "goldpinger.fullname" . }}-clusterrolebinding + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "goldpinger.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "goldpinger.fullname" . }}-clusterrole + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/charts/goldpinger/templates/configmap.yaml b/charts/goldpinger/templates/configmap.yaml new file mode 100644 index 0000000..a0a618b --- /dev/null +++ b/charts/goldpinger/templates/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "goldpinger.fullname" . }}-zap + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +data: + zap.json: {{ .Values.goldpinger.zapConfig | toJson }} diff --git a/charts/goldpinger/templates/daemonset.yaml b/charts/goldpinger/templates/daemonset.yaml new file mode 100644 index 0000000..54034a6 --- /dev/null +++ b/charts/goldpinger/templates/daemonset.yaml @@ -0,0 +1,103 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "goldpinger.fullname" . }} + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +spec: + {{- with .Values.updateStrategy }} + updateStrategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "goldpinger.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{ toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "goldpinger.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{ toYaml . | nindent 8 }} + {{- end }} + spec: + priorityClassName: {{ .Values.priorityClassName }} + serviceAccountName: {{ include "goldpinger.serviceAccountName" . }} + {{- if .Values.image.pullSecrets }} + imagePullSecrets: + {{- range .Values.image.pullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + containers: + - name: goldpinger-daemon + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + volumeMounts: + - name: zap + mountPath: /config + env: + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: HOST + value: "0.0.0.0" + - name: PORT + value: "{{ .Values.goldpinger.port }}" + - name: LABEL_SELECTOR + value: "app.kubernetes.io/name={{ include "goldpinger.name" . }}" + {{- if .Values.extraEnv -}} + {{ toYaml .Values.extraEnv | nindent 12 }} + {{- end }} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.goldpinger.port }} + protocol: TCP + {{- range $k := .Values.extraEnv }} + {{- if and (eq $k.name "USE_HOST_IP") (eq $k.value "true") }} + hostPort: {{ $.Values.goldpinger.port }} + {{- end }} + {{- end }} + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: zap + configMap: + name: {{ include "goldpinger.fullname" . }}-zap + {{- range $k := .Values.extraEnv }} + {{- if and (eq $k.name "USE_HOST_IP") (eq $k.value "true") }} + hostNetwork: true + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/goldpinger/templates/ingress.yaml b/charts/goldpinger/templates/ingress.yaml new file mode 100644 index 0000000..899b2c5 --- /dev/null +++ b/charts/goldpinger/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "goldpinger.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "goldpinger.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/goldpinger/templates/prometheusrule.yaml b/charts/goldpinger/templates/prometheusrule.yaml new file mode 100644 index 0000000..54a840f --- /dev/null +++ b/charts/goldpinger/templates/prometheusrule.yaml @@ -0,0 +1,19 @@ +{{- if .Values.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "goldpinger.fullname" . }} + {{- if .Values.prometheusRule.namespace }} + namespace: {{ .Values.prometheusRule.namespace }} + {{- else }} + namespace: {{ .Release.Namespace | quote }} + {{- end }} + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +spec: + {{- with .Values.prometheusRule.rules }} + groups: + - name: {{ template "goldpinger.name" $ }} + rules: {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/goldpinger/templates/role.yaml b/charts/goldpinger/templates/role.yaml new file mode 100644 index 0000000..0b85f3f --- /dev/null +++ b/charts/goldpinger/templates/role.yaml @@ -0,0 +1,20 @@ +{{- if or .Values.podSecurityPolicy.enabled (not .Values.rbac.clusterscoped) }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "goldpinger.fullname" . }}-pod-security-policy + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +rules: +{{- if not .Values.rbac.clusterscoped }} + - apiGroups: [""] + resources: ["pods"] + verbs: ["list"] +{{- end }} +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: ["extensions"] + resources: ["podsecuritypolicies"] + resourceNames: [{{ .Values.podSecurityPolicy.policyName | quote }}] + verbs: ["use"] +{{- end }} +{{- end }} diff --git a/charts/goldpinger/templates/rolebinding.yaml b/charts/goldpinger/templates/rolebinding.yaml new file mode 100644 index 0000000..34c0bc4 --- /dev/null +++ b/charts/goldpinger/templates/rolebinding.yaml @@ -0,0 +1,16 @@ +{{- if or .Values.podSecurityPolicy.enabled (not .Values.rbac.clusterscoped) }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "goldpinger.fullname" . }}-pod-security-policy + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +roleRef: + kind: Role + name: {{ include "goldpinger.fullname" . }}-pod-security-policy + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ include "goldpinger.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/goldpinger/templates/service.yaml b/charts/goldpinger/templates/service.yaml new file mode 100644 index 0000000..43a3e85 --- /dev/null +++ b/charts/goldpinger/templates/service.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "goldpinger.fullname" . }} + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +{{- with .Values.service.labels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.goldpinger.port }} + protocol: TCP + name: http + selector: + {{- include "goldpinger.selectorLabels" . | nindent 4 }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} diff --git a/charts/goldpinger/templates/serviceaccount.yaml b/charts/goldpinger/templates/serviceaccount.yaml new file mode 100644 index 0000000..5556433 --- /dev/null +++ b/charts/goldpinger/templates/serviceaccount.yaml @@ -0,0 +1,8 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "goldpinger.serviceAccountName" . }} + labels: + {{- include "goldpinger.labels" . | nindent 4 }} +{{- end }} diff --git a/charts/goldpinger/templates/servicemonitor.yaml b/charts/goldpinger/templates/servicemonitor.yaml new file mode 100644 index 0000000..95bbad6 --- /dev/null +++ b/charts/goldpinger/templates/servicemonitor.yaml @@ -0,0 +1,28 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "goldpinger.fullname" . }} + {{- if .Values.serviceMonitor.namespace }} + namespace: {{ .Values.serviceMonitor.namespace }} + {{- end }} + labels: + {{- include "goldpinger.labels" . | nindent 4 }} + {{- range $key, $value := .Values.serviceMonitor.selector }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + endpoints: + - port: http + interval: {{ .Values.serviceMonitor.interval }} + {{- if .Values.serviceMonitor.honorLabels }} + honorLabels: true + {{- end }} + jobLabel: name + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "goldpinger.selectorLabels" . | nindent 6 }} +{{- end -}} diff --git a/charts/goldpinger/values.yaml b/charts/goldpinger/values.yaml new file mode 100644 index 0000000..a721215 --- /dev/null +++ b/charts/goldpinger/values.yaml @@ -0,0 +1,159 @@ +# Default values for goldpinger. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +image: + repository: bloomberg/goldpinger + # Overrides the image tag whose default is the chart appVersion. + tag: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + +rbac: + create: true + clusterscoped: true + +serviceAccount: + create: true + name: + +goldpinger: + port: 8080 + zapConfig: | + { + "level": "info", + "encoding": "json", + "outputPaths": [ + "stdout" + ], + "errorOutputPaths": [ + "stderr" + ], + "initialFields": { + }, + "encoderConfig": { + "messageKey": "message", + "levelKey": "level", + "levelEncoder": "lowercase", + "timeKey": "ts", + "timeEncoder": "ISO8601", + "callerKey": "caller", + "callerEncoder": "Short" + } + } + +extraEnv: [] + +service: + type: ClusterIP + port: 8081 + annotations: {} + labels: {} + loadBalancerSourceRanges: {} + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +## Set a priorityClassName for the pod. If left blank a default priority will be set. +priorityClassName: + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +podAnnotations: {} + +podLabels: {} + +updateStrategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxUnavailable: 1 + +## Node labels for pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +## Tolerations for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Affinity for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Enable this if pod security policy enabled in your cluster +## It will bind ServiceAccount with unrestricted podSecurityPolicy +## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +podSecurityPolicy: + enabled: false + policyName: unrestricted-psp + +## Set security context of the goldpinger container +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +containerSecurityContext: {} +# allowPrivilegeEscalation: false +# privileged: false +# readOnlyRootFilesystem: true + +## Set security context of the pod +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +podSecurityContext: {} +# runAsNonRoot: true +# runAsUser: 1001 +# runAsGroup: 2001 +# seccompProfile: +# type: RuntimeDefault + +serviceMonitor: + enabled: false + selector: + prometheus: "kube-prometheus" + # namespace: monitoring + interval: 30s + # honorLabels: true + +## Custom PrometheusRule to be defined +## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions +prometheusRule: + enabled: false + rules: + - alert: goldpinger_nodes_unhealthy + expr: | + sum(goldpinger_nodes_health_total{job="{{ template "goldpinger.fullname" . }}", status="unhealthy"}) + BY (instance, goldpinger_instance) > 0 + for: 5m + annotations: + description: | + Goldpinger instance {{ "{{ $labels.goldpinger_instance }}" }} has been reporting unhealthy nodes for at least 5 minutes. + summary: Instance {{ "{{ $labels.instance }}" }} down + labels: + severity: warning diff --git a/extras/check_reachability.sh b/extras/check_reachability.sh new file mode 100755 index 0000000..b087cac --- /dev/null +++ b/extras/check_reachability.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# This is a simple script, used in the Tilt GitHub Action +# to validate that all worker nodes can inter-communicate. + +function print_help() { + echo "Usage: $0 [EXPECTED_HOST_COUNT]" + echo "Arguments:" + echo " EXPECTED_HOST_COUNT: The number of expected hosts in the Goldpinger output." + echo "Examples:" + echo " $0 2" +} + +if [ "$#" -ne 1 ]; then + echo "Error: Invalid number of arguments." + print_help + exit 1 +fi + +if ! [[ $1 =~ ^[0-9]+$ ]]; then + echo "Error: EXPECTED_HOST_COUNT must be a number." + print_help + exit 1 +fi + +expected_host_count=$1 +goldpinger_output="" +retry_count=0 +host_count=0 + +while :; do + if [ "$retry_count" -ge 20 ]; then + echo "Error: Failed to fetch Goldpinger output after 10 attempts." + exit 1 + fi + + echo "Sleeping for 8s..." + let retry_count++ + sleep 8 + + echo "Attempt $((retry_count)) to fetch Goldpinger output." + goldpinger_output=$(curl -s http://localhost:8080/check_all) + echo "Goldpinger output: $goldpinger_output" + + if [ "$goldpinger_output" == "null" ] || [ -z "$goldpinger_output" ]; then + echo "Goldpinger output is null or empty, retrying..." + continue + fi + + host_count=$(echo "$goldpinger_output" | jq '.hosts | length') + if [ "$host_count" -ne "$expected_host_count" ]; then + echo "Goldpinger has not identified all hosts, retrying..." + continue + fi + + for host in $(echo $goldpinger_output | jq -r '.responses | keys[]'); do + checksForPod=$(echo "$goldpinger_output" | jq -r --arg host "$host" '.responses[$host].response.podResults | length') + if [ "$checksForPod" -ne "$expected_host_count" ]; then + echo "Check for $host is not OK, retrying..." + continue 2 + fi + done + + break +done + +all_hosts_can_talk=true +for host in $(echo $goldpinger_output | jq -r '.responses | keys[]'); do + for target in $(echo $goldpinger_output | jq -r --arg host $host '.responses[$host].response.podResults | keys[]'); do + ok=$(echo $goldpinger_output | jq -r --arg host $host --arg target $target '.responses[$host].response.podResults[$target].OK') + if [ "$ok" != "true" ]; then + all_hosts_can_talk=false + break 2 + fi + done +done + +if [[ $host_count -eq $expected_host_count ]] && [[ $all_hosts_can_talk == "true" ]]; then + echo "Validation successful. There are $expected_host_count hosts and they can talk to each other." +else + echo "Validation failed. Expected $expected_host_count hosts but found $host_count, or not all hosts can talk to each other." + echo "Goldpinger Output: $goldpinger_output" + exit 1 +fi diff --git a/kind.yaml b/kind.yaml new file mode 100644 index 0000000..1e2507f --- /dev/null +++ b/kind.yaml @@ -0,0 +1,18 @@ +apiVersion: ctlptl.dev/v1alpha1 +kind: Registry +name: ctlptl-registry +port: 20021 +--- +apiVersion: ctlptl.dev/v1alpha1 +kind: Cluster +product: kind +registry: ctlptl-registry +kubernetesVersion: v1.27.3 +kindV1Alpha4Cluster: + name: goldpinger-test + nodes: + - role: control-plane + - role: worker + - role: worker + networking: + apiServerPort: 30022 From aed183926e9aa2d17a137313c634929cbedcc497 Mon Sep 17 00:00:00 2001 From: Sachin Kamboj Date: Tue, 14 May 2024 08:36:28 -0400 Subject: [PATCH 2/7] Update the versions to the latest Signed-off-by: Sachin Kamboj --- .github/workflows/helm-test.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/helm-test.yaml b/.github/workflows/helm-test.yaml index 971a461..2fcf894 100644 --- a/.github/workflows/helm-test.yaml +++ b/.github/workflows/helm-test.yaml @@ -1,6 +1,6 @@ name: Helm Test on: - pull_request: + pull_request: jobs: helm_test: runs-on: ubuntu-latest @@ -11,23 +11,23 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.22 - name: Install Tools shell: bash id: tool-versions env: - TILT_TOOL_CTLPTL_VERSION: "0.8.21" - TILT_TOOL_KIND_VERSION: "0.20.0" - TILT_TOOL_KUBECTL_VERSION: "1.27.3" - TILT_TOOL_HELM_VERSION: "3.12.2" - TILT_TOOL_TILT_VERSION: "0.33.3" + TILT_TOOL_CTLPTL_VERSION: "0.8.28" + TILT_TOOL_KIND_VERSION: "0.23.0" + TILT_TOOL_KUBECTL_VERSION: "1.30.0" + TILT_TOOL_HELM_VERSION: "3.14.4" + TILT_TOOL_TILT_VERSION: "0.33.13" run: | # Create Tools Directory TOOLS_DIR=/opt/helm_tools mkdir -p "${TOOLS_DIR}" - + # Download ctlptl echo "Downloading ctlptl" curl -fsSL https://github.com/tilt-dev/ctlptl/releases/download/v${TILT_TOOL_CTLPTL_VERSION}/ctlptl.${TILT_TOOL_CTLPTL_VERSION}.linux.x86_64.tar.gz | sudo tar -xzv -C "${TOOLS_DIR}" ctlptl From a1a481ffe90a8018a27cdd582cf40c8c4450da77 Mon Sep 17 00:00:00 2001 From: Sachin Kamboj Date: Tue, 14 May 2024 08:42:55 -0400 Subject: [PATCH 3/7] Update to kube 1.30 for the kind cluster as well Signed-off-by: Sachin Kamboj --- kind.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kind.yaml b/kind.yaml index 1e2507f..1678203 100644 --- a/kind.yaml +++ b/kind.yaml @@ -7,7 +7,7 @@ apiVersion: ctlptl.dev/v1alpha1 kind: Cluster product: kind registry: ctlptl-registry -kubernetesVersion: v1.27.3 +kubernetesVersion: v1.30.0 kindV1Alpha4Cluster: name: goldpinger-test nodes: From f514bac57ca5e1005a0853058bc430624f21b909 Mon Sep 17 00:00:00 2001 From: Sachin Kamboj Date: Tue, 14 May 2024 10:01:00 -0400 Subject: [PATCH 4/7] Remove kubernetes version to use the default image Signed-off-by: Sachin Kamboj --- charts/goldpinger/Chart.yaml | 2 +- kind.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/charts/goldpinger/Chart.yaml b/charts/goldpinger/Chart.yaml index 94a7ef9..da719fb 100644 --- a/charts/goldpinger/Chart.yaml +++ b/charts/goldpinger/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v1 name: goldpinger -appVersion: "v3.7.0" +appVersion: "v3.10.1" version: 1.0.0 description: Goldpinger is a tool to help debug, troublshoot and visualize network connectivity and slowness issues. home: https://github.com/bloomberg/goldpinger diff --git a/kind.yaml b/kind.yaml index 1678203..fbdb2d7 100644 --- a/kind.yaml +++ b/kind.yaml @@ -7,7 +7,6 @@ apiVersion: ctlptl.dev/v1alpha1 kind: Cluster product: kind registry: ctlptl-registry -kubernetesVersion: v1.30.0 kindV1Alpha4Cluster: name: goldpinger-test nodes: From 6a3794f3d62e0f88f61d69cb557c65eb422766df Mon Sep 17 00:00:00 2001 From: Sachin Kamboj Date: Tue, 14 May 2024 10:05:07 -0400 Subject: [PATCH 5/7] Secure by default - set the security context and pod security context Signed-off-by: Sachin Kamboj --- charts/goldpinger/values.yaml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/charts/goldpinger/values.yaml b/charts/goldpinger/values.yaml index a721215..b0cd8d2 100644 --- a/charts/goldpinger/values.yaml +++ b/charts/goldpinger/values.yaml @@ -119,19 +119,22 @@ podSecurityPolicy: ## Set security context of the goldpinger container ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -containerSecurityContext: {} -# allowPrivilegeEscalation: false -# privileged: false -# readOnlyRootFilesystem: true +containerSecurityContext: + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true ## Set security context of the pod ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -podSecurityContext: {} -# runAsNonRoot: true -# runAsUser: 1001 -# runAsGroup: 2001 -# seccompProfile: -# type: RuntimeDefault +podSecurityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 2000 + seccompProfile: + type: RuntimeDefault serviceMonitor: enabled: false From b8035264edb7f6043ad7571aecfcd568749f4de5 Mon Sep 17 00:00:00 2001 From: Sachin Kamboj Date: Tue, 14 May 2024 10:16:45 -0400 Subject: [PATCH 6/7] Update the publishing workflow Signed-off-by: Sachin Kamboj --- .github/workflows/helm-publish.yaml | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/helm-publish.yaml b/.github/workflows/helm-publish.yaml index bf67114..226acae 100644 --- a/.github/workflows/helm-publish.yaml +++ b/.github/workflows/helm-publish.yaml @@ -2,23 +2,32 @@ name: Helm Publish on: push: branches: - - master + - master + jobs: helm_publish: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: - fetch-depth: 0 - + fetch-depth: 0 + - name: Configure Git run: | git config user.name "$GITHUB_ACTOR" git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + - name: Install Helm + uses: azure/setup-helm@v4 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + - name: Run chart-releaser uses: helm/chart-releaser-action@v1.6.0 - with: - charts_dir: helm - token: "${{ secrets.GITHUB_TOKEN }}" + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" From a909e03de9f8d3eb1f2c31a9fd95126187e68a55 Mon Sep 17 00:00:00 2001 From: Sachin Kamboj Date: Tue, 14 May 2024 10:33:36 -0400 Subject: [PATCH 7/7] The appVersion should not have a v Signed-off-by: Sachin Kamboj --- charts/goldpinger/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/goldpinger/Chart.yaml b/charts/goldpinger/Chart.yaml index da719fb..733592b 100644 --- a/charts/goldpinger/Chart.yaml +++ b/charts/goldpinger/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v1 name: goldpinger -appVersion: "v3.10.1" +appVersion: "3.10.1" version: 1.0.0 description: Goldpinger is a tool to help debug, troublshoot and visualize network connectivity and slowness issues. home: https://github.com/bloomberg/goldpinger