From 0f5d7ea968f883ec6a09ad1f964dd62e2a2a05c2 Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Mon, 10 Jun 2024 17:00:29 +0000 Subject: [PATCH] fix: improved crd handling, version bumps of network, new HAProxy support, argocd auth fix --- admin/libhelm.sh | 17 ++- .../argo-cd/istio-authorization-policy.yaml | 2 +- .../kubezero-istio-gateway/tests/httpbin.yaml | 72 +++++++++++ .../tests/virtualservice.yaml | 15 +++ charts/kubezero-network/README.md | 44 +++++++ ...dashboards.yaml => cilium-dashboards.yaml} | 0 .../kubezero-network/haproxy-dashboards.yaml | 10 ++ ...ds.yaml => cilium-grafana-dashboards.yaml} | 0 .../templates/haproxy-grafana-dashboards.yaml | 15 +++ .../multus/crds.yaml} | 2 + charts/kubezero-network/update.sh | 3 +- charts/kubezero-network/values.yaml | 114 ++++++++++++++++++ 12 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 charts/kubezero-istio-gateway/tests/httpbin.yaml create mode 100644 charts/kubezero-istio-gateway/tests/virtualservice.yaml rename charts/kubezero-network/{dashboards.yaml => cilium-dashboards.yaml} (100%) create mode 100644 charts/kubezero-network/haproxy-dashboards.yaml rename charts/kubezero-network/templates/{grafana-dashboards.yaml => cilium-grafana-dashboards.yaml} (100%) create mode 100644 charts/kubezero-network/templates/haproxy-grafana-dashboards.yaml rename charts/kubezero-network/{crds/multus.yaml => templates/multus/crds.yaml} (97%) diff --git a/admin/libhelm.sh b/admin/libhelm.sh index 7509d3f6..0fd40be0 100644 --- a/admin/libhelm.sh +++ b/admin/libhelm.sh @@ -109,11 +109,18 @@ function delete_ns() { } -# Extract crds via helm calls and apply delta=crds only +# Extract crds via helm calls function _crds() { - helm secrets --evaluate-templates template $(chart_location $chart) -n $namespace --name-template $module $targetRevision --skip-crds --set ${module}.installCRDs=false -f $WORKDIR/values.yaml $API_VERSIONS --kube-version $KUBE_VERSION > $WORKDIR/helm-no-crds.yaml - helm secrets --evaluate-templates template $(chart_location $chart) -n $namespace --name-template $module $targetRevision --include-crds --set ${module}.installCRDs=true -f $WORKDIR/values.yaml $API_VERSIONS --kube-version $KUBE_VERSION > $WORKDIR/helm-crds.yaml - diff -e $WORKDIR/helm-no-crds.yaml $WORKDIR/helm-crds.yaml | head -n-1 | tail -n+2 > $WORKDIR/crds.yaml + helm secrets --evaluate-templates template $(chart_location $chart) -n $namespace --name-template $module $targetRevision --include-crds --set ${module}.installCRDs=true -f $WORKDIR/values.yaml $API_VERSIONS --kube-version $KUBE_VERSION $@ | python3 -c ' +#!/usr/bin/python3 +import yaml +import sys + +for manifest in yaml.safe_load_all(sys.stdin): + if manifest: + if "kind" in manifest and manifest["kind"] == "CustomResourceDefinition": + print("---") + print(yaml.dump(manifest))' > $WORKDIR/crds.yaml # Only apply if there are actually any crds if [ -s $WORKDIR/crds.yaml ]; then @@ -134,6 +141,8 @@ import sys for manifest in yaml.safe_load_all(sys.stdin): if manifest: + if "kind" in manifest and manifest["kind"] == "CustomResourceDefinition": + continue if "metadata" in manifest and "namespace" not in manifest["metadata"]: manifest["metadata"]["namespace"] = sys.argv[1] print("---") diff --git a/charts/kubezero-argo/templates/argo-cd/istio-authorization-policy.yaml b/charts/kubezero-argo/templates/argo-cd/istio-authorization-policy.yaml index 603d1dfb..5b8b2821 100644 --- a/charts/kubezero-argo/templates/argo-cd/istio-authorization-policy.yaml +++ b/charts/kubezero-argo/templates/argo-cd/istio-authorization-policy.yaml @@ -19,7 +19,7 @@ spec: {{- toYaml (index .Values "argo-cd" "istio" "ipBlocks") | nindent 8 }} to: - operation: - hosts: [{{ index .Values "argo-cd" "configs" "cm" "url" | quote }}] + hosts: [{{ get (urlParse (index .Values "argo-cd" "configs" "cm" "url")) "host" }}] when: - key: connection.sni values: diff --git a/charts/kubezero-istio-gateway/tests/httpbin.yaml b/charts/kubezero-istio-gateway/tests/httpbin.yaml new file mode 100644 index 00000000..cb64cf33 --- /dev/null +++ b/charts/kubezero-istio-gateway/tests/httpbin.yaml @@ -0,0 +1,72 @@ +# Copyright Istio Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################################## +# httpbin service +################################################################################################## +apiVersion: v1 +kind: ServiceAccount +metadata: + name: httpbin +--- +apiVersion: v1 +kind: Service +metadata: + name: httpbin + labels: + app: httpbin + service: httpbin +spec: + ports: + - name: http + port: 8000 + targetPort: 8080 + selector: + app: httpbin +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: httpbin +spec: + replicas: 1 + selector: + matchLabels: + app: httpbin + version: v1 + template: + metadata: + labels: + app: httpbin + version: v1 + spec: + serviceAccountName: httpbin + containers: + - image: docker.io/kong/httpbin + imagePullPolicy: IfNotPresent + name: httpbin + # Same as found in Dockerfile's CMD but using an unprivileged port + command: + - gunicorn + - -b + - 0.0.0.0:8080 + - httpbin:app + - -k + - gevent + env: + # Tells pipenv to use a writable directory instead of $HOME + - name: WORKON_HOME + value: /tmp + ports: + - containerPort: 8080 diff --git a/charts/kubezero-istio-gateway/tests/virtualservice.yaml b/charts/kubezero-istio-gateway/tests/virtualservice.yaml new file mode 100644 index 00000000..b8418662 --- /dev/null +++ b/charts/kubezero-istio-gateway/tests/virtualservice.yaml @@ -0,0 +1,15 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: httpbin +spec: + hosts: + - "httpbin.example.com" + gateways: + - istio-ingress/ingressgateway + http: + - route: + - destination: + port: + number: 8000 + host: httpbin diff --git a/charts/kubezero-network/README.md b/charts/kubezero-network/README.md index 33fb26a8..8709038f 100644 --- a/charts/kubezero-network/README.md +++ b/charts/kubezero-network/README.md @@ -59,8 +59,52 @@ Kubernetes: `>= 1.26.0` | cilium.resources.limits.memory | string | `"1024Mi"` | | | cilium.resources.requests.cpu | string | `"10m"` | | | cilium.resources.requests.memory | string | `"256Mi"` | | +| cilium.routingMode | string | `"tunnel"` | | | cilium.tunnelProtocol | string | `"geneve"` | | +| haproxy.PodDisruptionBudget.enable | bool | `false` | | +| haproxy.PodDisruptionBudget.minAvailable | int | `1` | | +| haproxy.args.defaults[0] | string | `"-f"` | | +| haproxy.args.defaults[1] | string | `"/usr/local/etc/haproxy/includes/global.cfg"` | | +| haproxy.args.defaults[2] | string | `"-f"` | | +| haproxy.args.defaults[3] | string | `"/usr/local/etc/haproxy/includes/prometheus.cfg"` | | +| haproxy.args.defaults[4] | string | `"-f"` | | +| haproxy.args.defaults[5] | string | `"/usr/local/etc/haproxy/haproxy.cfg"` | | +| haproxy.config | string | `"frontend fe_main\n bind :8080\n default_backend be_main\n\nbackend be_main\n server web1 10.0.0.1:8080 check\n"` | | +| haproxy.containerPorts.http | int | `8080` | | +| haproxy.containerPorts.https | string | `nil` | | +| haproxy.containerPorts.prometheus | int | `8404` | | +| haproxy.containerPorts.stat | string | `nil` | | | haproxy.enabled | bool | `false` | | +| haproxy.includes."global.cfg" | string | `"global\n log stdout format raw local0\n maxconn 2048\n\ndefaults\n log global\n mode tcp\n option http-server-close\n timeout connect 10s\n timeout client 30s\n timeout client-fin 30s\n timeout server 30s\n timeout tunnel 1h\n\nresolvers coredns\n accepted_payload_size 4096\n parse-resolv-conf\n hold valid 10s\n hold other 10s\n hold refused 10s\n hold nx 10s\n hold timeout 10s\n"` | | +| haproxy.includes."prometheus.cfg" | string | `"frontend prometheus\n bind *:8404\n mode http\n http-request use-service prometheus-exporter if { path /metrics }\n no log\n stats enable\n stats uri /stats\n stats refresh 10s\n stats auth admin:letmein\n"` | | +| haproxy.livenessProbe.failureThreshold | int | `3` | | +| haproxy.livenessProbe.initialDelaySeconds | int | `0` | | +| haproxy.livenessProbe.periodSeconds | int | `10` | | +| haproxy.livenessProbe.successThreshold | int | `1` | | +| haproxy.livenessProbe.tcpSocket.port | int | `8404` | | +| haproxy.livenessProbe.timeoutSeconds | int | `1` | | +| haproxy.readinessProbe.failureThreshold | int | `3` | | +| haproxy.readinessProbe.initialDelaySeconds | int | `0` | | +| haproxy.readinessProbe.periodSeconds | int | `10` | | +| haproxy.readinessProbe.successThreshold | int | `1` | | +| haproxy.readinessProbe.tcpSocket.port | int | `8404` | | +| haproxy.readinessProbe.timeoutSeconds | int | `1` | | +| haproxy.replicaCount | int | `1` | | +| haproxy.resources.requests.cpu | string | `"10m"` | | +| haproxy.resources.requests.memory | string | `"48Mi"` | | +| haproxy.securityContext.allowPrivilegeEscalation | bool | `false` | | +| haproxy.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| haproxy.securityContext.enabled | bool | `true` | | +| haproxy.securityContext.runAsGroup | int | `1000` | | +| haproxy.securityContext.runAsNonRoot | bool | `true` | | +| haproxy.securityContext.runAsUser | int | `1000` | | +| haproxy.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| haproxy.serviceMonitor.enabled | bool | `false` | | +| haproxy.serviceMonitor.endpoints[0].interval | string | `"30s"` | | +| haproxy.serviceMonitor.endpoints[0].params.no-maint[0] | string | `"empty"` | | +| haproxy.serviceMonitor.endpoints[0].path | string | `"/metrics"` | | +| haproxy.serviceMonitor.endpoints[0].port | string | `"prometheus"` | | +| haproxy.serviceMonitor.endpoints[0].scheme | string | `"http"` | | | metallb.controller.nodeSelector."node-role.kubernetes.io/control-plane" | string | `""` | | | metallb.controller.tolerations[0].effect | string | `"NoSchedule"` | | | metallb.controller.tolerations[0].key | string | `"node-role.kubernetes.io/control-plane"` | | diff --git a/charts/kubezero-network/dashboards.yaml b/charts/kubezero-network/cilium-dashboards.yaml similarity index 100% rename from charts/kubezero-network/dashboards.yaml rename to charts/kubezero-network/cilium-dashboards.yaml diff --git a/charts/kubezero-network/haproxy-dashboards.yaml b/charts/kubezero-network/haproxy-dashboards.yaml new file mode 100644 index 00000000..88da7c02 --- /dev/null +++ b/charts/kubezero-network/haproxy-dashboards.yaml @@ -0,0 +1,10 @@ +configmap: haproxy-grafana-dashboards +gzip: true +condition: 'index .Values.haproxy.serviceMonitor.enabled' +folder: KubeZero +dashboards: +- name: HAProxy + url: https://grafana.com/api/dashboards/12693/revisions/8/download + tags: + - haproxy + - network diff --git a/charts/kubezero-network/templates/grafana-dashboards.yaml b/charts/kubezero-network/templates/cilium-grafana-dashboards.yaml similarity index 100% rename from charts/kubezero-network/templates/grafana-dashboards.yaml rename to charts/kubezero-network/templates/cilium-grafana-dashboards.yaml diff --git a/charts/kubezero-network/templates/haproxy-grafana-dashboards.yaml b/charts/kubezero-network/templates/haproxy-grafana-dashboards.yaml new file mode 100644 index 00000000..175c38e6 --- /dev/null +++ b/charts/kubezero-network/templates/haproxy-grafana-dashboards.yaml @@ -0,0 +1,15 @@ +{{- if index .Values.haproxy.serviceMonitor.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-%s" (include "kubezero-lib.fullname" $) "haproxy-grafana-dashboards" | trunc 63 | trimSuffix "-" }} + namespace: {{ .Release.Namespace }} + labels: + grafana_dashboard: "1" + {{- include "kubezero-lib.labels" . | nindent 4 }} + annotations: + k8s-sidecar-target-directory: KubeZero +binaryData: + HAProxy.json.gz: + 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 +{{- end }} diff --git a/charts/kubezero-network/crds/multus.yaml b/charts/kubezero-network/templates/multus/crds.yaml similarity index 97% rename from charts/kubezero-network/crds/multus.yaml rename to charts/kubezero-network/templates/multus/crds.yaml index 8aa15e6c..ff4bcf18 100644 --- a/charts/kubezero-network/crds/multus.yaml +++ b/charts/kubezero-network/templates/multus/crds.yaml @@ -1,3 +1,4 @@ +{{- if .Values.multus.enabled }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -42,3 +43,4 @@ spec: config: description: 'NetworkAttachmentDefinition config is a JSON-formatted CNI configuration' type: string +{{- end }} diff --git a/charts/kubezero-network/update.sh b/charts/kubezero-network/update.sh index 120f9dbe..79887b85 100755 --- a/charts/kubezero-network/update.sh +++ b/charts/kubezero-network/update.sh @@ -7,6 +7,7 @@ set -ex update_helm # Create ZDT dashboard configmap -../kubezero-metrics/sync_grafana_dashboards.py dashboards.yaml templates/grafana-dashboards.yaml +../kubezero-metrics/sync_grafana_dashboards.py cilium-dashboards.yaml templates/cilium-grafana-dashboards.yaml +../kubezero-metrics/sync_grafana_dashboards.py haproxy-dashboards.yaml templates/haproxy-grafana-dashboards.yaml update_docs diff --git a/charts/kubezero-network/values.yaml b/charts/kubezero-network/values.yaml index 7ee731fb..4cd8c87d 100644 --- a/charts/kubezero-network/values.yaml +++ b/charts/kubezero-network/values.yaml @@ -113,3 +113,117 @@ cilium: haproxy: enabled: false + + replicaCount: 1 + + # enable pdb if replica > 1 + PodDisruptionBudget: + enable: false + minAvailable: 1 + + containerPorts: + http: 8080 + https: null + prometheus: 8404 + stat: null + + serviceMonitor: + enabled: false + endpoints: + - port: prometheus + path: /metrics + scheme: http + interval: 30s + params: + no-maint: + - empty + config: | + frontend fe_main + bind :8080 + default_backend be_main + + backend be_main + server web1 10.0.0.1:8080 check + + includes: + global.cfg: | + global + log stdout format raw local0 + maxconn 2048 + + defaults + log global + mode tcp + option http-server-close + timeout connect 10s + timeout client 30s + timeout client-fin 30s + timeout server 30s + timeout tunnel 1h + + resolvers coredns + accepted_payload_size 4096 + parse-resolv-conf + hold valid 10s + hold other 10s + hold refused 10s + hold nx 10s + hold timeout 10s + + prometheus.cfg: | + frontend prometheus + bind *:8404 + mode http + http-request use-service prometheus-exporter if { path /metrics } + no log + stats enable + stats uri /stats + stats refresh 10s + stats auth admin:letmein + + args: + defaults: + - "-f" + - "/usr/local/etc/haproxy/includes/global.cfg" + - "-f" + - "/usr/local/etc/haproxy/includes/prometheus.cfg" + - "-f" + - "/usr/local/etc/haproxy/haproxy.cfg" + + livenessProbe: + failureThreshold: 3 + successThreshold: 1 + initialDelaySeconds: 0 + timeoutSeconds: 1 + tcpSocket: + port: 8404 + periodSeconds: 10 + + readinessProbe: + failureThreshold: 3 + successThreshold: 1 + initialDelaySeconds: 0 + timeoutSeconds: 1 + tcpSocket: + port: 8404 + periodSeconds: 10 + + securityContext: + enabled: true + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + resources: + requests: + cpu: 10m + memory: 48Mi + # limits: + # cpu: 250m + # memory: 128Mi