From 2bb6934c77cf286890ab97b62210735c89e7da86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=8C=AF=E5=AE=87?= <> Date: Fri, 10 Jan 2025 02:35:25 +0800 Subject: [PATCH] chore: code staging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 孙振宇 <> --- README.md | 30 + assets/layout.png | Bin 0 -> 62660 bytes cluster/group_vars/all/all.yml | 137 + cluster/group_vars/all/containerd.yml | 59 + cluster/group_vars/all/etcd.yml | 16 + cluster/group_vars/etcd.yml | 38 + cluster/group_vars/k8s_cluster/addons.yml | 290 +++ .../group_vars/k8s_cluster/k8s-cluster.yml | 387 +++ .../group_vars/k8s_cluster/k8s-net-calico.yml | 132 + cluster/inventory.ini | 8 + .../cert-manager/.gitkeep | 0 .../godaddy-webhook/.gitkeep | 0 .../ingress-nginx/.gitkeep | 0 .../argo-cd/values.yaml | 2294 +++++++++++++++++ .../freeleaps-devops-system/jenkins/.gitkeep | 0 .../freeleaps-devops-system/namespace.yaml | 17 + .../kube-prometheus-stack/.gitkeep | 0 .../azure-blob-storage-csi/.gitkeep | 0 .../open-ebs/.gitkeep | 0 cluster/manifests/helm-repos/REPO.list | 12 + 20 files changed, 3420 insertions(+) create mode 100644 assets/layout.png create mode 100644 cluster/group_vars/all/all.yml create mode 100644 cluster/group_vars/all/containerd.yml create mode 100644 cluster/group_vars/all/etcd.yml create mode 100644 cluster/group_vars/etcd.yml create mode 100644 cluster/group_vars/k8s_cluster/addons.yml create mode 100644 cluster/group_vars/k8s_cluster/k8s-cluster.yml create mode 100644 cluster/group_vars/k8s_cluster/k8s-net-calico.yml create mode 100644 cluster/inventory.ini create mode 100644 cluster/manifests/freeleaps-controls-system/cert-manager/.gitkeep create mode 100644 cluster/manifests/freeleaps-controls-system/godaddy-webhook/.gitkeep create mode 100644 cluster/manifests/freeleaps-controls-system/ingress-nginx/.gitkeep create mode 100644 cluster/manifests/freeleaps-devops-system/argo-cd/values.yaml create mode 100644 cluster/manifests/freeleaps-devops-system/jenkins/.gitkeep create mode 100644 cluster/manifests/freeleaps-devops-system/namespace.yaml create mode 100644 cluster/manifests/freeleaps-monitoring-system/kube-prometheus-stack/.gitkeep create mode 100644 cluster/manifests/freeleaps-storage-system/azure-blob-storage-csi/.gitkeep create mode 100644 cluster/manifests/freeleaps-storage-system/open-ebs/.gitkeep create mode 100644 cluster/manifests/helm-repos/REPO.list diff --git a/README.md b/README.md index 4f1524ce..9d956009 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,33 @@ # Freeleaps Ops > All GitOps relates manifests or scripts. + +## Introduce + +This repo has stored all manifests files of Freeleaps productions, infrastructures and cluster. + +The project layout is follow this pattern: + +![layout](assets/layout.png) + +## How to use ? + +**Please do not edit files under this repo if you do not know what you doing.** + +This repo files are managed by CI/CD services (Jenkins, Argo CD etc,.). + +## About `cluster` folder + +**P.S. THIS FOLDER IS ONLY USED FOR CLUSTER ADMINISTRATOR, YOU MUST KNOW WHAT YOU DOING BEFORE YOU MODIFY IT.** + +> If you want to working with cluster folder, you must set-up local maintaining environment first. +> You need make sure you have `Python 3` environment in local and `Ansible` already installed. +> And you need to make sure run `git submodule update --init --recursive` to clone `kubespray` repo before you start to work. + +`cluster` folder stores the infrastructure components, applications manifests and [`kubespray`](https://kubespray.io/) configuration files for entire cluster. + +`cluster/manifests//` stores the manifests of components or applications. + +`cluster/inventory.ini` stores the current state of the cluster, if you want to add new nodes to cluster, you need edit this file. + +`cluster/group_vars` describes current configuration states of the cluster. diff --git a/assets/layout.png b/assets/layout.png new file mode 100644 index 0000000000000000000000000000000000000000..39b1800dbe86e5ed6e4060bd9faa9e781f940c3d GIT binary patch literal 62660 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 L7lZz_t98k3tW>yxe5)fQUP5t`2?K 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 + {%- if kube_proxy_nodeport_addresses_cidr is defined -%} + [{{ kube_proxy_nodeport_addresses_cidr }}] + {%- else -%} + [] + {%- endif -%} + +# If non-empty, will use this string as identification instead of the actual hostname +# kube_override_hostname: {{ inventory_hostname }} + +## Encrypting Secret Data at Rest +kube_encrypt_secret_data: false + +# Graceful Node Shutdown (Kubernetes >= 1.21.0), see https://kubernetes.io/blog/2021/04/21/graceful-node-shutdown-beta/ +# kubelet_shutdown_grace_period had to be greater than kubelet_shutdown_grace_period_critical_pods to allow +# non-critical podsa to also terminate gracefully +# kubelet_shutdown_grace_period: 60s +# kubelet_shutdown_grace_period_critical_pods: 20s + +# DNS configuration. +# Kubernetes cluster name, also will be used as DNS domain +cluster_name: freeleaps.cluster +# Subdomains of DNS domain to be resolved via /etc/resolv.conf for hostnet pods +ndots: 2 +# dns_timeout: 2 +# dns_attempts: 2 +# Custom search domains to be added in addition to the default cluster search domains +# searchdomains: +# - svc.{{ cluster_name }} +# - default.svc.{{ cluster_name }} +# Remove default cluster search domains (``default.svc.{{ dns_domain }}, svc.{{ dns_domain }}``). +# remove_default_searchdomains: false +# Can be coredns, coredns_dual, manual or none +dns_mode: coredns +# Set manual server if using a custom cluster DNS server +# manual_dns_server: 10.x.x.x +# Enable nodelocal dns cache +enable_nodelocaldns: true +enable_nodelocaldns_secondary: false +nodelocaldns_ip: 169.254.25.10 +nodelocaldns_health_port: 9254 +nodelocaldns_second_health_port: 9256 +nodelocaldns_bind_metrics_host_ip: false +nodelocaldns_secondary_skew_seconds: 5 +# nodelocaldns_external_zones: +# - zones: +# - example.com +# - example.io:1053 +# nameservers: +# - 1.1.1.1 +# - 2.2.2.2 +# cache: 5 +# - zones: +# - https://mycompany.local:4453 +# nameservers: +# - 192.168.0.53 +# cache: 0 +# - zones: +# - mydomain.tld +# nameservers: +# - 10.233.0.3 +# cache: 5 +# rewrite: +# - name website.tld website.namespace.svc.cluster.local +# Enable k8s_external plugin for CoreDNS +enable_coredns_k8s_external: false +coredns_k8s_external_zone: k8s_external.local +# Enable endpoint_pod_names option for kubernetes plugin +enable_coredns_k8s_endpoint_pod_names: false +# Set forward options for upstream DNS servers in coredns (and nodelocaldns) config +# dns_upstream_forward_extra_opts: +# policy: sequential +# Apply extra options to coredns kubernetes plugin +# coredns_kubernetes_extra_opts: +# - 'fallthrough example.local' +# Forward extra domains to the coredns kubernetes plugin +# coredns_kubernetes_extra_domains: '' + +# Can be docker_dns, host_resolvconf or none +resolvconf_mode: host_resolvconf +# Deploy netchecker app to verify DNS resolve as an HTTP service +deploy_netchecker: false +# Ip address of the kubernetes skydns service +skydns_server: "{{ kube_service_addresses | ansible.utils.ipaddr('net') | ansible.utils.ipaddr(3) | ansible.utils.ipaddr('address') }}" +skydns_server_secondary: "{{ kube_service_addresses | ansible.utils.ipaddr('net') | ansible.utils.ipaddr(4) | ansible.utils.ipaddr('address') }}" +dns_domain: "{{ cluster_name }}" + +## Container runtime +## docker for docker, crio for cri-o and containerd for containerd. +## Default: containerd +container_manager: containerd + +# Additional container runtimes +kata_containers_enabled: false + +kubeadm_certificate_key: "{{ lookup('password', credentials_dir + '/kubeadm_certificate_key.creds length=64 chars=hexdigits') | lower }}" + +# K8s image pull policy (imagePullPolicy) +k8s_image_pull_policy: IfNotPresent + +# audit log for kubernetes +kubernetes_audit: true + +# define kubelet config dir for dynamic kubelet +# kubelet_config_dir: +default_kubelet_config_dir: "{{ kube_config_dir }}/dynamic_kubelet_dir" + +# Make a copy of kubeconfig on the host that runs Ansible in {{ inventory_dir }}/artifacts +# kubeconfig_localhost: false +# Use ansible_host as external api ip when copying over kubeconfig. +# kubeconfig_localhost_ansible_host: false +# Download kubectl onto the host that runs Ansible in {{ bin_dir }} +# kubectl_localhost: false + +# A comma separated list of levels of node allocatable enforcement to be enforced by kubelet. +# Acceptable options are 'pods', 'system-reserved', 'kube-reserved' and ''. Default is "". +# kubelet_enforce_node_allocatable: pods + +## Set runtime and kubelet cgroups when using systemd as cgroup driver (default) +# kubelet_runtime_cgroups: "/{{ kube_service_cgroups }}/{{ container_manager }}.service" +# kubelet_kubelet_cgroups: "/{{ kube_service_cgroups }}/kubelet.service" + +## Set runtime and kubelet cgroups when using cgroupfs as cgroup driver +# kubelet_runtime_cgroups_cgroupfs: "/system.slice/{{ container_manager }}.service" +# kubelet_kubelet_cgroups_cgroupfs: "/system.slice/kubelet.service" + +# Whether to run kubelet and container-engine daemons in a dedicated cgroup. +# kube_reserved: false +## Uncomment to override default values +## The following two items need to be set when kube_reserved is true +# kube_reserved_cgroups_for_service_slice: kube.slice +# kube_reserved_cgroups: "/{{ kube_reserved_cgroups_for_service_slice }}" +# kube_memory_reserved: 256Mi +# kube_cpu_reserved: 100m +# kube_ephemeral_storage_reserved: 2Gi +# kube_pid_reserved: "1000" +# Reservation for control plane hosts +# kube_master_memory_reserved: 512Mi +# kube_master_cpu_reserved: 200m +# kube_master_ephemeral_storage_reserved: 2Gi +# kube_master_pid_reserved: "1000" + +## Optionally reserve resources for OS system daemons. +# system_reserved: true +## Uncomment to override default values +## The following two items need to be set when system_reserved is true +# system_reserved_cgroups_for_service_slice: system.slice +# system_reserved_cgroups: "/{{ system_reserved_cgroups_for_service_slice }}" +# system_memory_reserved: 512Mi +# system_cpu_reserved: 500m +# system_ephemeral_storage_reserved: 2Gi +## Reservation for master hosts +# system_master_memory_reserved: 256Mi +# system_master_cpu_reserved: 250m +# system_master_ephemeral_storage_reserved: 2Gi + +## Eviction Thresholds to avoid system OOMs +# https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#eviction-thresholds +# eviction_hard: {} +# eviction_hard_control_plane: {} + +# An alternative flexvolume plugin directory +# kubelet_flexvolumes_plugins_dir: /usr/libexec/kubernetes/kubelet-plugins/volume/exec + +## Supplementary addresses that can be added in kubernetes ssl keys. +## That can be useful for example to setup a keepalived virtual IP +# supplementary_addresses_in_ssl_keys: [10.0.0.1, 10.0.0.2, 10.0.0.3] + +## Running on top of openstack vms with cinder enabled may lead to unschedulable pods due to NoVolumeZoneConflict restriction in kube-scheduler. +## See https://github.com/kubernetes-sigs/kubespray/issues/2141 +## Set this variable to true to get rid of this issue +volume_cross_zone_attachment: false +## Add Persistent Volumes Storage Class for corresponding cloud provider (supported: in-tree OpenStack, Cinder CSI, +## AWS EBS CSI, Azure Disk CSI, GCP Persistent Disk CSI) +persistent_volumes_enabled: false + +## Container Engine Acceleration +## Enable container acceleration feature, for example use gpu acceleration in containers +# nvidia_accelerator_enabled: true +## Nvidia GPU driver install. Install will by done by a (init) pod running as a daemonset. +## Important: if you use Ubuntu then you should set in all.yml 'docker_storage_options: -s overlay2' +## Array with nvida_gpu_nodes, leave empty or comment if you don't want to install drivers. +## Labels and taints won't be set to nodes if they are not in the array. +# nvidia_gpu_nodes: +# - kube-gpu-001 +# nvidia_driver_version: "384.111" +## flavor can be tesla or gtx +# nvidia_gpu_flavor: gtx +## NVIDIA driver installer images. Change them if you have trouble accessing gcr.io. +# nvidia_driver_install_centos_container: atzedevries/nvidia-centos-driver-installer:2 +# nvidia_driver_install_ubuntu_container: gcr.io/google-containers/ubuntu-nvidia-driver-installer@sha256:7df76a0f0a17294e86f691c81de6bbb7c04a1b4b3d4ea4e7e2cccdc42e1f6d63 +## NVIDIA GPU device plugin image. +# nvidia_gpu_device_plugin_container: "registry.k8s.io/nvidia-gpu-device-plugin@sha256:0842734032018be107fa2490c98156992911e3e1f2a21e059ff0105b07dd8e9e" + +## Support tls min version, Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. +# tls_min_version: "" + +## Support tls cipher suites. +# tls_cipher_suites: {} +# - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +# - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +# - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +# - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +# - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +# - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 +# - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +# - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +# - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +# - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +# - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +# - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +# - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +# - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +# - TLS_ECDHE_RSA_WITH_RC4_128_SHA +# - TLS_RSA_WITH_3DES_EDE_CBC_SHA +# - TLS_RSA_WITH_AES_128_CBC_SHA +# - TLS_RSA_WITH_AES_128_CBC_SHA256 +# - TLS_RSA_WITH_AES_128_GCM_SHA256 +# - TLS_RSA_WITH_AES_256_CBC_SHA +# - TLS_RSA_WITH_AES_256_GCM_SHA384 +# - TLS_RSA_WITH_RC4_128_SHA + +## Amount of time to retain events. (default 1h0m0s) +event_ttl_duration: "1h0m0s" + +# COMMENTS: Enable the auto renew certificates @ Sun Zhenyu +## Automatically renew K8S control plane certificates on first Monday of each month +auto_renew_certificates: true +# First Monday of each month +# auto_renew_certificates_systemd_calendar: "Mon *-*-1,2,3,4,5,6,7 03:{{ groups['kube_control_plane'].index(inventory_hostname) }}0:00" + +kubeadm_patches_dir: "{{ kube_config_dir }}/patches" +kubeadm_patches: [] +# See https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/control-plane-flags/#patches +# Correspondance with this link +# patchtype = type +# target = target +# suffix -> managed automatically +# extension -> always "yaml" +# kubeadm_patches: +# - target: kube-apiserver|kube-controller-manager|kube-scheduler|etcd|kubeletconfiguration +# type: strategic(default)|json|merge +# patch: +# metadata: +# annotations: +# example.com/test: "true" +# labels: +# example.com/prod_level: "{{ prod_level }}" +# - ... +# Patches are applied in the order they are specified. + +# Set to true to remove the role binding to anonymous users created by kubeadm +remove_anonymous_access: false diff --git a/cluster/group_vars/k8s_cluster/k8s-net-calico.yml b/cluster/group_vars/k8s_cluster/k8s-net-calico.yml new file mode 100644 index 00000000..9089bac8 --- /dev/null +++ b/cluster/group_vars/k8s_cluster/k8s-net-calico.yml @@ -0,0 +1,132 @@ +--- +# see roles/network_plugin/calico/defaults/main.yml + +# the default value of name +calico_cni_name: freeleaps-network-system + +## With calico it is possible to distributed routes with border routers of the datacenter. +## Warning : enabling router peering will disable calico's default behavior ('node mesh'). +## The subnets of each nodes will be distributed by the datacenter router +# peer_with_router: false + +# Enables Internet connectivity from containers +# nat_outgoing: true +# nat_outgoing_ipv6: false + +# Enables Calico CNI "host-local" IPAM plugin +# calico_ipam_host_local: true + +# add default ippool name +calico_pool_name: "freeleaps-network-ip-pool" + +# add default ippool blockSize +calico_pool_blocksize: 26 + +# add default ippool CIDR (must be inside kube_pods_subnet, defaults to kube_pods_subnet otherwise) +# calico_pool_cidr: 1.2.3.4/5 + +# add default ippool CIDR to CNI config +# calico_cni_pool: true + +# Add default IPV6 IPPool CIDR. Must be inside kube_pods_subnet_ipv6. Defaults to kube_pods_subnet_ipv6 if not set. +# calico_pool_cidr_ipv6: fd85:ee78:d8a6:8607::1:0000/112 + +# Add default IPV6 IPPool CIDR to CNI config +# calico_cni_pool_ipv6: true + +# Global as_num (/calico/bgp/v1/global/as_num) +# global_as_num: "64512" + +# If doing peering with node-assigned asn where the globas does not match your nodes, you want this +# to be true. All other cases, false. +# calico_no_global_as_num: false + +# You can set MTU value here. If left undefined or empty, it will +# not be specified in calico CNI config, so Calico will use built-in +# defaults. The value should be a number, not a string. +# calico_mtu: 1500 + +# Configure the MTU to use for workload interfaces and tunnels. +# - If Wireguard is enabled, subtract 60 from your network MTU (i.e 1500-60=1440) +# - Otherwise, if VXLAN or BPF mode is enabled, subtract 50 from your network MTU (i.e. 1500-50=1450) +# - Otherwise, if IPIP is enabled, subtract 20 from your network MTU (i.e. 1500-20=1480) +# - Otherwise, if not using any encapsulation, set to your network MTU (i.e. 1500) +# calico_veth_mtu: 1440 + +# Advertise Cluster IPs +# calico_advertise_cluster_ips: true + +# Advertise Service External IPs +# calico_advertise_service_external_ips: +# - x.x.x.x/24 +# - y.y.y.y/32 + +# Advertise Service LoadBalancer IPs +# calico_advertise_service_loadbalancer_ips: +# - x.x.x.x/24 +# - y.y.y.y/16 + +# Choose data store type for calico: "etcd" or "kdd" (kubernetes datastore) +# calico_datastore: "kdd" + +# Choose Calico iptables backend: "Legacy", "Auto" or "NFT" +# calico_iptables_backend: "Auto" + +# Use typha (only with kdd) +# typha_enabled: false + +# Generate TLS certs for secure typha<->calico-node communication +# typha_secure: false + +# Scaling typha: 1 replica per 100 nodes is adequate +# Number of typha replicas +# typha_replicas: 1 + +# Set max typha connections +# typha_max_connections_lower_limit: 300 + +# Set calico network backend: "bird", "vxlan" or "none" +# bird enable BGP routing, required for ipip and no encapsulation modes +# calico_network_backend: vxlan + +# IP in IP and VXLAN is mutually exclusive modes. +# set IP in IP encapsulation mode: "Always", "CrossSubnet", "Never" +# calico_ipip_mode: 'Never' + +# set VXLAN encapsulation mode: "Always", "CrossSubnet", "Never" +# calico_vxlan_mode: 'Always' + +# set VXLAN port and VNI +# calico_vxlan_vni: 4096 +# calico_vxlan_port: 4789 + +# Enable eBPF mode +# calico_bpf_enabled: false + +# If you want to use non default IP_AUTODETECTION_METHOD, IP6_AUTODETECTION_METHOD for calico node set this option to one of: +# * can-reach=DESTINATION +# * interface=INTERFACE-REGEX +# see https://docs.projectcalico.org/reference/node/configuration +# calico_ip_auto_method: "interface=eth.*" +# calico_ip6_auto_method: "interface=eth.*" + +# Set FELIX_MTUIFACEPATTERN, Pattern used to discover the host’s interface for MTU auto-detection. +# see https://projectcalico.docs.tigera.io/reference/felix/configuration +# calico_felix_mtu_iface_pattern: "^((en|wl|ww|sl|ib)[opsx].*|(eth|wlan|wwan).*)" + +# Choose the iptables insert mode for Calico: "Insert" or "Append". +# calico_felix_chaininsertmode: Insert + +# If you want use the default route interface when you use multiple interface with dynamique route (iproute2) +# see https://docs.projectcalico.org/reference/node/configuration : FELIX_DEVICEROUTESOURCEADDRESS +# calico_use_default_route_src_ipaddr: false + +# Enable calico traffic encryption with wireguard +# calico_wireguard_enabled: false + +# Under certain situations liveness and readiness probes may need tunning +# calico_node_livenessprobe_timeout: 10 +# calico_node_readinessprobe_timeout: 10 + +# Calico apiserver (only with kdd) +# calico_apiserver_enabled: false diff --git a/cluster/inventory.ini b/cluster/inventory.ini new file mode 100644 index 00000000..344de3d9 --- /dev/null +++ b/cluster/inventory.ini @@ -0,0 +1,8 @@ +# Configure 'ip' variable to bind kubernetes services on a different ip than the default iface +# We should set etcd_member_name for etcd cluster. The node that are not etcd members do not need to set the value, +# or can set the empty string value. +[kube_control_plane] + +[etcd:children] + +[kube_node] \ No newline at end of file diff --git a/cluster/manifests/freeleaps-controls-system/cert-manager/.gitkeep b/cluster/manifests/freeleaps-controls-system/cert-manager/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/cluster/manifests/freeleaps-controls-system/godaddy-webhook/.gitkeep b/cluster/manifests/freeleaps-controls-system/godaddy-webhook/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/cluster/manifests/freeleaps-controls-system/ingress-nginx/.gitkeep b/cluster/manifests/freeleaps-controls-system/ingress-nginx/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/cluster/manifests/freeleaps-devops-system/argo-cd/values.yaml b/cluster/manifests/freeleaps-devops-system/argo-cd/values.yaml new file mode 100644 index 00000000..3d4c6c1c --- /dev/null +++ b/cluster/manifests/freeleaps-devops-system/argo-cd/values.yaml @@ -0,0 +1,2294 @@ +## Argo CD configuration +## Ref: https://github.com/argoproj/argo-cd +## +# -- Provide a name in place of `argocd` +nameOverride: argocd +# -- Override the namespace +namespaceOverride: "freeleaps-devops-system" +# -- Create aggregated roles that extend existing cluster roles to interact with argo-cd resources +## Ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles +createAggregateRoles: false +# -- Create cluster roles for cluster-wide installation. +## Used when you manage applications in the same cluster where Argo CD runs +createClusterRoles: true + +## Custom resource configuration +crds: + # -- Install and upgrade CRDs + install: true + # -- Keep CRDs on chart uninstall + keep: true + +## Globally shared configuration +global: + # -- Default domain used by all components + ## Used for ingresses, certificates, SSO, notifications, etc. + domain: argo.mathmast.com + # -- Number of old deployment ReplicaSets to retain. The rest will be garbage collected. + revisionHistoryLimit: 3 + # Default image used by all components + image: + # -- If defined, a repository applied to all Argo CD deployments + repository: quay.io/argoproj/argocd + # -- If defined, a imagePullPolicy applied to all Argo CD deployments + imagePullPolicy: IfNotPresent + # Default logging options used by all components + logging: + # -- Set the global logging format. Either: `text` or `json` + format: text + # -- Set the global logging level. One of: `debug`, `info`, `warn` or `error` + level: info + # -- Add Prometheus scrape annotations to all metrics services. This can be used as an alternative to the ServiceMonitors. + addPrometheusAnnotations: false + # Default network policy rules used by all components + networkPolicy: + # -- Create NetworkPolicy objects for all components + create: false + # -- Default deny all ingress traffic + defaultDenyIngress: false + +## Argo Configs +configs: + # General Argo CD configuration + ## Ref: https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/argocd-cm.yaml + cm: + # -- Create the argocd-cm configmap for [declarative setup] + create: true + # -- The name of tracking label used by Argo CD for resource pruning + application.instanceLabelKey: argocd.argoproj.io/instance + # -- Enable logs RBAC enforcement + ## Ref: https://argo-cd.readthedocs.io/en/latest/operator-manual/upgrading/2.3-2.4/#enable-logs-rbac-enforcement + server.rbac.log.enforce.enable: false + # -- Enable exec feature in Argo UI + ## Ref: https://argo-cd.readthedocs.io/en/latest/operator-manual/rbac/#exec-resource + exec.enabled: true + # -- Enable local admin user + ## Ref: https://argo-cd.readthedocs.io/en/latest/faq/#how-to-disable-admin-user + admin.enabled: true + # -- Timeout to discover if a new manifests version got published to the repository + timeout.reconciliation: 180s + # -- Timeout to refresh application data as well as target manifests cache + timeout.hard.reconciliation: 0s + # -- Enable Status Badge + ## Ref: https://argo-cd.readthedocs.io/en/stable/user-guide/status-badge/ + statusbadge.enabled: true + # OIDC configuration as an alternative to dex (optional). + # oidc.config: | + # name: AzureAD + # issuer: https://login.microsoftonline.com/TENANT_ID/v2.0 + # clientID: CLIENT_ID + # clientSecret: $oidc.azuread.clientSecret + # rootCA: | + # -----BEGIN CERTIFICATE----- + # ... encoded certificate data here ... + # -----END CERTIFICATE----- + # requestedIDTokenClaims: + # groups: + # essential: true + # requestedScopes: + # - openid + # - profile + # - email + + # Argo CD configuration parameters + ## Ref: https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/argocd-cmd-params-cm.yaml + params: + # -- Create the argocd-cmd-params-cm configmap + # If false, it is expected the configmap will be created by something else. + create: true + ## Controller Properties + # -- Number of application status processors + controller.status.processors: 20 + # -- Number of application operation processors + controller.operation.processors: 10 + # -- Specifies timeout between application self heal attempts + controller.self.heal.timeout.seconds: 5 + # -- Repo server RPC call timeout seconds. + controller.repo.server.timeout.seconds: 60 + ## Server properties + # -- Run server without TLS + ## NOTE: This value should be set when you generate params by other means as it changes ports used by ingress template. + ## NOTE: We are using Ingress for serve TLS request and redirect none-TLS request to actual service. + server.insecure: true + # -- Value for base href in index.html. Used if Argo CD is running behind reverse proxy under subpath different from / + server.basehref: / + # -- Directory path that contains additional static assets + server.staticassets: /shared/app + # -- Disable Argo CD RBAC for user authentication + server.disable.auth: false + # -- Enable GZIP compression + server.enable.gzip: true + # -- Enable proxy extension feature. (proxy extension is in Alpha phase) + server.enable.proxy.extension: false + # -- Set X-Frame-Options header in HTTP responses to value. To disable, set to "". + server.x.frame.options: sameorigin + ## Repo-server properties + # -- Limit on number of concurrent manifests generate requests. Any value less the 1 means no limit. + reposerver.parallelism.limit: 0 + ## ApplicationSet Properties + # -- Modify how application is synced between the generator and the cluster. One of: `sync`, `create-only`, `create-update`, `create-delete` + applicationsetcontroller.policy: sync + # -- Enables use of the Progressive Syncs capability + applicationsetcontroller.enable.progressive.syncs: false + # -- JQ Path expression timeout + ## By default, the evaluation of a JQPathExpression is limited to one second. + ## If you encounter a "JQ patch execution timed out" error message due to a complex JQPathExpression + ## that requires more time to evaluate, you can extend the timeout period. + controller.ignore.normalizer.jq.timeout: "1s" + + # Argo CD RBAC policy configuration + ## Ref: https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/rbac.md + rbac: + # -- Create the argocd-rbac-cm configmap with ([Argo CD RBAC policy]) definitions. + # If false, it is expected the configmap will be created by something else. + # Argo CD will not work if there is no configmap created with the name above. + create: true + # -- OIDC scopes to examine during rbac enforcement (in addition to `sub` scope). + # The scope value can be a string, or a list of strings. + scopes: "[groups]" + # -- Matcher function for Casbin, `glob` for glob matcher and `regex` for regex matcher. + policy.matchMode: "glob" + # SSH known hosts for Git repositories + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#ssh-known-host-public-keys + ssh: + # -- Specifies if the argocd-ssh-known-hosts-cm configmap should be created by Helm. + create: true + # -- Known hosts to be added to the known host list by default. + # @default -- See [values.yaml] + knownHosts: | + [ssh.github.com]:443 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= + [ssh.github.com]:443 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl + [ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= + bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE= + bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO + bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M= + github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= + github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl + github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= + gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= + gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf + gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 + ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H + vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H + + # Argo CD sensitive data + # Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/#sensitive-data-and-sso-client-secrets + secret: + # -- Create the argocd-secret + createSecret: true + # -- Bcrypt hashed admin password + ## Argo expects the password in the secret to be bcrypt hashed. You can create this hash with + ## `htpasswd -nbBC 10 "" $ARGO_PWD | tr -d ':\n' | sed 's/$2y/$2a/'` + argocdServerAdminPassword: "" + # -- Admin password modification time. Eg. `"2006-01-02T15:04:05Z"` + # @default -- `""` (defaults to current time) + argocdServerAdminPasswordMtime: "" + +## Application controller +controller: + # -- Application controller name string + name: application-controller + # -- The number of application controller pods to run. + # Additional replicas will cause sharding of managed clusters across number of replicas. + ## With dynamic cluster distribution turned on, sharding of the clusters will gracefully + ## rebalance if the number of replica's changes or one becomes unhealthy. (alpha) + replicas: 1 + # -- Enable dynamic cluster distribution (alpha) + # Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/dynamic-cluster-distribution + ## This is done using a deployment instead of a statefulSet + ## When replicas are added or removed, the sharding algorithm is re-run to ensure that the + ## clusters are distributed according to the algorithm. If the algorithm is well-balanced, + ## like round-robin, then the shards will be well-balanced. + dynamicClusterDistribution: false + # -- Application controller heartbeat time + # Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/dynamic-cluster-distribution/#working-of-dynamic-distribution + heartbeatTime: 10 + # -- Maximum number of controller revisions that will be maintained in StatefulSet history + revisionHistoryLimit: 5 + ## Application controller Pod Disruption Budget + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + pdb: + # -- Deploy a [PodDisruptionBudget] for the application controller + enabled: true + # -- Number of pods that are available after eviction as number or percentage (eg.: 50%) + # @default -- `""` (defaults to 0 if not specified) + minAvailable: "1" + # -- Number of pods that are unavailable after eviction as number or percentage (eg.: 50%). + ## Has higher precedence over `controller.pdb.minAvailable` + maxUnavailable: "0" + ## Application controller emptyDir volumes + emptyDir: + # -- EmptyDir size limit for application controller + # @default -- `""` (defaults not set if not specified i.e. no size limit) + sizeLimit: "" + # -- Resource limits and requests for the application controller pods + resources: + limits: + cpu: "1" + memory: "1Gi" + requests: + cpu: "250m" + memory: "512Mi" + # Application controller container ports + containerPorts: + # -- Metrics container port + metrics: 8082 + # -- Host Network for application controller pods + hostNetwork: false + # -- Alternative DNS policy for application controller pods + dnsPolicy: "ClusterFirst" + # -- Application controller container-level security context + # @default -- See [values.yaml] + containerSecurityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + # Readiness probe for application controller + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + readinessProbe: + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + # -- terminationGracePeriodSeconds for container lifecycle hook + terminationGracePeriodSeconds: 30 + # -- Automount API credentials for the Service Account into the pod. + automountServiceAccountToken: true + serviceAccount: + # -- Create a service account for the application controller + create: true + # -- Service account name + name: argocd-application-controller + # -- Automount API credentials for the Service Account + automountServiceAccountToken: true + ## Application controller metrics configuration + metrics: + # -- Deploy metrics service + enabled: true + service: + # -- Metrics service type + type: ClusterIP + # -- Metrics service port + servicePort: 8082 + # -- Metrics service port name + portName: http-metrics + serviceMonitor: + # -- Enable a prometheus ServiceMonitor + enabled: true + # -- Prometheus ServiceMonitor interval + interval: 30s + # -- Prometheus ServiceMonitor namespace + namespace: "freeleaps-monitoring-system" + rules: + # -- Deploy a PrometheusRule for the application controller + enabled: true + # -- PrometheusRule namespace + namespace: "freeleaps-monitoring-system" # "monitoring" + # -- PrometheusRule.Spec for the application controller + spec: + - alert: ArgoAppMissing + expr: | + absent(argocd_app_info) == 1 + for: 15m + labels: + severity: critical + annotations: + summary: "[Argo CD] No reported applications" + description: > + Argo CD has not reported any applications data for the past 15 minutes which + means that it must be down or not functioning properly. This needs to be + resolved for this cloud to continue to maintain state. + - alert: ArgoAppNotSynced + expr: | + argocd_app_info{sync_status!="Synced"} == 1 + for: 12h + labels: + severity: warning + annotations: + summary: "[{{`{{$labels.name}}`}}] Application not synchronized" + description: > + The application [{{`{{$labels.name}}`}} has not been synchronized for over + 12 hours which means that the state of this cloud has drifted away from the + state inside Git. + +## Dex +dex: + # FIXME: we need self-hosted dex if required @ Zhenyu Sun + enabled: false + +## Redis +redis: + # -- Enable redis + enabled: true + # -- Redis name + name: argo-cd-dedicated-redis + ## Redis Pod Disruption Budget + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + pdb: + # -- Deploy a [PodDisruptionBudget] for the Redis + enabled: true + # -- Number of pods that are available after eviction as number or percentage (eg.: 50%) + # @default -- `""` (defaults to 0 if not specified) + minAvailable: "1" + # -- Number of pods that are unavailble after eviction as number or percentage (eg.: 50%). + ## Has higher precedence over `redis.pdb.minAvailable` + maxUnavailable: "0" + ## Redis image + image: + # -- Redis repository + repository: public.ecr.aws/docker/library/redis + # -- Redis tag + tag: 7.4.1-alpine + ## Prometheus redis-exporter sidecar + exporter: + # -- Enable Prometheus redis-exporter sidecar + enabled: true + ## Prometheus redis-exporter image + image: + # -- Repository to use for the redis-exporter + repository: public.ecr.aws/bitnami/redis-exporter + # -- Tag to use for the redis-exporter + tag: 1.58.0 + # -- Redis exporter security context + # @default -- See [values.yaml] + containerSecurityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## Probes for Redis exporter (optional) + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + readinessProbe: + # -- Enable Kubernetes liveness probe for Redis exporter (optional) + enabled: true + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 30 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 15 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 15 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 5 + livenessProbe: + # -- Enable Kubernetes liveness probe for Redis exporter + enabled: true + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 30 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 15 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 15 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 5 + # -- Resource limits and requests for redis-exporter sidecar + resources: + limits: + cpu: "50m" + memory: "64Mi" + requests: + cpu: "10m" + memory: "32Mi" + ## Probes for Redis server (optional) + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + readinessProbe: + # -- Enable Kubernetes liveness probe for Redis server + enabled: true + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 30 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 15 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 15 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 5 + livenessProbe: + # -- Enable Kubernetes liveness probe for Redis server + enabled: true + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 30 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 15 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 15 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 5 + # -- Resource limits and requests for redis + resources: + limits: + cpu: "500m" + memory: "512Mi" + requests: + cpu: "100m" + memory: "128Mi" + # -- Redis pod-level security context + # @default -- See [values.yaml] + securityContext: + runAsNonRoot: true + runAsUser: 999 + seccompProfile: + type: RuntimeDefault + # Redis container ports + containerPorts: + # -- Redis container port + redis: 6379 + # -- Metrics container port + metrics: 9121 + # -- Alternative DNS policy for Redis server pods + dnsPolicy: "ClusterFirst" + # -- Redis container-level security context + # @default -- See [values.yaml] + containerSecurityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + # -- Redis service port + servicePort: 6379 + # -- terminationGracePeriodSeconds for container lifecycle hook + terminationGracePeriodSeconds: 30 + # -- Automount API credentials for the Service Account into the pod. + automountServiceAccountToken: true + serviceAccount: + # -- Create a service account for the redis pod + create: false + # -- Service account name for redis pod + name: "argo-cd-dedicated-redis-sa" + # -- Automount API credentials for the Service Account + automountServiceAccountToken: false + + metrics: + # -- Deploy metrics service + enabled: true + # Redis metrics service configuration + service: + # -- Metrics service type + type: ClusterIP + # -- Metrics service clusterIP. `None` makes a "headless service" (no virtual IP) + clusterIP: None + # -- Metrics service port + servicePort: 9121 + # -- Metrics service port name + portName: http-metrics + serviceMonitor: + # -- Enable a prometheus ServiceMonitor + enabled: true + # -- Interval at which metrics should be scraped + interval: 30s + # -- Prometheus ServiceMonitor namespace + namespace: "freeleaps-monitoring-system" + +redisSecretInit: + # -- Enable Redis secret initialization. If disabled, secret must be provisioned by alternative methods + enabled: true + # -- Redis secret-init name + name: argo-cd-dedicated-redis-secret-init + # -- Application controller container-level security context + # @default -- See [values.yaml] + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + serviceAccount: + # -- Create a service account for the redis pod + create: false + +## Server +server: + # -- Argo CD server name + name: server + # -- The number of server pods to run + replicas: 1 + ## Argo CD server Horizontal Pod Autoscaler + autoscaling: + # -- Enable Horizontal Pod Autoscaler ([HPA]) for the Argo CD server + enabled: false + ## Argo CD server Pod Disruption Budget + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + pdb: + # -- Deploy a [PodDisruptionBudget] for the Argo CD server + enabled: true + # -- Number of pods that are available after eviction as number or percentage (eg.: 50%) + # @default -- `""` (defaults to 0 if not specified) + minAvailable: "1" + # -- Number of pods that are unavailable after eviction as number or percentage (eg.: 50%). + ## Has higher precedence over `server.pdb.minAvailable` + maxUnavailable: "0" + ## Argo CD server emptyDir volumes + emptyDir: + # -- EmptyDir size limit for the Argo CD server + # @default -- `""` (defaults not set if not specified i.e. no size limit) + sizeLimit: "" + # -- Resource limits and requests for the Argo CD server + resources: + limits: + cpu: "1" + memory: "512Mi" + requests: + cpu: "250m" + memory: "256Mi" + # Server container ports + containerPorts: + # -- Server container port + server: 8080 + # -- Metrics container port + metrics: 8083 + # -- Host Network for Server pods + hostNetwork: false + # -- Alternative DNS policy for Server pods + dnsPolicy: "ClusterFirst" + # -- Server container-level security context + # @default -- See [values.yaml] + containerSecurityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + ## Readiness and liveness probes for default backend + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + readinessProbe: + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + livenessProbe: + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + # -- terminationGracePeriodSeconds for container lifecycle hook + terminationGracePeriodSeconds: 30 + # TLS certificate configuration via cert-manager + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/tls/#tls-certificates-used-by-argocd-server + certificate: + # -- Deploy a Certificate resource (requires cert-manager) + enabled: false + # -- Certificate primary domain (commonName) + # @default -- `""` (defaults to global.domain) + domain: "" + # -- Certificate Subject Alternate Names (SANs) + additionalHosts: [] + # -- The requested 'duration' (i.e. lifetime) of the certificate. + # @default -- `""` (defaults to 2160h = 90d if not specified) + ## Ref: https://cert-manager.io/docs/usage/certificate/#renewal + duration: "" + # -- How long before the expiry a certificate should be renewed. + # @default -- `""` (defaults to 360h = 15d if not specified) + ## Ref: https://cert-manager.io/docs/usage/certificate/#renewal + renewBefore: "" + # Certificate issuer + ## Ref: https://cert-manager.io/docs/concepts/issuer + issuer: + # -- Certificate issuer group. Set if using an external issuer. Eg. `cert-manager.io` + group: "" + # -- Certificate issuer kind. Either `Issuer` or `ClusterIssuer` + kind: "" + # -- Certificate issuer name. Eg. `letsencrypt` + name: "" + # Private key of the certificate + privateKey: + # -- Rotation policy of private key when certificate is re-issued. Either: `Never` or `Always` + rotationPolicy: Never + # -- The private key cryptography standards (PKCS) encoding for private key. Either: `PCKS1` or `PKCS8` + encoding: PKCS1 + # -- Algorithm used to generate certificate private key. One of: `RSA`, `Ed25519` or `ECDSA` + algorithm: RSA + # -- Key bit size of the private key. If algorithm is set to `Ed25519`, size is ignored. + size: 2048 + # -- Annotations to be applied to the Server Certificate + annotations: {} + # -- Usages for the certificate + ### Ref: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.KeyUsage + usages: [] + # -- Annotations that allow the certificate to be composed from data residing in existing Kubernetes Resources + secretTemplateAnnotations: {} + + # TLS certificate configuration via Secret + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/tls/#tls-certificates-used-by-argocd-server + certificateSecret: + # -- Create argocd-server-tls secret + enabled: false + # -- Annotations to be added to argocd-server-tls secret + annotations: {} + # -- Labels to be added to argocd-server-tls secret + labels: {} + # -- Private Key of the certificate + key: '' + # -- Certificate data + crt: '' + + ## Server service configuration + service: + # -- Server service annotations + annotations: {} + # -- Server service labels + labels: {} + # -- Server service type + type: ClusterIP + # -- Server service http port for NodePort service type (only if `server.service.type` is set to "NodePort") + nodePortHttp: 30080 + # -- Server service https port for NodePort service type (only if `server.service.type` is set to "NodePort") + nodePortHttps: 30443 + # -- Server service http port + servicePortHttp: 80 + # -- Server service https port + servicePortHttps: 443 + # -- Server service http port name, can be used to route traffic via istio + servicePortHttpName: http + # -- Server service https port name, can be used to route traffic via istio + servicePortHttpsName: https + # -- Server service https port appProtocol + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol + servicePortHttpsAppProtocol: "" + # -- The class of the load balancer implementation + loadBalancerClass: "" + # -- LoadBalancer will get created with the IP specified in this field + loadBalancerIP: "" + # -- Source IP ranges to allow access to service from + ## Ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + loadBalancerSourceRanges: [] + # -- Server service external IPs + externalIPs: [] + # -- Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints + ## Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + externalTrafficPolicy: Cluster + # -- Used to maintain session affinity. Supports `ClientIP` and `None` + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + sessionAffinity: None + + ## Server metrics service configuration + metrics: + # -- Deploy metrics service + enabled: false + service: + # -- Metrics service type + type: ClusterIP + # -- Metrics service clusterIP. `None` makes a "headless service" (no virtual IP) + clusterIP: "" + # -- Metrics service annotations + annotations: {} + # -- Metrics service labels + labels: {} + # -- Metrics service port + servicePort: 8083 + # -- Metrics service port name + portName: http-metrics + serviceMonitor: + # -- Enable a prometheus ServiceMonitor + enabled: false + # -- Prometheus ServiceMonitor interval + interval: 30s + # -- Prometheus ServiceMonitor scrapeTimeout. If empty, Prometheus uses the global scrape timeout unless it is less than the target's scrape interval value in which the latter is used. + scrapeTimeout: "" + # -- When true, honorLabels preserves the metric’s labels when they collide with the target’s labels. + honorLabels: false + # -- Prometheus [RelabelConfigs] to apply to samples before scraping + relabelings: [] + # -- Prometheus [MetricRelabelConfigs] to apply to samples before ingestion + metricRelabelings: [] + # -- Prometheus ServiceMonitor selector + selector: {} + # prometheus: kube-prometheus + + # -- Prometheus ServiceMonitor scheme + scheme: "" + # -- Prometheus ServiceMonitor tlsConfig + tlsConfig: {} + # -- Prometheus ServiceMonitor namespace + namespace: "" # monitoring + # -- Prometheus ServiceMonitor labels + additionalLabels: {} + # -- Prometheus ServiceMonitor annotations + annotations: {} + + # -- Automount API credentials for the Service Account into the pod. + automountServiceAccountToken: true + + serviceAccount: + # -- Create server service account + create: true + # -- Server service account name + name: argocd-server + # -- Annotations applied to created service account + annotations: {} + # -- Labels applied to created service account + labels: {} + # -- Automount API credentials for the Service Account + automountServiceAccountToken: true + + # Argo CD server ingress configuration + ingress: + # -- Enable an ingress resource for the Argo CD server + enabled: false + # -- Specific implementation for ingress controller. One of `generic`, `aws` or `gke` + ## Additional configuration might be required in related configuration sections + controller: generic + # -- Additional ingress labels + labels: {} + # -- Additional ingress annotations + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-1-ssl-passthrough + annotations: {} + # nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + # nginx.ingress.kubernetes.io/ssl-passthrough: "true" + + # -- Defines which ingress controller will implement the resource + ingressClassName: "" + + # -- Argo CD server hostname + # @default -- `""` (defaults to global.domain) + hostname: "" + + # -- The path to Argo CD server + path: / + + # -- Ingress path type. One of `Exact`, `Prefix` or `ImplementationSpecific` + pathType: Prefix + + # -- Enable TLS configuration for the hostname defined at `server.ingress.hostname` + ## TLS certificate will be retrieved from a TLS secret `argocd-server-tls` + ## You can create this secret via `certificate` or `certificateSecret` option + tls: false + + # -- The list of additional hostnames to be covered by ingress record + # @default -- `[]` (See [values.yaml]) + extraHosts: [] + # - name: argocd.example.com + # path: / + + # -- Additional ingress paths + # @default -- `[]` (See [values.yaml]) + ## Note: Supports use of custom Helm templates + extraPaths: [] + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + + # -- Additional ingress rules + # @default -- `[]` (See [values.yaml]) + ## Note: Supports use of custom Helm templates + extraRules: [] + # - http: + # paths: + # - path: / + # pathType: Prefix + # backend: + # service: + # name: '{{ include "argo-cd.server.fullname" . }}' + # port: + # name: '{{ .Values.server.service.servicePortHttpsName }}' + + # -- Additional TLS configuration + # @default -- `[]` (See [values.yaml]) + extraTls: [] + # - hosts: + # - argocd.example.com + # secretName: your-certificate-name + + # AWS specific options for Application Load Balancer + # Applies only when `serv.ingress.controller` is set to `aws` + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#aws-application-load-balancers-albs-and-classic-elb-http-mode + aws: + # -- Backend protocol version for the AWS ALB gRPC service + ## This tells AWS to send traffic from the ALB using gRPC. + ## For more information: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html#health-check-settings + backendProtocolVersion: GRPC + # -- Service type for the AWS ALB gRPC service + ## Can be of type NodePort or ClusterIP depending on which mode you are running. + ## Instance mode needs type NodePort, IP mode needs type ClusterIP + ## Ref: https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/how-it-works/#ingress-traffic + serviceType: NodePort + + # Google specific options for Google Application Load Balancer + # Applies only when `server.ingress.controller` is set to `gke` + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#google-cloud-load-balancers-with-kubernetes-ingress + gke: + # -- Google [BackendConfig] resource, for use with the GKE Ingress Controller + # @default -- `{}` (See [values.yaml]) + ## Ref: https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#configuring_ingress_features_through_frontendconfig_parameters + backendConfig: {} + # iap: + # enabled: true + # oauthclientCredentials: + # secretName: argocd-secret + + # -- Google [FrontendConfig] resource, for use with the GKE Ingress Controller + # @default -- `{}` (See [values.yaml]) + ## Ref: https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#configuring_ingress_features_through_frontendconfig_parameters + frontendConfig: {} + # redirectToHttps: + # enabled: true + # responseCodeName: RESPONSE_CODE + + # Managed GKE certificate for ingress hostname + managedCertificate: + # -- Create ManagedCertificate resource and annotations for Google Load balancer + ## Ref: https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs + create: true + # -- Additional domains for ManagedCertificate resource + extraDomains: [] + # - argocd.example.com + + # Dedicated gRPC ingress for ingress controllers that supports only single backend protocol per Ingress resource + # Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-2-multiple-ingress-objects-and-hosts + ingressGrpc: + # -- Enable an ingress resource for the Argo CD server for dedicated [gRPC-ingress] + enabled: false + # -- Additional ingress annotations for dedicated [gRPC-ingress] + annotations: {} + # -- Additional ingress labels for dedicated [gRPC-ingress] + labels: {} + # -- Defines which ingress controller will implement the resource [gRPC-ingress] + ingressClassName: "" + + # -- Argo CD server hostname for dedicated [gRPC-ingress] + # @default -- `""` (defaults to grpc.`server.ingress.hostname`) + hostname: "" + + # -- Argo CD server ingress path for dedicated [gRPC-ingress] + path: / + + # -- Ingress path type for dedicated [gRPC-ingress]. One of `Exact`, `Prefix` or `ImplementationSpecific` + pathType: Prefix + + # -- Enable TLS configuration for the hostname defined at `server.ingressGrpc.hostname` + ## TLS certificate will be retrieved from a TLS secret with name: `argocd-server-grpc-tls` + tls: false + + # -- The list of additional hostnames to be covered by ingress record + # @default -- `[]` (See [values.yaml]) + extraHosts: [] + # - name: grpc.argocd.example.com + # path: / + + # -- Additional ingress paths for dedicated [gRPC-ingress] + # @default -- `[]` (See [values.yaml]) + ## Note: Supports use of custom Helm templates + extraPaths: [] + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + + # -- Additional ingress rules + # @default -- `[]` (See [values.yaml]) + ## Note: Supports use of custom Helm templates + extraRules: [] + # - http: + # paths: + # - path: / + # pathType: Prefix + # backend: + # service: + # name: '{{ include "argo-cd.server.fullname" . }}' + # port: + # name: '{{ .Values.server.service.servicePortHttpName }}' + + # -- Additional TLS configuration for dedicated [gRPC-ingress] + # @default -- `[]` (See [values.yaml]) + extraTls: [] + # - secretName: your-certificate-name + # hosts: + # - argocd.example.com + + # Create a OpenShift Route with SSL passthrough for UI and CLI + # Consider setting 'hostname' e.g. https://argocd.apps-crc.testing/ using your Default Ingress Controller Domain + # Find your domain with: kubectl describe --namespace=openshift-ingress-operator ingresscontroller/default | grep Domain: + # If 'hostname' is an empty string "" OpenShift will create a hostname for you. + route: + # -- Enable an OpenShift Route for the Argo CD server + enabled: false + # -- Openshift Route annotations + annotations: {} + # -- Hostname of OpenShift Route + hostname: "" + # -- Termination type of Openshift Route + termination_type: passthrough + # -- Termination policy of Openshift Route + termination_policy: None + + ## Enable this and set the rules: to whatever custom rules you want for the Cluster Role resource. + ## Defaults to off + clusterRoleRules: + # -- Enable custom rules for the server's ClusterRole resource + enabled: false + # -- List of custom rules for the server's ClusterRole resource + rules: [] + +## Repo Server +repoServer: + # -- Repo server name + name: repo-server + + # -- The number of repo server pods to run + replicas: 1 + + # -- Runtime class name for the repo server + # @default -- `""` (defaults to global.runtimeClassName) + runtimeClassName: "" + + ## Repo server Horizontal Pod Autoscaler + autoscaling: + # -- Enable Horizontal Pod Autoscaler ([HPA]) for the repo server + enabled: false + # -- Minimum number of replicas for the repo server [HPA] + minReplicas: 1 + # -- Maximum number of replicas for the repo server [HPA] + maxReplicas: 5 + # -- Average CPU utilization percentage for the repo server [HPA] + targetCPUUtilizationPercentage: 50 + # -- Average memory utilization percentage for the repo server [HPA] + targetMemoryUtilizationPercentage: 50 + # -- Configures the scaling behavior of the target in both Up and Down directions. + behavior: {} + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 2 + # periodSeconds: 60 + # -- Configures custom HPA metrics for the Argo CD repo server + # Ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ + metrics: [] + + ## Repo server Pod Disruption Budget + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + pdb: + # -- Deploy a [PodDisruptionBudget] for the repo server + enabled: false + # -- Labels to be added to repo server pdb + labels: {} + # -- Annotations to be added to repo server pdb + annotations: {} + # -- Number of pods that are available after eviction as number or percentage (eg.: 50%) + # @default -- `""` (defaults to 0 if not specified) + minAvailable: "" + # -- Number of pods that are unavailable after eviction as number or percentage (eg.: 50%). + ## Has higher precedence over `repoServer.pdb.minAvailable` + maxUnavailable: "" + + ## Repo server image + image: + # -- Repository to use for the repo server + # @default -- `""` (defaults to global.image.repository) + repository: "" + # -- Tag to use for the repo server + # @default -- `""` (defaults to global.image.tag) + tag: "" + # -- Image pull policy for the repo server + # @default -- `""` (defaults to global.image.imagePullPolicy) + imagePullPolicy: "" + + # -- Secrets with credentials to pull images from a private registry + # @default -- `[]` (defaults to global.imagePullSecrets) + imagePullSecrets: [] + + # -- Additional command line arguments to pass to repo server + extraArgs: [] + + # -- Environment variables to pass to repo server + env: [] + + # -- envFrom to pass to repo server + # @default -- `[]` (See [values.yaml]) + envFrom: [] + # - configMapRef: + # name: config-map-name + # - secretRef: + # name: secret-name + + # -- Specify postStart and preStop lifecycle hooks for your argo-repo-server container + lifecycle: {} + + # -- Additional containers to be added to the repo server pod + ## Ref: https://argo-cd.readthedocs.io/en/stable/user-guide/config-management-plugins/ + ## Note: Supports use of custom Helm templates + extraContainers: [] + # - name: cmp-my-plugin + # command: + # - "/var/run/argocd/argocd-cmp-server" + # image: busybox + # securityContext: + # runAsNonRoot: true + # runAsUser: 999 + # volumeMounts: + # - mountPath: /var/run/argocd + # name: var-files + # - mountPath: /home/argocd/cmp-server/plugins + # name: plugins + # # Remove this volumeMount if you've chosen to bake the config file into the sidecar image. + # - mountPath: /home/argocd/cmp-server/config/plugin.yaml + # subPath: my-plugin.yaml + # name: argocd-cmp-cm + # # Starting with v2.4, do NOT mount the same tmp volume as the repo-server container. The filesystem separation helps + # # mitigate path traversal attacks. + # - mountPath: /tmp + # name: cmp-tmp + # - name: cmp-my-plugin2 + # command: + # - "/var/run/argocd/argocd-cmp-server" + # image: busybox + # securityContext: + # runAsNonRoot: true + # runAsUser: 999 + # volumeMounts: + # - mountPath: /var/run/argocd + # name: var-files + # # Remove this volumeMount if you've chosen to bake the config file into the sidecar image. + # - mountPath: /home/argocd/cmp-server/plugins + # name: plugins + # - mountPath: /home/argocd/cmp-server/config/plugin.yaml + # subPath: my-plugin2.yaml + # name: argocd-cmp-cm + # # Starting with v2.4, do NOT mount the same tmp volume as the repo-server container. The filesystem separation helps + # # mitigate path traversal attacks. + # - mountPath: /tmp + # name: cmp-tmp + + # -- Init containers to add to the repo server pods + initContainers: [] + + # -- Additional volumeMounts to the repo server main container + volumeMounts: [] + + # -- Additional volumes to the repo server pod + volumes: [] + # - name: argocd-cmp-cm + # configMap: + # name: argocd-cmp-cm + # - name: cmp-tmp + # emptyDir: {} + + # -- Volumes to be used in replacement of emptydir on default volumes + existingVolumes: {} + # gpgKeyring: + # persistentVolumeClaim: + # claimName: pvc-argocd-repo-server-keyring + # helmWorkingDir: + # persistentVolumeClaim: + # claimName: pvc-argocd-repo-server-workdir + # tmp: + # persistentVolumeClaim: + # claimName: pvc-argocd-repo-server-tmp + # varFiles: + # persistentVolumeClaim: + # claimName: pvc-argocd-repo-server-varfiles + # plugins: + # persistentVolumeClaim: + # claimName: pvc-argocd-repo-server-plugins + + ## RepoServer emptyDir volumes + emptyDir: + # -- EmptyDir size limit for repo server + # @default -- `""` (defaults not set if not specified i.e. no size limit) + sizeLimit: "" + # sizeLimit: "1Gi" + + # -- Toggle the usage of a ephemeral Helm working directory + useEphemeralHelmWorkingDir: true + + # -- Annotations to be added to repo server Deployment + deploymentAnnotations: {} + + # -- Annotations to be added to repo server pods + podAnnotations: {} + + # -- Labels to be added to repo server pods + podLabels: {} + + # -- Resource limits and requests for the repo server pods + resources: {} + # limits: + # cpu: 50m + # memory: 128Mi + # requests: + # cpu: 10m + # memory: 64Mi + + # Repo server container ports + containerPorts: + # -- Repo server container port + server: 8081 + # -- Metrics container port + metrics: 8084 + + # -- Host Network for Repo server pods + hostNetwork: false + + # -- [DNS configuration] + dnsConfig: {} + # -- Alternative DNS policy for Repo server pods + dnsPolicy: "ClusterFirst" + + # -- Repo server container-level security context + # @default -- See [values.yaml] + containerSecurityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + + ## Readiness and liveness probes for default backend + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + readinessProbe: + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + + livenessProbe: + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + + # -- terminationGracePeriodSeconds for container lifecycle hook + terminationGracePeriodSeconds: 30 + + # -- [Node selector] + # @default -- `{}` (defaults to global.nodeSelector) + nodeSelector: {} + + # -- [Tolerations] for use with node taints + # @default -- `[]` (defaults to global.tolerations) + tolerations: [] + + # -- Assign custom [affinity] rules to the deployment + # @default -- `{}` (defaults to global.affinity preset) + affinity: {} + + # -- Assign custom [TopologySpreadConstraints] rules to the repo server + # @default -- `[]` (defaults to global.topologySpreadConstraints) + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## If labelSelector is left out, it will default to the labelSelector configuration of the deployment + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Deployment strategy to be added to the repo server Deployment + deploymentStrategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 25% + # maxUnavailable: 25% + + # -- Priority class for the repo server pods + # @default -- `""` (defaults to global.priorityClassName) + priorityClassName: "" + + # TLS certificate configuration via Secret + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/tls/#configuring-tls-to-argocd-repo-server + ## Note: Issuing certificates via cert-manager in not supported right now because it's not possible to restart repo server automatically without extra controllers. + certificateSecret: + # -- Create argocd-repo-server-tls secret + enabled: false + # -- Annotations to be added to argocd-repo-server-tls secret + annotations: {} + # -- Labels to be added to argocd-repo-server-tls secret + labels: {} + # -- Certificate authority. Required for self-signed certificates. + ca: '' + # -- Certificate private key + key: '' + # -- Certificate data. Must contain SANs of Repo service (ie: argocd-repo-server, argocd-repo-server.argo-cd.svc) + crt: '' + + ## Repo server service configuration + service: + # -- Repo server service annotations + annotations: {} + # -- Repo server service labels + labels: {} + # -- Repo server service port + port: 8081 + # -- Repo server service port name + portName: tcp-repo-server + + ## Repo server metrics service configuration + metrics: + # -- Deploy metrics service + enabled: false + service: + # -- Metrics service type + type: ClusterIP + # -- Metrics service clusterIP. `None` makes a "headless service" (no virtual IP) + clusterIP: "" + # -- Metrics service annotations + annotations: {} + # -- Metrics service labels + labels: {} + # -- Metrics service port + servicePort: 8084 + # -- Metrics service port name + portName: http-metrics + serviceMonitor: + # -- Enable a prometheus ServiceMonitor + enabled: false + # -- Prometheus ServiceMonitor interval + interval: 30s + # -- Prometheus ServiceMonitor scrapeTimeout. If empty, Prometheus uses the global scrape timeout unless it is less than the target's scrape interval value in which the latter is used. + scrapeTimeout: "" + # -- When true, honorLabels preserves the metric’s labels when they collide with the target’s labels. + honorLabels: false + # -- Prometheus [RelabelConfigs] to apply to samples before scraping + relabelings: [] + # -- Prometheus [MetricRelabelConfigs] to apply to samples before ingestion + metricRelabelings: [] + # -- Prometheus ServiceMonitor selector + selector: {} + # prometheus: kube-prometheus + + # -- Prometheus ServiceMonitor scheme + scheme: "" + # -- Prometheus ServiceMonitor tlsConfig + tlsConfig: {} + # -- Prometheus ServiceMonitor namespace + namespace: "" # "monitoring" + # -- Prometheus ServiceMonitor labels + additionalLabels: {} + # -- Prometheus ServiceMonitor annotations + annotations: {} + + ## Enable Custom Rules for the Repo server's Cluster Role resource + ## Enable this and set the rules: to whatever custom rules you want for the Cluster Role resource. + ## Defaults to off + clusterRoleRules: + # -- Enable custom rules for the Repo server's Cluster Role resource + enabled: false + # -- List of custom rules for the Repo server's Cluster Role resource + rules: [] + + # -- Automount API credentials for the Service Account into the pod. + automountServiceAccountToken: true + + ## Repo server service account + ## If create is set to true, make sure to uncomment the name and update the rbac section below + serviceAccount: + # -- Create repo server service account + create: true + # -- Repo server service account name + name: "" # "argocd-repo-server" + # -- Annotations applied to created service account + annotations: {} + # -- Labels applied to created service account + labels: {} + # -- Automount API credentials for the Service Account + automountServiceAccountToken: true + + # -- Repo server rbac rules + rbac: [] + # - apiGroups: + # - argoproj.io + # resources: + # - applications + # verbs: + # - get + # - list + # - watch + +## ApplicationSet controller +applicationSet: + # -- ApplicationSet controller name string + name: applicationset-controller + + # -- The number of ApplicationSet controller pods to run + replicas: 1 + + # -- Runtime class name for the ApplicationSet controller + # @default -- `""` (defaults to global.runtimeClassName) + runtimeClassName: "" + + ## ApplicationSet controller Pod Disruption Budget + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + pdb: + # -- Deploy a [PodDisruptionBudget] for the ApplicationSet controller + enabled: false + # -- Labels to be added to ApplicationSet controller pdb + labels: {} + # -- Annotations to be added to ApplicationSet controller pdb + annotations: {} + # -- Number of pods that are available after eviction as number or percentage (eg.: 50%) + # @default -- `""` (defaults to 0 if not specified) + minAvailable: "" + # -- Number of pods that are unavailable after eviction as number or percentage (eg.: 50%). + ## Has higher precedence over `applicationSet.pdb.minAvailable` + maxUnavailable: "" + + ## ApplicationSet controller image + image: + # -- Repository to use for the ApplicationSet controller + # @default -- `""` (defaults to global.image.repository) + repository: "" + # -- Tag to use for the ApplicationSet controller + # @default -- `""` (defaults to global.image.tag) + tag: "" + # -- Image pull policy for the ApplicationSet controller + # @default -- `""` (defaults to global.image.imagePullPolicy) + imagePullPolicy: "" + + # -- If defined, uses a Secret to pull an image from a private Docker registry or repository. + # @default -- `[]` (defaults to global.imagePullSecrets) + imagePullSecrets: [] + + # -- ApplicationSet controller command line flags + extraArgs: [] + + # -- Environment variables to pass to the ApplicationSet controller + extraEnv: [] + # - name: "MY_VAR" + # value: "value" + + # -- envFrom to pass to the ApplicationSet controller + # @default -- `[]` (See [values.yaml]) + extraEnvFrom: [] + # - configMapRef: + # name: config-map-name + # - secretRef: + # name: secret-name + + # -- Additional containers to be added to the ApplicationSet controller pod + ## Note: Supports use of custom Helm templates + extraContainers: [] + + # -- Init containers to add to the ApplicationSet controller pod + ## Note: Supports use of custom Helm templates + initContainers: [] + + # -- List of extra mounts to add (normally used with extraVolumes) + extraVolumeMounts: [] + + # -- List of extra volumes to add + extraVolumes: [] + + ## ApplicationSet controller emptyDir volumes + emptyDir: + # -- EmptyDir size limit for applicationSet controller + # @default -- `""` (defaults not set if not specified i.e. no size limit) + sizeLimit: "" + # sizeLimit: "1Gi" + + ## Metrics service configuration + metrics: + # -- Deploy metrics service + enabled: false + service: + # -- Metrics service type + type: ClusterIP + # -- Metrics service clusterIP. `None` makes a "headless service" (no virtual IP) + clusterIP: "" + # -- Metrics service annotations + annotations: {} + # -- Metrics service labels + labels: {} + # -- Metrics service port + servicePort: 8080 + # -- Metrics service port name + portName: http-metrics + serviceMonitor: + # -- Enable a prometheus ServiceMonitor + enabled: false + # -- Prometheus ServiceMonitor interval + interval: 30s + # -- Prometheus ServiceMonitor scrapeTimeout. If empty, Prometheus uses the global scrape timeout unless it is less than the target's scrape interval value in which the latter is used. + scrapeTimeout: "" + # -- When true, honorLabels preserves the metric’s labels when they collide with the target’s labels. + honorLabels: false + # -- Prometheus [RelabelConfigs] to apply to samples before scraping + relabelings: [] + # -- Prometheus [MetricRelabelConfigs] to apply to samples before ingestion + metricRelabelings: [] + # -- Prometheus ServiceMonitor selector + selector: {} + # prometheus: kube-prometheus + + # -- Prometheus ServiceMonitor scheme + scheme: "" + # -- Prometheus ServiceMonitor tlsConfig + tlsConfig: {} + # -- Prometheus ServiceMonitor namespace + namespace: "" # monitoring + # -- Prometheus ServiceMonitor labels + additionalLabels: {} + # -- Prometheus ServiceMonitor annotations + annotations: {} + + ## ApplicationSet service configuration + service: + # -- ApplicationSet service annotations + annotations: {} + # -- ApplicationSet service labels + labels: {} + # -- ApplicationSet service type + type: ClusterIP + # -- ApplicationSet service port + port: 7000 + # -- ApplicationSet service port name + portName: http-webhook + + # -- Automount API credentials for the Service Account into the pod. + automountServiceAccountToken: true + + serviceAccount: + # -- Create ApplicationSet controller service account + create: true + # -- ApplicationSet controller service account name + name: argocd-applicationset-controller + # -- Annotations applied to created service account + annotations: {} + # -- Labels applied to created service account + labels: {} + # -- Automount API credentials for the Service Account + automountServiceAccountToken: true + + # -- Annotations to be added to ApplicationSet controller Deployment + deploymentAnnotations: {} + + # -- Annotations for the ApplicationSet controller pods + podAnnotations: {} + + # -- Labels for the ApplicationSet controller pods + podLabels: {} + + # -- Resource limits and requests for the ApplicationSet controller pods. + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # ApplicationSet controller container ports + containerPorts: + # -- Metrics container port + metrics: 8080 + # -- Probe container port + probe: 8081 + # -- Webhook container port + webhook: 7000 + + # -- [DNS configuration] + dnsConfig: {} + # -- Alternative DNS policy for ApplicationSet controller pods + dnsPolicy: "ClusterFirst" + + # -- ApplicationSet controller container-level security context + # @default -- See [values.yaml] + containerSecurityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + + ## Probes for ApplicationSet controller (optional) + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + readinessProbe: + # -- Enable Kubernetes liveness probe for ApplicationSet controller + enabled: false + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + + livenessProbe: + # -- Enable Kubernetes liveness probe for ApplicationSet controller + enabled: false + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + + # -- terminationGracePeriodSeconds for container lifecycle hook + terminationGracePeriodSeconds: 30 + + # -- [Node selector] + # @default -- `{}` (defaults to global.nodeSelector) + nodeSelector: {} + + # -- [Tolerations] for use with node taints + # @default -- `[]` (defaults to global.tolerations) + tolerations: [] + + # -- Assign custom [affinity] rules + # @default -- `{}` (defaults to global.affinity preset) + affinity: {} + + # -- Assign custom [TopologySpreadConstraints] rules to the ApplicationSet controller + # @default -- `[]` (defaults to global.topologySpreadConstraints) + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## If labelSelector is left out, it will default to the labelSelector configuration of the deployment + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Deployment strategy to be added to the ApplicationSet controller Deployment + deploymentStrategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 25% + # maxUnavailable: 25% + + # -- Priority class for the ApplicationSet controller pods + # @default -- `""` (defaults to global.priorityClassName) + priorityClassName: "" + + # TLS certificate configuration via cert-manager + ## Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/tls/#tls-configuration + certificate: + # -- Deploy a Certificate resource (requires cert-manager) + enabled: false + # -- Certificate primary domain (commonName) + # @default -- `""` (defaults to global.domain) + domain: "" + # -- Certificate Subject Alternate Names (SANs) + additionalHosts: [] + # -- The requested 'duration' (i.e. lifetime) of the certificate. + # @default -- `""` (defaults to 2160h = 90d if not specified) + ## Ref: https://cert-manager.io/docs/usage/certificate/#renewal + duration: "" + # -- How long before the expiry a certificate should be renewed. + # @default -- `""` (defaults to 360h = 15d if not specified) + ## Ref: https://cert-manager.io/docs/usage/certificate/#renewal + renewBefore: "" + # Certificate issuer + ## Ref: https://cert-manager.io/docs/concepts/issuer + issuer: + # -- Certificate issuer group. Set if using an external issuer. Eg. `cert-manager.io` + group: "" + # -- Certificate issuer kind. Either `Issuer` or `ClusterIssuer` + kind: "" + # -- Certificate issuer name. Eg. `letsencrypt` + name: "" + # Private key of the certificate + privateKey: + # -- Rotation policy of private key when certificate is re-issued. Either: `Never` or `Always` + rotationPolicy: Never + # -- The private key cryptography standards (PKCS) encoding for private key. Either: `PCKS1` or `PKCS8` + encoding: PKCS1 + # -- Algorithm used to generate certificate private key. One of: `RSA`, `Ed25519` or `ECDSA` + algorithm: RSA + # -- Key bit size of the private key. If algorithm is set to `Ed25519`, size is ignored. + size: 2048 + # -- Annotations to be applied to the ApplicationSet Certificate + annotations: {} + + ## Ingress for the Git Generator webhook + ## Ref: https://argocd-applicationset.readthedocs.io/en/master/Generators-Git/#webhook-configuration) + ingress: + # -- Enable an ingress resource for ApplicationSet webhook + enabled: false + # -- Additional ingress labels + labels: {} + # -- Additional ingress annotations + annotations: {} + + # -- Defines which ingress ApplicationSet controller will implement the resource + ingressClassName: "" + + # -- Argo CD ApplicationSet hostname + # @default -- `""` (defaults to global.domain) + hostname: "" + + # -- List of ingress paths + path: /api/webhook + + # -- Ingress path type. One of `Exact`, `Prefix` or `ImplementationSpecific` + pathType: Prefix + + # -- Enable TLS configuration for the hostname defined at `applicationSet.webhook.ingress.hostname` + ## TLS certificate will be retrieved from a TLS secret with name:`argocd-applicationset-controller-tls` + tls: false + + # -- The list of additional hostnames to be covered by ingress record + # @default -- `[]` (See [values.yaml]) + extraHosts: [] + # - name: argocd.example.com + # path: / + + # -- Additional ingress paths + # @default -- `[]` (See [values.yaml]) + extraPaths: [] + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + + # -- Additional ingress rules + # @default -- `[]` (See [values.yaml]) + ## Note: Supports use of custom Helm templates + extraRules: [] + # - http: + # paths: + # - path: /api/webhook + # pathType: Prefix + # backend: + # service: + # name: '{{ include "argo-cd.applicationSet.fullname" . }}' + # port: + # name: '{{ .Values.applicationSet.service.portName }}' + + # -- Additional ingress TLS configuration + # @default -- `[]` (See [values.yaml]) + extraTls: [] + # - secretName: argocd-applicationset-tls + # hosts: + # - argocd-applicationset.example.com + # -- Enable ApplicationSet in any namespace feature + allowAnyNamespace: false +## Notifications controller +notifications: + # -- Enable notifications controller + enabled: true + + # -- Notifications controller name string + name: notifications-controller + + # -- Argo CD dashboard url; used in place of {{.context.argocdUrl}} in templates + # @default -- `""` (defaults to https://`global.domain`) + argocdUrl: "" + + # -- Runtime class name for the notifications controller + # @default -- `""` (defaults to global.runtimeClassName) + runtimeClassName: "" + + ## Notifications controller Pod Disruption Budget + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + pdb: + # -- Deploy a [PodDisruptionBudget] for the notifications controller + enabled: false + # -- Labels to be added to notifications controller pdb + labels: {} + # -- Annotations to be added to notifications controller pdb + annotations: {} + # -- Number of pods that are available after eviction as number or percentage (eg.: 50%) + # @default -- `""` (defaults to 0 if not specified) + minAvailable: "" + # -- Number of pods that are unavailable after eviction as number or percentage (eg.: 50%). + ## Has higher precedence over `notifications.pdb.minAvailable` + maxUnavailable: "" + + ## Notifications controller image + image: + # -- Repository to use for the notifications controller + # @default -- `""` (defaults to global.image.repository) + repository: "" + # -- Tag to use for the notifications controller + # @default -- `""` (defaults to global.image.tag) + tag: "" + # -- Image pull policy for the notifications controller + # @default -- `""` (defaults to global.image.imagePullPolicy) + imagePullPolicy: "" + + # -- Secrets with credentials to pull images from a private registry + # @default -- `[]` (defaults to global.imagePullSecrets) + imagePullSecrets: [] + + # -- Notifications controller log format. Either `text` or `json` + # @default -- `""` (defaults to global.logging.format) + logFormat: "" + # -- Notifications controller log level. One of: `debug`, `info`, `warn`, `error` + # @default -- `""` (defaults to global.logging.level) + logLevel: "" + + # -- Extra arguments to provide to the notifications controller + extraArgs: [] + + # -- Additional container environment variables + extraEnv: [] + + # -- envFrom to pass to the notifications controller + # @default -- `[]` (See [values.yaml]) + extraEnvFrom: [] + # - configMapRef: + # name: config-map-name + # - secretRef: + # name: secret-name + + # -- Additional containers to be added to the notifications controller pod + ## Note: Supports use of custom Helm templates + extraContainers: [] + + # -- Init containers to add to the notifications controller pod + ## Note: Supports use of custom Helm templates + initContainers: [] + + # -- List of extra mounts to add (normally used with extraVolumes) + extraVolumeMounts: [] + + # -- List of extra volumes to add + extraVolumes: [] + + # -- Define user-defined context + ## For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/templates/#defining-user-defined-context + context: {} + # region: east + # environmentName: staging + + secret: + # -- Whether helm chart creates notifications controller secret + ## If true, will create a secret with the name below. Otherwise, will assume existence of a secret with that name. + create: true + + # -- notifications controller Secret name + name: "argocd-notifications-secret" + + # -- key:value pairs of annotations to be added to the secret + annotations: {} + + # -- key:value pairs of labels to be added to the secret + labels: {} + + # -- Generic key:value pairs to be inserted into the secret + ## Can be used for templates, notification services etc. Some examples given below. + ## For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/services/overview/ + items: {} + # slack-token: + # # For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/services/slack/ + + # grafana-apiKey: + # # For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/services/grafana/ + + # webhooks-github-token: + + # email-username: + # email-password: + # For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/services/email/ + + metrics: + # -- Enables prometheus metrics server + enabled: false + # -- Metrics port + port: 9001 + service: + # -- Metrics service type + type: ClusterIP + # -- Metrics service clusterIP. `None` makes a "headless service" (no virtual IP) + clusterIP: "" + # -- Metrics service annotations + annotations: {} + # -- Metrics service labels + labels: {} + # -- Metrics service port name + portName: http-metrics + serviceMonitor: + # -- Enable a prometheus ServiceMonitor + enabled: false + # -- Prometheus ServiceMonitor selector + selector: {} + # prometheus: kube-prometheus + # -- Prometheus ServiceMonitor labels + additionalLabels: {} + # -- Prometheus ServiceMonitor annotations + annotations: {} + # namespace: monitoring + # interval: 30s + # scrapeTimeout: 10s + # -- Prometheus ServiceMonitor scheme + scheme: "" + # -- Prometheus ServiceMonitor tlsConfig + tlsConfig: {} + # -- When true, honorLabels preserves the metric’s labels when they collide with the target’s labels. + honorLabels: false + # -- Prometheus [RelabelConfigs] to apply to samples before scraping + relabelings: [] + # -- Prometheus [MetricRelabelConfigs] to apply to samples before ingestion + metricRelabelings: [] + + # -- Configures notification services such as slack, email or custom webhook + # @default -- See [values.yaml] + ## For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/services/overview/ + notifiers: {} + # service.slack: | + # token: $slack-token + + # -- Annotations to be applied to the notifications controller Deployment + deploymentAnnotations: {} + + # -- Annotations to be applied to the notifications controller Pods + podAnnotations: {} + + # -- Labels to be applied to the notifications controller Pods + podLabels: {} + + # -- Resource limits and requests for the notifications controller + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # Notification controller container ports + containerPorts: + # -- Metrics container port + metrics: 9001 + + # -- [DNS configuration] + dnsConfig: {} + # -- Alternative DNS policy for notifications controller Pods + dnsPolicy: "ClusterFirst" + + # -- Notification controller container-level security Context + # @default -- See [values.yaml] + containerSecurityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + seccompProfile: + type: RuntimeDefault + capabilities: + drop: + - ALL + + ## Probes for notifications controller Pods (optional) + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ + readinessProbe: + # -- Enable Kubernetes liveness probe for notifications controller Pods + enabled: false + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + + livenessProbe: + # -- Enable Kubernetes liveness probe for notifications controller Pods + enabled: false + # -- Number of seconds after the container has started before [probe] is initiated + initialDelaySeconds: 10 + # -- How often (in seconds) to perform the [probe] + periodSeconds: 10 + # -- Number of seconds after which the [probe] times out + timeoutSeconds: 1 + # -- Minimum consecutive successes for the [probe] to be considered successful after having failed + successThreshold: 1 + # -- Minimum consecutive failures for the [probe] to be considered failed after having succeeded + failureThreshold: 3 + + # -- terminationGracePeriodSeconds for container lifecycle hook + terminationGracePeriodSeconds: 30 + + # -- [Node selector] + # @default -- `{}` (defaults to global.nodeSelector) + nodeSelector: {} + + # -- [Tolerations] for use with node taints + # @default -- `[]` (defaults to global.tolerations) + tolerations: [] + + # -- Assign custom [affinity] rules + # @default -- `{}` (defaults to global.affinity preset) + affinity: {} + + # -- Assign custom [TopologySpreadConstraints] rules to the application controller + # @default -- `[]` (defaults to global.topologySpreadConstraints) + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## If labelSelector is left out, it will default to the labelSelector configuration of the deployment + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + + # -- Deployment strategy to be added to the notifications controller Deployment + deploymentStrategy: + type: Recreate + + # -- Priority class for the notifications controller pods + # @default -- `""` (defaults to global.priorityClassName) + priorityClassName: "" + + # -- Automount API credentials for the Service Account into the pod. + automountServiceAccountToken: true + + serviceAccount: + # -- Create notifications controller service account + create: true + # -- Notification controller service account name + name: argocd-notifications-controller + # -- Annotations applied to created service account + annotations: {} + # -- Labels applied to created service account + labels: {} + # -- Automount API credentials for the Service Account + automountServiceAccountToken: true + + cm: + # -- Whether helm chart creates notifications controller config map + create: true + + ## Enable this and set the rules: to whatever custom rules you want for the Cluster Role resource. + ## Defaults to off + clusterRoleRules: + # -- List of custom rules for the notifications controller's ClusterRole resource + rules: [] + + # -- Contains centrally managed global application subscriptions + ## For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/subscriptions/ + subscriptions: [] + # # subscription for on-sync-status-unknown trigger notifications + # - recipients: + # - slack:test2 + # - email:test@gmail.com + # triggers: + # - on-sync-status-unknown + # # subscription restricted to applications with matching labels only + # - recipients: + # - slack:test3 + # selector: test=true + # triggers: + # - on-sync-status-unknown + + # -- The notification template is used to generate the notification content + ## For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/templates/ + templates: {} + # template.app-deployed: | + # email: + # subject: New version of an application {{.app.metadata.name}} is up and running. + # message: | + # {{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} is now running new version of deployments manifests. + # slack: + # attachments: | + # [{ + # "title": "{{ .app.metadata.name}}", + # "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", + # "color": "#18be52", + # "fields": [ + # { + # "title": "Sync Status", + # "value": "{{.app.status.sync.status}}", + # "short": true + # }, + # { + # "title": "Repository", + # "value": "{{.app.spec.source.repoURL}}", + # "short": true + # }, + # { + # "title": "Revision", + # "value": "{{.app.status.sync.revision}}", + # "short": true + # } + # {{range $index, $c := .app.status.conditions}} + # {{if not $index}},{{end}} + # {{if $index}},{{end}} + # { + # "title": "{{$c.type}}", + # "value": "{{$c.message}}", + # "short": true + # } + # {{end}} + # ] + # }] + # template.app-health-degraded: | + # email: + # subject: Application {{.app.metadata.name}} has degraded. + # message: | + # {{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} has degraded. + # Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}. + # slack: + # attachments: |- + # [{ + # "title": "{{ .app.metadata.name}}", + # "title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", + # "color": "#f4c030", + # "fields": [ + # { + # "title": "Sync Status", + # "value": "{{.app.status.sync.status}}", + # "short": true + # }, + # { + # "title": "Repository", + # "value": "{{.app.spec.source.repoURL}}", + # "short": true + # } + # {{range $index, $c := .app.status.conditions}} + # {{if not $index}},{{end}} + # {{if $index}},{{end}} + # { + # "title": "{{$c.type}}", + # "value": "{{$c.message}}", + # "short": true + # } + # {{end}} + # ] + # }] + # template.app-sync-failed: | + # email: + # subject: Failed to sync application {{.app.metadata.name}}. + # message: | + # {{if eq .serviceType "slack"}}:exclamation:{{end}} The sync operation of application {{.app.metadata.name}} has failed at {{.app.status.operationState.finishedAt}} with the following error: {{.app.status.operationState.message}} + # Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true . + # slack: + # attachments: |- + # [{ + # "title": "{{ .app.metadata.name}}", + # "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", + # "color": "#E96D76", + # "fields": [ + # { + # "title": "Sync Status", + # "value": "{{.app.status.sync.status}}", + # "short": true + # }, + # { + # "title": "Repository", + # "value": "{{.app.spec.source.repoURL}}", + # "short": true + # } + # {{range $index, $c := .app.status.conditions}} + # {{if not $index}},{{end}} + # {{if $index}},{{end}} + # { + # "title": "{{$c.type}}", + # "value": "{{$c.message}}", + # "short": true + # } + # {{end}} + # ] + # }] + # template.app-sync-running: | + # email: + # subject: Start syncing application {{.app.metadata.name}}. + # message: | + # The sync operation of application {{.app.metadata.name}} has started at {{.app.status.operationState.startedAt}}. + # Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true . + # slack: + # attachments: |- + # [{ + # "title": "{{ .app.metadata.name}}", + # "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", + # "color": "#0DADEA", + # "fields": [ + # { + # "title": "Sync Status", + # "value": "{{.app.status.sync.status}}", + # "short": true + # }, + # { + # "title": "Repository", + # "value": "{{.app.spec.source.repoURL}}", + # "short": true + # } + # {{range $index, $c := .app.status.conditions}} + # {{if not $index}},{{end}} + # {{if $index}},{{end}} + # { + # "title": "{{$c.type}}", + # "value": "{{$c.message}}", + # "short": true + # } + # {{end}} + # ] + # }] + # template.app-sync-status-unknown: | + # email: + # subject: Application {{.app.metadata.name}} sync status is 'Unknown' + # message: | + # {{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} sync is 'Unknown'. + # Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}. + # {{if ne .serviceType "slack"}} + # {{range $c := .app.status.conditions}} + # * {{$c.message}} + # {{end}} + # {{end}} + # slack: + # attachments: |- + # [{ + # "title": "{{ .app.metadata.name}}", + # "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", + # "color": "#E96D76", + # "fields": [ + # { + # "title": "Sync Status", + # "value": "{{.app.status.sync.status}}", + # "short": true + # }, + # { + # "title": "Repository", + # "value": "{{.app.spec.source.repoURL}}", + # "short": true + # } + # {{range $index, $c := .app.status.conditions}} + # {{if not $index}},{{end}} + # {{if $index}},{{end}} + # { + # "title": "{{$c.type}}", + # "value": "{{$c.message}}", + # "short": true + # } + # {{end}} + # ] + # }] + # template.app-sync-succeeded: | + # email: + # subject: Application {{.app.metadata.name}} has been successfully synced. + # message: | + # {{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} has been successfully synced at {{.app.status.operationState.finishedAt}}. + # Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true . + # slack: + # attachments: |- + # [{ + # "title": "{{ .app.metadata.name}}", + # "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", + # "color": "#18be52", + # "fields": [ + # { + # "title": "Sync Status", + # "value": "{{.app.status.sync.status}}", + # "short": true + # }, + # { + # "title": "Repository", + # "value": "{{.app.spec.source.repoURL}}", + # "short": true + # } + # {{range $index, $c := .app.status.conditions}} + # {{if not $index}},{{end}} + # {{if $index}},{{end}} + # { + # "title": "{{$c.type}}", + # "value": "{{$c.message}}", + # "short": true + # } + # {{end}} + # ] + # }] + + # -- The trigger defines the condition when the notification should be sent + ## For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/triggers/ + triggers: {} + # trigger.on-deployed: | + # - description: Application is synced and healthy. Triggered once per commit. + # oncePer: app.status.sync.revision + # send: + # - app-deployed + # when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy' + # trigger.on-health-degraded: | + # - description: Application has degraded + # send: + # - app-health-degraded + # when: app.status.health.status == 'Degraded' + # trigger.on-sync-failed: | + # - description: Application syncing has failed + # send: + # - app-sync-failed + # when: app.status.operationState.phase in ['Error', 'Failed'] + # trigger.on-sync-running: | + # - description: Application is being synced + # send: + # - app-sync-running + # when: app.status.operationState.phase in ['Running'] + # trigger.on-sync-status-unknown: | + # - description: Application status is 'Unknown' + # send: + # - app-sync-status-unknown + # when: app.status.sync.status == 'Unknown' + # trigger.on-sync-succeeded: | + # - description: Application syncing has succeeded + # send: + # - app-sync-succeeded + # when: app.status.operationState.phase in ['Succeeded'] + # + # For more information: https://argo-cd.readthedocs.io/en/stable/operator-manual/notifications/triggers/#default-triggers + # defaultTriggers: | + # - on-sync-status-unknown diff --git a/cluster/manifests/freeleaps-devops-system/jenkins/.gitkeep b/cluster/manifests/freeleaps-devops-system/jenkins/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/cluster/manifests/freeleaps-devops-system/namespace.yaml b/cluster/manifests/freeleaps-devops-system/namespace.yaml new file mode 100644 index 00000000..5e6e77fb --- /dev/null +++ b/cluster/manifests/freeleaps-devops-system/namespace.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: freeleaps-devops-system + labels: + name: freeleaps-devops-system + +--- + +apiVersion: v1 +kind: ResourceQuota +metadata: + name: freeleaps-devops-system + namespace: freeleaps-devops-system +spec: + hard: + requests.cpu: "4" diff --git a/cluster/manifests/freeleaps-monitoring-system/kube-prometheus-stack/.gitkeep b/cluster/manifests/freeleaps-monitoring-system/kube-prometheus-stack/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/cluster/manifests/freeleaps-storage-system/azure-blob-storage-csi/.gitkeep b/cluster/manifests/freeleaps-storage-system/azure-blob-storage-csi/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/cluster/manifests/freeleaps-storage-system/open-ebs/.gitkeep b/cluster/manifests/freeleaps-storage-system/open-ebs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/cluster/manifests/helm-repos/REPO.list b/cluster/manifests/helm-repos/REPO.list new file mode 100644 index 00000000..c18e37e2 --- /dev/null +++ b/cluster/manifests/helm-repos/REPO.list @@ -0,0 +1,12 @@ +UPDATED_AT:20250109(UTC+8) +LAST_UPDATED_BY:SUNZHENYU + +bitnami,https://charts.bitnami.com/bitnami,force-update +argo,https://argoproj.github.io/argo-helm,force-update +prometheus-community,https://prometheus-community.github.io/helm-charts,force-update +jet-stack,https://charts.jetstack.io,force-update +ingress-nginx,https://kubernetes.github.io/ingress-nginx,force-update +jenkins-ci,https://charts.jenkins.io,force-update +openebs,https://openebs.github.io/openebs,force-update +azure-blob-csi-driver,https://raw.githubusercontent.com/kubernetes-sigs/blob-csi-driver/master/charts,force-update +godaddy-webhook,https://snowdrop.github.io/godaddy-webhook,force-update \ No newline at end of file