diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..9ac10b7 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,136 @@ +package main + +import ( + "fmt" + "oc-k8s/internal" + "os" +) + +func main() { + defer func() { + if r := recover(); r != nil { + + } + }() + if len(os.Args) < 2 { + internal.Help_Func() + fmt.Println("Error: Not enought arguments") + return + } + + if err := action(); err != nil { + internal.Help_Func() + fmt.Println(err) + } +} + +func action() error { + action := os.Args[1] + switch action { + case "start": + args := []string{} + if len(os.Args) > 2 { + args = os.Args[2:] + } + internal.Start(args...) + case "stop": + args := []string{} + if len(os.Args) > 2 { + args = os.Args[2:] + } + internal.Start(args...) + case "help": + what := os.Args[2] + switch what { + case "helm": + internal.Help_Helm() + case "k3s": + internal.Help_K3S() + case "kind": + internal.Help_Kind() + case "cluster": + internal.Help_Cluster() + case "db": + internal.Help_DB() + case "services": + internal.Help_Services() + case "values": + internal.Help_Values() + default: + internal.Help_Func() + } + case "install": + if len(os.Args) < 2 { + args := []string{} + if len(os.Args) > 2 { + args = os.Args[2:] + } + return internal.Install_Func(args...) + } else { + what := os.Args[2] + switch what { + case "helm": + return internal.Install_Helm() + case "k3s": + return internal.Install_K3S() + case "kind": + return internal.Install_Kind() + default: + internal.Help_Func() + } + } + case "create": + what := os.Args[2] + args := []string{} + if len(os.Args) > 3 { + args = os.Args[3:] + } + switch what { + case "helm": + return internal.Create_Helm(args...) + case "cluster": + return internal.Create_Cluster(args...) + case "db": + return internal.Create_DB(args...) + case "services": + return internal.Create_Services(args...) + case "values": + return internal.Create_Values(args...) + default: + internal.Help_Func() + } + case "delete": + what := os.Args[2] + args := []string{} + if len(os.Args) > 3 { + args = os.Args[3:] + } + switch what { + case "helm": + return internal.Delete_Helm(args...) + case "cluster": + return internal.Delete_Cluster(args...) + case "db": + return internal.Delete_DB(args...) + default: + internal.Help_Func() + } + case "upgrade": + what := os.Args[2] + args := []string{} + if len(os.Args) > 3 { + args = os.Args[3:] + } + switch what { + case "helm": + return internal.Upgrade_Helm(args...) + case "db": + return internal.Upgrade_DB(args...) + default: + internal.Help_Func() + } + default: + internal.Help_Func() + } + return nil +} diff --git a/deployed_config b/deployed_config index 38ab762..e2c5f92 100644 --- a/deployed_config +++ b/deployed_config @@ -1,8 +1,8 @@ apiVersion: v1 clusters: - cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJSzVaV2xBVVpyYnN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TmpBeE1EVXhOak14TlRoYUZ3MHpOakF4TURNeE5qTTJOVGhhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUMyV0piMTVvMUorQk81RGVTbmpvVVpTSkRqdkxFaUc5VjZyQ3pFZG1KYjkxU3Q4RjRKSUhZUmdTNSsKdkljQ1A2UHI3WThUSGl0VlB6UWdlMjh5VjdHK245NDhpaHc5SkVBTDBQK2poYW9SYXJnOHRvLzV3LzZjbm5OUwpzTGZTTUYvdS8yVkE1YWFwb1RMbXFMbjgwbmI3MThaM0VQRUtydlhqSnpLOStCUm5lMUpVeFF0MmdJUTVubXBHCmtmK2E2bXhiRUI3OXFGaUJCWFEwN2JkSFppZFRxWEFydGY0RGkrWit1VE9BM0dCU1hsR3FMNGREU1hKSkM3MkUKajJWZk02K1d4SE9SSUE5TUx1cVd6OWxlem4wd1J3YURuME9iWG5EWUhXVWlxbmZoY2NsS3k0bnhjRWxqYTZhNwpuQ1VYc3ZpcCtsZUZHenQvWE9jOWhDWlU4SUpmQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSVUVkYVhJMHJ4TXl6REgrTk9MRWF1S1UvV3dUQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQW5yenJmRHNHcApZMTkvdyt3TFJmalgvREFkcmFsNWRtdGZuZFF0T213VmZETW5XRUNLV09RTXZYcWZlZUUyTDFjalBPVDQrVUNqCmltM0RrcksvSEpSa0NGWGdwVVl1R0JKaVYzbTBsUzJHUkNDckZ5QTdKQS9CYnVUaVBsWmFGOURPNzc5WVd4UkYKaDc0dFowQ09mY0l0dDJlbit1TGh5N29JVUx0ZzJjN3RLSzNKYmRvZFU1SGlSSjBjOG9DNVp6S2sreUdZZVFqTgozYm1rQW1nS1Z5L25yQSt1SXJXRC81T28rdTVhZXEvU1VjcGJFV3A1OWUxcDNQWEFtS1pRczlXZ0ZzVVEvWk1EClVEcjhkMlc0Tmw0MXBIVWpvTEhObldVUmdoNTcwbW9xcFNldGxTemFZL29BYVErV2Z4cjZlaUpIVER0NmhoZFoKMU9qVEJCQUJYMCsvCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - server: https://127.0.0.1:40481 + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJYWhHK01mckdsQlV3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TmpBeE1EY3dPRE13TkROYUZ3MHpOakF4TURVd09ETTFORE5hTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUNuK0ZiOWtuWEhpb1VKZ2tzam1yNmNCVlU4WGdXeFVWdG5RczJCbWJURzNGMnVjTXAzaUovMk5FVlYKVnJyQVNnaldwT0xIeEdoblh6cHhyWFIyVnJFR3EraFpWcHJ6cmVHTjZFS1lkUXozanlXcjVWSTJUdXdYN1FQbgoybC9sby9JVlprRDdaUGY4QmFRVUgwVVQ3VkZ5OExQeVpZUWpVZXM1V3NDcWVKZnF6Y0xJbjhwYnNWQ2U1L2ZPCmlSUTlpcTdQTFcvblhUSGs3bVo0cXY1ZTVJd2NRa2N4bFZvSDNZanNCSzdtYnp3TzdxWTYyZWFITUlLenVYTGsKV0RTUjdaeHlJK0Z3YTZ5bVQzdGdzejBtTFkzRk1INW5HcUF2UTdBbFVzeTlUR3FCS1pSdFZiYUI0MXhnUUhsOQpPUk9BSnFTUzJvdUdFTTJURmtSY2ZuV0NiazZiQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUbXZjRUZkZ2JFWk84SUUyYmsyYUs2SjFGNDN6QVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQTZHTUVyZVFMaQpSVHZJU2V3dmxZTS96dU5QbGVydDIxTm9IaS81SHhHTEgvZDhSVjNjVzREQU5xcm5nSGkwdkUwV3lOYXFtT2ZaCmxpODBEa3dEM2ZYeDdCTHZKUmxuaUJRSDFQdXpCNSs0ZUFRLzhFeVRiUU5vTWV2TGJkQWxHT0VWZTJyK05Bb3kKMURpSHl4YkEzbEZiV2svVHhjV0NMOGQwZ01QbDV0WmJRMGMvdE5nTCs5REFnMGxUbWFVQkZ0dWZVR2llSjVIYQpCcklZS3VsbXNXWUxsK2Ezc0VDb2VqQVN4cnoxZkE0QU5VUzNUN2lDUElJOHFJMXRzUzZ2eEJiakNFM1c2TU1OCmpsRmF0NjVUR3V1Z0NYb3Jac3JKRVpVTzJ2Q1JrWUk0V0ZlTU44RkNRUHBFbmZvTHFrVHhRWVB3U2tuR2xQRXIKN1JjZ1NJVU5ZVU9uCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:41689 name: kind-opencloud contexts: - context: @@ -14,6 +14,6 @@ kind: Config users: - name: kind-opencloud user: - client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJTCtxbzhTOXAzckV3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TmpBeE1EVXhOak14TlRoYUZ3MHlOekF4TURVeE5qTTJOVGhhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFET2tLbUIKcGxBOE4wYktYaFF3YmRGd3ptMC9BT1NvUFg4R0hSSTZDRktXYU1LZjJKNjZDWk9LV0hEMjFiVFFCZ2VXOU5qdwpZNjBqbXlCcE5wS3MrYW1Say9ZWWdnVFg5Qm4ydEFSSDdQNEF6MlVRTktlZ0tNYkVyZFgyYzVVRzg1MldJbk8rCmxyb0sxWUY1OG8zb0IyUmxTZ3NaZ2RyZWh5WlFBekVHUjUxZFdER2hwS3kwNExHNXhUSGNsV0lONUpkRC9qemYKbUIzSkozNUFTRFlLU25ia3g5Rjk4bjYvMm9MVDgvNnF5bmhSTm9tNUVHZUNpSVUyY0ZHQVNESk1Scm1TQ3pNcwpwQm0wWk5sdi91ZDNmU2lzelQwc1JGVG1OUVdSL29sOTlGVVFNQzZWTkFsMGgrY0J4M0poZEExUHc3R0l5WTBDCk05NHN4MzU4YmJqWmt3RW5BZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkZRUjFwY2pTdkV6TE1NZgo0MDRzUnE0cFQ5YkJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJHazlZLytQbGl2VXk4ajRxWnJKMFpaVUZqCk1XWHNQeEtveUh4SHdnMXpYczBIY29oSWFhNVYyblVUb1dqRFNZYWppak5ZbTg4U3czdms1YVlDUEphaVRZWFoKZVZPY05qY09FRVVZZE5zRU0zNFNSWTArVHlpNXk2OS9Bc20zckJyRTZRZlc3YThzTHZOS2ZNZmdsT1BRWmxhcwpIQmpNVGFjS0tmWmo0RnlFMm41dzRQblM0WU9PdmkzTmcxYmFRcVNneHJNOGpKSG1BRFluU0xwMnhyU0NBWEdZCkZBMSsrNlA1STVLVEpGWHUzRWE3RTBZYkxyQXJoQkNrbWVLTWtmcEJVTXhoUVBPcTV4RzlwajMvL0NoRXk0aGUKekdyMVAvQml1a1FEZHRSMXRKb0dVLzQ1WXlSczZtclJZWU42eWtkaEV6dUlVUzhBY05SY2dhd3ZhcDArCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBenBDcGdhWlFQRGRHeWw0VU1HM1JjTTV0UHdEa3FEMS9CaDBTT2doU2xtakNuOWllCnVnbVRpbGh3OXRXMDBBWUhsdlRZOEdPdEk1c2dhVGFTclBtcGtaUDJHSUlFMS9RWjlyUUVSK3orQU05bEVEU24Kb0NqR3hLM1Y5bk9WQnZPZGxpSnp2cGE2Q3RXQmVmS042QWRrWlVvTEdZSGEzb2NtVUFNeEJrZWRYVmd4b2FTcwp0T0N4dWNVeDNKVmlEZVNYUS80ODM1Z2R5U2QrUUVnMkNrcDI1TWZSZmZKK3Y5cUMwL1ArcXNwNFVUYUp1UkJuCmdvaUZObkJSZ0VneVRFYTVrZ3N6TEtRWnRHVFpiLzduZDMwb3JNMDlMRVJVNWpVRmtmNkpmZlJWRURBdWxUUUoKZElmbkFjZHlZWFFOVDhPeGlNbU5BalBlTE1kK2ZHMjQyWk1CSndJREFRQUJBb0lCQUFnaUtSSjZUbmw0Z2JpUgpLTUZaYWFCRCtJZzlERVBWbkExTkVyMG5PNzFCWmJ4dWhwMXpxQlFQOUc2N3JuRnNjMXNOekFiM0hjZWpvWXlUCkFnWitsQjh2ME1aWlJFQ09rNEVqeUhGZWt3Zk1Jc0lYR0t5VlBuSmJGK3dxMCtqZ3FjbFNGUFdoc0xTaGdJWWgKTjFZMkNFMTJzMll2TjBPQTFkRGJ0MC8wZk8xQ2JDSGd0a0IrQkRCQlBVbUkva201dUVTOTRKTmpJWE1pbW5KdwpZWU01OHhXSWF2RGs5eUVyQ0JUcHhmTW5wNzZnN3duT0dxb3lXU2ZlZFdsbXRUNlliTlBid1MwbzRBSmhhT3NQCnNvdm44ekhOa0VacmEvVTZuSVREdTJlTEUzUDdsME8rTGFMRXhhY2VlalM0aW12eG53T0l1Q1l0NW10cDVONlYKeXduVXk3a0NnWUVBNWV2NEhyTlZnaE9aRTJ4cG9HUmlNdDJKRS9xOTVYQXlGM3QwZVFDbi8vK3lZeFgvVXZsOAo1TGd0VklKb3l1OEIwejlIUWdNQnlOMnZhK0xSd1c3NlY3UkFPMVgrMnpHa1RCbWRERkdRRXFSSE12Zk50UkltCmc5K0tJT1dzbWRSYVRLaXNEQS91RkpjdFdFMEJpRnk3cTNTVk16NHhuR0NsUklWdlFSVW40RzhDZ1lFQTVmNkIKb3F1T01hZnFaQnBVakNzcmxvQzdrSEEzUGRPNFljRTVJWjhYY2xWSStKNDVnV0JFWlFWcmFMMGhRTk1WaTdIRgo3TjhjRGdWY0lEVzdPYm5FRk5yTys0Ui9oNEF1U3g3ZGdVNm1mY2I1QXVvODhzeUNtaW5mbFZ2ZHJsVElCTStyCkJYdkdSaG5WOExFRTFWdGtNSjlxbVJHaDNuWWtGVTk0SVpoSjFza0NnWUVBMVFsVG1YNnBHQ0Y0a0pxL05ESlAKR3JwU0xRVUR0dmZDTWlmZHY5QnYyYS9lWmhrWHZwWVV0d2hBV0RHTlQ1c3RvY0xjRDdvaGlUQi9QZ09vUHdiSgpSMEpvMFpIWTF0aWtWeTdVYVhtWmVPeG1YRDluaHdNT1ZOcG5iaHZoVlplQkk4NlZ1NGQzSGZVRnV1OS9JQTVzCmhXMDhZWUtiRFQ0dlk5SVBSOHFHYkZrQ2dZRUFtZVdVUHhKR2dxbVdhTWRKbmNWaFZFTHR2dmVucjBKVmxXdmkKMjhHRndlYVpmbXI1bGIyaDVtc2E5U25nNzJ5UGRUdE9jbkxVWmZsbUxOTm5aWGdOWWRzTU56YncwdTJOakl5cApzVlc4aUZzMDBxT0Vodjhid1NhVnltNS9ScURLZXBXdkhXczJRRUFYYlFnMmNNSEhwOVYwVWRwL2tzbEEyZFdrClQrNkVNaWtDZ1lCMkI3UmV2WEtZZjY2V09mQ3B1cFY0emhHUTJncDU1Qk1scTFTcVZMZktwMkJCS0V5TW9Pa1QKVnoyMWllRHowbXhjY1QwbFA4YzNVbG9uUkhuZWhNTFhnR0dXRlhad2hjZkl3Y2h3RjRwU3VoVldVL01kdEs1Vgo2cmNlVU1tUFFaSkVNeVJ1MkQ0M1IwV1ZRRnpYSHVXc29EbXREa3NjUUtQMlBXT25vdy9vWkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJQ3FrbTVTVVNKbGN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TmpBeE1EY3dPRE13TkROYUZ3MHlOekF4TURjd09ETTFORE5hTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDd2xaOGQKVktORVZSSUUxMWVQQzJTVDZtRW1DM254Y0tHcjE0c0dBNHV5K001bTVQcnJ1TnNDd3kxVTRhNi9FY1RYZUEzbgprMS9scVFtU0R4UVkzZ21RcUdvamZFNlh0cFBzcjYxbGF4OE9FRTdtTks2bUQ4MlF6ampMd05VR2VLLzlLTHYwCnJZNWlyRkVPT3pnYjF1NTdqTWpFZWJ0UlRvOWY5V2FDdVREMVZPdS9QdEZUVE52aERMa29YMHhXNXdSN0I1TGkKY3hVdVhRUTV6MmRhZE9oQUQzQUhVUjNCU2oxYURnWjMrT3lYeWJOTFVuVlQwdVhzWWlPNUFYWGU0a0JtZzdWLwovelNsVUhKaVZrdkpQb3cyRnZiQ0I2MU5qVGdudzZaVDRKQitrSTA1eEJ1R200OFdwcC83SjBWQmducFlFTXdzCnlqci9Gb2JDaVNNNmxnd3JBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRk9hOXdRVjJCc1JrN3dnVApadVRab3JvblVYamZNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNrL3p4MW9ib0RzTDErNXJWaU0xeVdWaDJHCllOaW1IeE02eU54YWJsbGk1QWJUbzNZcHEydEpqQmlYdlFxZWJLNHBwb1dBblFHcGhmTFNkVmsvREU2MUQ4ZFcKVC9oZWRIMzN5aEl5SmpFMGtvQ0VaOW1LdE04Q1daeXNxOXBYekZKYzhwbkVITG44SGJrRjZDdGFpLzRNL01oMQptQ3g5K09OT0ZMRTBRTk13SEFPVzlpNTk3RFdnenhZR1NlQkIwWGVJcWRDUWU0ZFB5Szk2UHNEOXFQOXZUNjYwCmNRbUVuclFtc0d0T0srdlhaclliWlNUY3NSd0RWVldiWldLYW1sbU9RYlUxeWl5SmJEVkp0TnJrRE5aMGdaNFQKTlB3Y0VoQ3Urb1R6aCtMcVpaYlIrSGlLUnZwMW5FR0I3YVgyRkowZy9YUlVjRzRBZDlvUlpMNDF5Q3F0Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBc0pXZkhWU2pSRlVTQk5kWGp3dGtrK3BoSmd0NThYQ2hxOWVMQmdPTHN2ak9adVQ2CjY3amJBc010Vk9HdXZ4SEUxM2dONTVOZjVha0prZzhVR040SmtLaHFJM3hPbDdhVDdLK3RaV3NmRGhCTzVqU3UKcGcvTmtNNDR5OERWQm5pdi9TaTc5SzJPWXF4UkRqczRHOWJ1ZTR6SXhIbTdVVTZQWC9WbWdya3c5VlRydno3UgpVMHpiNFF5NUtGOU1WdWNFZXdlUzRuTVZMbDBFT2M5blduVG9RQTl3QjFFZHdVbzlXZzRHZC9qc2w4bXpTMUoxClU5TGw3R0lqdVFGMTN1SkFab08xZi84MHBWQnlZbFpMeVQ2TU5oYjJ3Z2V0VFkwNEo4T21VK0NRZnBDTk9jUWIKaHB1UEZxYWYreWRGUVlKNldCRE1MTW82L3hhR3dva2pPcFlNS3dJREFRQUJBb0lCQUJoZ0J1OC9EQ3gyQzc4MApWSWRQM01uWVBDSEt5c0hydUwxbVN2QUJGRXNYc2pJYzRKQWlXOFVGV1NBUzZSTEI2cWlOajJuTWU1dlJtaHNaCnpyM2lCSEw5OUd6Q2ozeTh2SzJhMEhZajg4ejJybFZ6cHpvUUMyRzJQYnZPZWZsak5uUGRLQmpOems1TG1BSzkKWlBEZTJkdWZJdVdRSWkzR2lOOEhtbWRvRmR4L2FmZFpCQnNDc3BSVE5ZTmpHMHZTWklaL0V6ZUxMcjJZS1o0YgpDczdyb3prNVAwREJwUm5QamdvZE84a2FDbmZsUEo5L2lFY25rR1R4K056bml1NEY4TndBdWxobWtpVjFQVnVXClB4aVZYTUcvWkRRaExIMXZtck11ZTI5emRENXEzTTNuREx6NG5kNGd5VTB6UXdhV2hha1ZSK2hxZVFPcklYNUkKT2NvM3UyMENnWUVBNmJPOWU3QXEyMnI2Tmx0L1loaEVyc1h6SEZwK3FBTnNaK1BSMERFM1lJZldmbUJ6c2NFMApJMjdsNU5scEcrWEJuaE9McE81U1YyaVhHMXlLSTJXTkNJTkRPTHllQWRHbjFkb2JIWndEcDJzVTgwS0VZaXNNCm90WmtGQkQ4MDFIN0toTnBybzkva09teXhJaENMVVp1d3VqV3UzVkNXVzRyZDg1ejVmNGtRY1VDZ1lFQXdXN0QKQkJ2NHpBbkFyVkRQMG9Fa3p1SXZPaU9uajNVVmdXNUxWQUtyNEFPWWVyNFdKbFRTTFBIQnRXejgrVU5FTjFNaQorVDFkbDhTZ3pZK2FpMFJEWVMwcUYvWVVEbVJaeXJ2aSs5YkVGbzFsL2lLT2Z3Zlh1VTRkSnUyUE5PUzdOenpUCmZ1UkFyNlFjc1kyNzVqRzcxRTlTZktlc1NlME5teUdZTC9BQ3BTOENnWUVBcTNLWVRQaGx5SWpIdlQ4TXladEMKTC9HNnM0OVVJZEE1SkZKSEozUWp5eVo4WGtSR1BCNmdNR3A0TDVhci9MSm1nNkNWTHM5RUN5b0l5U0x2bUo0MApoQTFBTUl4M1lxQTdmN0M5ZWRCdUFkR1dFZ3czY0lsaWdNZkZyYzcwbTljbDZxMUpONjNBaVVCWlRNTWx3VzlOCmJLSkNmazI4K2p6UG1Ob1Z2cUhlV1gwQ2dZQS9uZUFCai9tSmtZT08vTTc4Mm9CeWtpMGFIL1BSMko0VURXUTAKNHhRSC91YTlKNXM5VEJRN3Q5OFBmaUxORC9SMWhhQXcvSisxZEhPMlo0NWFVejhkeks3VlpwYytESDhEa0R1Ywp2QXVOcHo5dUQ0dHg5L0JZLzNuUy9icGxtUHlCdEQyU3RCc2FLUTFPeitDR1dzRDltSUQyZ21iRmdYTkNIQkJqClk3cGEvUUtCZ1FDc0F3aXdveVcyWm1OaExWMytLL2l4TEFNMm1xOUZmVnVEbmpPbzVHTzEwSExRNHFSbTVkNksKWk9iQlQ3WnFWUFVDNFFieFRDc3ZIUkZ4TEt5YU84REV1VWJJNjl1Ly8zc0plekdZWnFOUXRUYzZCdWgrTnZCegpnZlZNZlJienE3SURwVzBYV2VsWlNMUUd0eGlncnR0N2Q2cTFTd2VsUnZKNlBHbVpHbWZZYkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..18882be --- /dev/null +++ b/go.mod @@ -0,0 +1,40 @@ +module oc-k8s + +go 1.24.9 + +toolchain go1.24.11 + +require ( + github.com/prometheus/client_golang v1.23.2 + github.com/prometheus/common v0.67.5 + github.com/prometheus/prometheus v0.309.0 + github.com/stretchr/testify v1.11.1 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/oauth2 v0.34.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..49ec4c3 --- /dev/null +++ b/go.sum @@ -0,0 +1,206 @@ +cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4= +cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 h1:JXg2dwJUmPB9JmtVmdEB16APJ7jurfbY5jnfXpJoRMc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/aws/aws-sdk-go-v2 v1.41.0 h1:tNvqh1s+v0vFYdA1xq0aOJH+Y5cRyZ5upu6roPgPKd4= +github.com/aws/aws-sdk-go-v2 v1.41.0/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= +github.com/aws/aws-sdk-go-v2/config v1.32.6 h1:hFLBGUKjmLAekvi1evLi5hVvFQtSo3GYwi+Bx4lpJf8= +github.com/aws/aws-sdk-go-v2/config v1.32.6/go.mod h1:lcUL/gcd8WyjCrMnxez5OXkO3/rwcNmvfno62tnXNcI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.6 h1:F9vWao2TwjV2MyiyVS+duza0NIRtAslgLUM0vTA1ZaE= +github.com/aws/aws-sdk-go-v2/credentials v1.19.6/go.mod h1:SgHzKjEVsdQr6Opor0ihgWtkWdfRAIwxYzSJ8O85VHY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 h1:80+uETIWS1BqjnN9uJ0dBUaETh+P1XwFy5vwHwK5r9k= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16/go.mod h1:wOOsYuxYuB/7FlnVtzeBYRcjSRtQpAW0hCP7tIULMwo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 h1:rgGwPzb82iBYSvHMHXc8h9mRoOUBZIGFgKb9qniaZZc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16/go.mod h1:L/UxsGeKpGoIj6DxfhOWHWQ/kGKcd4I1VncE4++IyKA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 h1:1jtGzuV7c82xnqOVfx2F0xmJcOw5374L7N6juGW6x6U= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16/go.mod h1:M2E5OQf+XLe+SZGmmpaI2yy+J326aFf6/+54PoxSANc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 h1:oHjJHeUy0ImIV0bsrX0X91GkV5nJAyv1l1CC9lnO0TI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16/go.mod h1:iRSNGgOYmiYwSCXxXaKb9HfOEj40+oTKn8pTxMlYkRM= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 h1:HpI7aMmJ+mm1wkSHIA2t5EaFFv5EFYXePW30p1EIrbQ= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.4/go.mod h1:C5RdGMYGlfM0gYq/tifqgn4EbyX99V15P2V3R+VHbQU= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 h1:aM/Q24rIlS3bRAhTyFurowU8A0SMyGDtEOY/l/s/1Uw= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.8/go.mod h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX1s+lFTg4+4DOy70= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk= +github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= +github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= +github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 h1:cLN4IBkmkYZNnk7EAJ0BHIethd+J6LqxFNw5mSiI2bM= +github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_golang/exp v0.0.0-20251212205219-7ba246a648ca h1:BOxmsLoL2ymn8lXJtorca7N/m+2vDQUDoEtPjf0iAxA= +github.com/prometheus/client_golang/exp v0.0.0-20251212205219-7ba246a648ca/go.mod h1:gndBHh3ZdjBozGcGrjUYjN3UJLRS3l2drALtu4lUt+k= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= +github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/prometheus v0.309.0 h1:e5ftKJSkjDE4LKWWN9qtYtbVq627BabwGzlKWqX7t2Y= +github.com/prometheus/prometheus v0.309.0/go.mod h1:d+dOGiVhuNDa4MaFXHVdnUBy/CzqlcNTooR8oM1wdTU= +github.com/prometheus/sigv4 v0.3.0 h1:QIG7nTbu0JTnNidGI1Uwl5AGVIChWUACxn2B/BQ1kms= +github.com/prometheus/sigv4 v0.3.0/go.mod h1:fKtFYDus2M43CWKMNtGvFNHGXnAJJEGZbiYCmVp/F8I= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.257.0 h1:8Y0lzvHlZps53PEaw+G29SsQIkuKrumGWs9puiexNAA= +google.golang.org/api v0.257.0/go.mod h1:4eJrr+vbVaZSqs7vovFd1Jb/A6ml6iw2e6FBYf3GAO4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/apimachinery v0.34.3 h1:/TB+SFEiQvN9HPldtlWOTp0hWbJ+fjU+wkxysf/aQnE= +k8s.io/apimachinery v0.34.3/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.3 h1:wtYtpzy/OPNYf7WyNBTj3iUA0XaBHVqhv4Iv3tbrF5A= +k8s.io/client-go v0.34.3/go.mod h1:OxxeYagaP9Kdf78UrKLa3YZixMCfP6bgPwPwNBQBzpM= +k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= diff --git a/internal/cluster.go b/internal/cluster.go new file mode 100644 index 0000000..51cffe8 --- /dev/null +++ b/internal/cluster.go @@ -0,0 +1,115 @@ +package internal + +import ( + "bytes" + "fmt" + "oc-k8s/utils" + "os" + "os/exec" +) + +func Help_Cluster() { + fmt.Println(` +Cluster commands: oc-k8s cluster [env_folder] [release] + create - Create a new kind cluster named 'opencloud' + delete - Delete the kind cluster named 'opencloud' + help - Show this help message + +Usage: + oc-k8s create cluster [env_folder] [release] + env_folder - Helm config folder (required, default: .) + release - Release values name (required, default: dev) + oc-k8s delete cluster [env_folder] [release] + env_folder - Helm config folder (required, default: .) + release - Release values name (required, default: dev) + oc-k8s help cluster `) +} + +func Delete_Cluster(args ...string) error { + folder := "." + env := "dev" + if len(args) > 0 { + folder = args[0] + } + if len(args) > 1 { + env = args[1] + } + clusterName := "opencloud" + if b, err := os.ReadFile(folder + "/" + env + "-values.yaml"); err == nil { + clusterName, _ = utils.Extract(string(b), "clusterName") + } + utils.Exec("kind delete cluster --name " + clusterName) + return nil +} + +func Create_Cluster(args ...string) error { + Delete_Cluster(args...) + folder := "." + env := "dev" + if len(args) > 0 { + folder = args[0] + } + if len(args) > 1 { + env = args[1] + } + clusterName := "opencloud" + if b, err := os.ReadFile(folder + "/" + env + "-values.yaml"); err == nil { + clusterName, _ = utils.Extract(string(b), "clusterName") + } + utils.Exec("kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.9.0/deploy/longhorn.yaml ") + + kindConfig := ` +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 30950 + hostPort: 80 + protocol: TCP + - containerPort: 30951 + hostPort: 443 + protocol: TCP +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"] + endpoint = ["http://dev-docker-registry-ui-registry-server.opencloud.svc.cluster.local:5000"] +` + + cmd := exec.Command("kind", "create", "cluster", "--name", clusterName, "--config=-") + cmd.Stdin = bytes.NewBufferString(kindConfig) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + return err + } + + fmt.Println("[WARNING] New cluster should be merged into your current config !") + + if err := utils.Exec("kind get kubeconfig --name " + clusterName + " > /tmp/kind-" + clusterName + ".kubeconfig"); err != nil { + return err + } + if err := utils.Exec("KUBECONFIG=~/.kube/config:/tmp/kind-" + clusterName + ".kubeconfig kubectl config view --flatten --merge --minify > /tmp/merged-kubeconfig.yaml"); err != nil { + return err + } + if err := utils.Exec("sudo mv /tmp/merged-kubeconfig.yaml ~/.kube/config"); err != nil { + return err + } + if err := utils.Exec("chmod 600 ~/.kube/config"); err != nil { + return err + } + if err := utils.Exec("kubectl config get-contexts"); err != nil { + return err + } + if err := utils.Exec("kubectl config use-context kind-opencloud"); err != nil { + return err + } + return nil +} diff --git a/internal/db.go b/internal/db.go new file mode 100644 index 0000000..b68c57a --- /dev/null +++ b/internal/db.go @@ -0,0 +1,96 @@ +package internal + +import ( + "errors" + "fmt" + "oc-k8s/utils" + "os" + "strings" +) + +func Help_DB() { + fmt.Println(` +Cluster commands: oc-k8s cluster + create - Add datas in db + replace - Replace datas in db + delete - Delete datas in db + help - Show this help message + +Usage: + oc-k8s create db [file_path] [release] [db_name] [env_folder] + file_path - Datas folder files path (required) + release - Release values name (default: dev) + db_name - db name (default: opencloud) + env_folder - Helm config folder (required, default: .) + oc-k8s upgrade db [file_path] [release] [db_name] [env_folder] + file_path - Datas folder files path (required) + release - Release values name (default: dev) + db_name - db name (default: opencloud) + env_folder - Helm config folder (required, default: .) + oc-k8s delete db [release] [db_name] [env_folder] + release - Release values name (default: dev) + db_name - db name (default: opencloud) + env_folder - Helm config folder (required, default: .) + oc-k8s help db `) +} + +func Delete_DB(args ...string) error { + release := "dev" + db_name := "dev" + if len(args) > 0 { + release = args[0] + } + if len(args) > 1 { + db_name = args[1] + } + podName := "$(kubectl get pods -n " + release + " -o=name | grep " + release + "-mongodb-* | sed 's|pod/||')" + return utils.Exec("kubectl exec " + podName + ": -- mongosh --eval \"db.getSiblingDB('" + db_name + "').dropDatabase()\"") +} + +func getFileNames(folderPath string) []string { + fileNames := []string{} + entries, err := os.ReadDir(folderPath) + if err != nil { + return fileNames + } + for _, entry := range entries { + if entry.IsDir() { + continue + } + fileNames = append(fileNames, entry.Name()) + } + return fileNames +} + +func Create_DB(args ...string) error { + filePath := "" + if len(args) == 0 { + return errors.New("missing db datas file path") + } else { + filePath = args[0] + } + release := "dev" + db_name := "dev" + if len(args) > 1 { + release = args[1] + } + if len(args) > 2 { + db_name = args[2] + } + podName := "$(kubectl get pods -n " + release + " -o=name | grep " + release + "-mongodb-* | sed 's|pod/||')" + for _, fileName := range getFileNames(filePath) { + fmt.Println("ADD file " + fileName + " in collection") + if err := utils.Exec("kubectl cp " + fileName + " " + podName + ":/tmp/" + fileName); err != nil { + return err + } + if err := utils.Exec("kubectl exec " + podName + ": -- mongoimport --db " + db_name + " --collection " + strings.ReplaceAll(fileName, ".json", "") + " --file /tmp/" + fileName + " --jsonArray"); err != nil { + return err + } + } + return nil +} + +func Upgrade_DB(args ...string) error { + Delete_DB(args[1:]...) + return Create_DB(args...) +} diff --git a/internal/func.go b/internal/func.go new file mode 100644 index 0000000..68d0fb4 --- /dev/null +++ b/internal/func.go @@ -0,0 +1,55 @@ +package internal + +import ( + "fmt" + "oc-k8s/utils" +) + +func Help_Func() { + fmt.Println(` +Main commands: oc-k8s + install - Install opencloud dependancies [arch] [version] + start - Start opencloud k8s + stop - Stop opencloud k8s +Usage: + oc-k8s install [arch] [version] + arch - Arch of OS (required) + kind_version - version of kind (required) + oc-k8s start [env_folder] [release] [namespace] [branch] [target] [hostname] + env_folder - Helm config folder (required, default: .) + release - environnement selected (default: dev) + namespace - namespace selected (default: dev) + branch - Git branch to build (default: main) + target - make target (default: all) + oc-k8s stop`) + Help_Cluster() + Help_Services() + Help_Helm() + Help_Values() + Help_K3S() + Help_Kind() + Help_DB() +} + +func Start(args ...string) error { + utils.Exec("sudo sysctl -w fs.inotify.max_user_instances=256") + utils.Exec("sudo /etc/init.d/apache2 stop") + utils.Exec("sudo nginx -s stop") + Create_Cluster(args...) + Create_Services(args...) + Create_Helm(args...) + return nil +} + +func Stop(args ...string) error { + Delete_Helm(args...) + Delete_Cluster(args...) + return nil +} + +func Install_Func(args ...string) error { + Install_K3S() + Install_Kind(args...) + Install_Helm() + return nil +} diff --git a/internal/helm.go b/internal/helm.go new file mode 100644 index 0000000..4f302fb --- /dev/null +++ b/internal/helm.go @@ -0,0 +1,109 @@ +package internal + +import ( + "fmt" + "oc-k8s/utils" + "os" +) + +func Help_Helm() { + fmt.Println(` +Helm commands: oc-k8s helm + install - Install Helm + create - Install a helm release for the given environment (default: dev) + delete - Uninstall a helm release for the given environment (default: dev) + help - Show this help message + +Usage: + oc-k8s install helm + oc-k8s create helm [env_folder] [release] [namespace] + env_folder - Helm config folder (required, default: .) + release - environnement selected (default: dev) + namespace - namespace selected (default: dev) + oc-k8s upgrade helm [env_folder] [release] [namespace] + env_folder - Helm config folder (required, default: .) + release - environnement selected (default: dev) + namespace - namespace selected (default: dev) + oc-k8s delete helm [release] [namespace] + release - environnement selected (default: dev) + namespace - namespace selected (default: dev) + oc-k8sh help helm`) +} + +func Install_Helm() error { + utils.Exec("curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash") + utils.Exec("helm version") + return nil +} + +func Delete_Helm(args ...string) error { + env := "dev" + namespace := "dev" + if len(args) > 0 { + env = args[0] + } + if len(args) > 1 { + namespace = args[1] + } + utils.Exec("helm uninstall " + env + " -n " + namespace) + utils.Exec("kubectl delete namespace " + namespace + " &") + return nil +} + +func Create_Helm(args ...string) error { + folder := "." + release := "dev" + namespace := "dev" + if len(args) > 0 { + folder = args[0] + } + Delete_Cluster(args[1:]...) + + if len(args) > 1 { + release = args[1] + } + if len(args) > 2 { + namespace = args[2] + } + clusterName := "opencloud" + if b, err := os.ReadFile(folder + "/" + release + "-values.yaml"); err == nil { + clusterName, _ = utils.Extract(string(b), "clusterName") + } + if err := utils.Exec("helm dependency update"); err != nil { + return err + } + if err := utils.Exec("helm dependency build"); err != nil { + return err + } + utils.Exec("kubectl delete sc longhorn-nor1") + utils.Exec("sudo ulimit -n 1000000") + if err := utils.Exec("helm install " + release + " " + clusterName + " -n " + namespace + " --create-namespace -f " + folder + "/" + release + "-values.yaml --debug"); err != nil { + return err + } + + utils.Exec("kind get kubeconfig --name opencloud > ./deployed_config") + utils.Exec("kind export logs ./kind-logs") + return nil +} + +func Upgrade_Helm(args ...string) error { + folder := "." + release := "dev" + namespace := "dev" + if len(args) > 0 { + folder = args[0] + } + Delete_Cluster(args[1:]...) + + if len(args) > 1 { + release = args[1] + } + if len(args) > 2 { + namespace = args[2] + } + clusterName := "opencloud" + if b, err := os.ReadFile(folder + "/" + release + "-values.yaml"); err == nil { + clusterName, _ = utils.Extract(string(b), "clusterName") + } + return utils.Exec("helm upgrade " + release + " " + clusterName + " -n " + namespace + " --create-namespace -f " + folder + "/" + release + "-values.yaml") +} diff --git a/internal/k3s.go b/internal/k3s.go new file mode 100644 index 0000000..983c6b1 --- /dev/null +++ b/internal/k3s.go @@ -0,0 +1,29 @@ +package internal + +import ( + "fmt" + "oc-k8s/utils" +) + +func Help_K3S() { + fmt.Println(` +K3S commands: oc-k8s k3s + install - Install k3s + help - Show this help message + +Usage: + oc-k8s install k3s + oc-k8s help values `) +} + +func Install_K3S() error { + utils.Exec("sudo /usr/local/bin/k3s-uninstall.sh") + utils.Exec("sudo rm -rf /etc/rancher /var/lib/rancher ~/.kube") + if err := utils.Exec("curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644"); err != nil { + return err + } + if err := utils.Exec("sudo systemctl status k3s"); err != nil { + return err + } + return nil +} diff --git a/internal/kind.go b/internal/kind.go new file mode 100644 index 0000000..32cb8cc --- /dev/null +++ b/internal/kind.go @@ -0,0 +1,32 @@ +package internal + +import ( + "fmt" + "oc-k8s/utils" +) + +func Help_Kind() { + fmt.Println(` +Kind commands: oc-k8s kind + install - Install kind + help - Show this help message + +Usage: + oc-k8s install kind [arch] [version] + arch - Arch of OS (required) + kind_version - version of kind (required) + oc-k8s help values `) +} + +func Install_Kind(args ...string) error { + arch := "linux-amd64" + version := "v0.30.0" + if len(args) > 0 { + arch = args[0] + } + if len(args) > 1 { + version = args[1] + } + utils.Exec("curl -Lo kind-linux-amd64 https://kind.sigs.k8s.io/dl/" + version + "/kind-" + arch) + return nil +} diff --git a/internal/services.go b/internal/services.go new file mode 100644 index 0000000..e2fd723 --- /dev/null +++ b/internal/services.go @@ -0,0 +1,85 @@ +package internal + +import ( + "fmt" + "oc-k8s/utils" + "os" +) + +var REPOS = []string{ + "oc-auth", + "oc-catalog", + "oc-datacenter", + "oc-front", + "oc-monitord", + "oc-peer", + "oc-shared", + "oc-scheduler", + "oc-schedulerd", + "oc-workflow", + "oc-workspace", +} + +func Help_Service() { + fmt.Println(` +Service commands: oc-k8s services + create - Build all opencloud services + help - Show this help message + +Usage: + oc-k8s create services [env_folder] [branch] [target] + env_folder - Helm config folder (required, default: .) + branch - Git branch to build (default: main) + target - make target (default: all) + oc-k8s help services `) +} + +func Create_Service(args ...string) error { + folder := "." + release := "dev" + branch := "main" + target := "all" + + if len(args) > 0 { + folder = args[0] + } + if len(args) > 1 { + release = args[1] + } + if len(args) > 3 { + branch = args[3] + } + if len(args) > 4 { + target = args[4] + } + hostname := "beta.opencloud.com" + if b, err := os.ReadFile(folder + "/" + release + "-values.yaml"); err == nil { + hostname, _ = utils.Extract(string(b), "host") + } + + for _, repo := range REPOS { + repo_url := "https://cloud.o-forge.io/core/" + repo + ".git" + host := "$(ip -4 addr show $(ip route | awk '/default/ {print $5}') | awk '/inet / {print $2}' | cut -d/ -f1)" + port := "6443" + ca := "$(kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')" + cert := "$(kubectl config view --raw --minify -o jsonpath='{.users[0].user.client-certificate-data}')" + key := "$(kubectl config view --raw --minify -o jsonpath='{.users[0].user.client-key-data}')" + + if inf, err := os.Stat("./" + repo); err != nil || !inf.IsDir() { + fmt.Println("Cloning repository: " + repo) + if err := utils.Exec("git clone " + repo_url); err != nil { + return err + } + } + fmt.Println("Repository '" + repo + "' now exists. Pulling latest changes...") + if err := utils.Exec("cd " + repo + " && git checkout " + branch + " && git pull"); err != nil { + return err + } + + if err := utils.Exec("cd " + repo + " && export HOST=" + hostname + " && export KUBERNETES_SERVICE_HOST=" + host + " && export KUBERNETES_SERVICE_PORT=" + port + " && export KUBE_CA=" + ca + " && export KUBE_CERT=" + cert + " && export KUBE_DATA=" + key + " && make " + target); err != nil { + return err + } + + } + return nil +} diff --git a/internal/values.go b/internal/values.go new file mode 100644 index 0000000..f189150 --- /dev/null +++ b/internal/values.go @@ -0,0 +1,117 @@ +package internal + +import ( + "bufio" + "fmt" + "oc-k8s/utils" + "os" + "regexp" + "strings" +) + +func Help_Values() { + fmt.Println(` +Values commands: oc-k8s values + create - Create a new values release yaml + help - Show this help message + +Usage: + oc-k8s create values [release] [env_folder] [env_file] + release - Release values name (required) + env_folder - Helm config folder (optionnal, default: .) + env_file - env to map (optionnal) + oc-k8s help values `) +} + +var varPattern = regexp.MustCompile(`\$\{([A-Za-z_][A-Za-z0-9_]*)[:-]([^}]+)\}`) + +func Create_Values(args ...string) error { + folder := "." + release := "dev" + conf := "" + + if len(args) > 0 { + release = args[0] + } + if len(args) > 1 { + folder = args[1] + } + if len(args) > 2 { + conf = args[2] + } + return generateConfig(conf, release, folder) +} + +func generateConfig(confFile string, release string, output_folder string) error { + // Load env file if provided + var err error + confs := map[string]string{} + if confFile != "" { + if confs, err = loadEnvFile(confFile); err != nil { + return err + } + } else { + confFile = "no configuration file" + } + // Read template + content, err := utils.ReadFS("assets/values.yaml.template") + if err != nil { + return err + } + + rendered := renderTemplate(string(content), confs) + + // Ensure output directory exists + if err := os.MkdirAll(output_folder, 0755); err != nil { + return err + } + + // Write output + if err := os.WriteFile(output_folder+"/"+release+"-values.yaml", []byte(rendered), 0644); err != nil { + return err + } + fmt.Printf("Rendered %s from %s using %s\n", output_folder+"/"+release+"-values.yaml", "assets/values.yaml.template", confFile) + return nil +} + +func loadEnvFile(path string) (map[string]string, error) { + envs := map[string]string{} + file, err := os.Open(path) + if err != nil { + return envs, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + + if line == "" || strings.HasPrefix(line, "#") { + continue + } + + parts := strings.SplitN(line, "=", 2) + if len(parts) != 2 { + continue + } + + key := strings.TrimSpace(parts[0]) + val := strings.Trim(strings.TrimSpace(parts[1]), `"'`) + + envs[key] = val + } + return envs, scanner.Err() +} + +func renderTemplate(input string, envs map[string]string) string { + return varPattern.ReplaceAllStringFunc(input, func(match string) string { + sub := varPattern.FindStringSubmatch(match) + varName := sub[1] + defaultVal := sub[2][1:] + + if val, ok := envs[varName]; ok && val != "" { + return val + } + return defaultVal + }) +} diff --git a/oc-k8s.sh b/oc-k8s.sh index cfce1f3..9e6b55b 100755 --- a/oc-k8s.sh +++ b/oc-k8s.sh @@ -31,7 +31,7 @@ main_delete_db() { POD_NAME=$(kubectl get pods --all-namespaces -o=name | grep $RELEASE-mongodb-*) - kubectl exec ${POD_NAME/pod\//}: -- mongosh --eval "db.getSiblingDB('$DB_NAME').dropDatabase()" + kubectl exec /pod\//}: -- mongosh --eval "db.getSiblingDB('$DB_NAME').dropDatabase()" } main_install_db() { @@ -161,6 +161,7 @@ build_service() { local repo_url="https://cloud.o-forge.io/core/$1.git" local branch=${2:-main} local target=${3:-all} + local hostname=${4:-beta.opencloud.com} local repo_name=$(basename "$repo_url" .git) server=$(grep 'server:' ~/.kube/config | awk '{print $2}') @@ -185,7 +186,7 @@ build_service() { cd "$repo_name" && git checkout $branch && git pull echo "Running 'make $target' in $repo_name" - export HOST="${2:-http://beta.opencloud.com/}" && export KUBERNETES_SERVICE_HOST=$host && export KUBERNETES_SERVICE_PORT=$port \ + export HOST="$hostname" && export KUBERNETES_SERVICE_HOST=$host && export KUBERNETES_SERVICE_PORT=$port \ && export KUBE_CA=$ca && export KUBE_CERT=$cert && export KUBE_DATA=$key && make "$target" if [ $? -ne 0 ]; then echo "Error: make $target failed in $dir" @@ -195,13 +196,15 @@ build_service() { } main_build_services() { - branch=${1:-main} - target=${2:-all} + local env=${1:-dev} + local branch=${2:-main} + local target=${3:-all} + local hostname=$(grep 'host:' ./opencloud/values/$env-values.yaml | awk '{print $2}') # docker system prune -af cd .. # Iterate through each repository in the list for repo in "${REPOS[@]}"; do - build_service "$repo" "$branch" "$target" + build_service "$repo" "$branch" "$target" "$hostname" done echo "All repositories processed successfully." } @@ -386,7 +389,7 @@ Usage: oc-k8s install [arch] [version] arch - Arch of OS (required) kind_version - version of kind (required) - oc-k8s start [env] [branch] [target] + oc-k8s start [env] [branch] [target] [hostname] env - environnement selected (default: dev) branch - Git branch to build (default: main) target - make target (default: all) @@ -406,7 +409,7 @@ main_start() { sudo /etc/init.d/apache2 stop sudo nginx -s stop main_create_cluster - main_build_services "${@:2}" + main_build_services "${@:1}" cd ./oc-k8s main_create_helm $1 } diff --git a/opencloud/charts/mongodb/templates/mongo_seed_data.yml b/opencloud/charts/mongodb/templates/mongo_seed_data.yml new file mode 100644 index 0000000..cff23fa --- /dev/null +++ b/opencloud/charts/mongodb/templates/mongo_seed_data.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mongo-seed-data +data: +{{- range $path, $_ := .Files.Glob (printf "start_files/%s/*.json" .Values.name) }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} \ No newline at end of file diff --git a/opencloud/charts/mongodb/templates/mongo_seed_job.yaml b/opencloud/charts/mongodb/templates/mongo_seed_job.yaml new file mode 100644 index 0000000..490259f --- /dev/null +++ b/opencloud/charts/mongodb/templates/mongo_seed_job.yaml @@ -0,0 +1,52 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: mongo-seed +spec: + backoffLimit: 1 + template: + spec: + containers: + - name: mongo-seed + image: mongo:6 + command: + - sh + - -c + - | + echo "Waiting for Mongo to be ready..." + until mongo --host mongo --eval "print(\"ok\")" >/dev/null 2>&1; do + echo "Mongo not ready yet..." + sleep 2 + done + + echo "Checking for JSON files in /opt/opencloud/seed-data..." + files=(/opt/opencloud/seed-data/*.json) + + if [ "${files[0]}" = "/opt/opencloud/seed-data/*.json" ]; then + echo "No JSON files found. Skipping import." + else + echo "Importing JSON files..." + for file in /opt/opencloud/seed-data/*.json; do + if [ -f "$file" ]; then + collection=$(basename "$file" .json) + echo "Importing $file into collection $collection" + mongoimport \ + --uri="mongodb://mongo:27017/opencloud" \ + --collection "$collection" \ + --drop \ + --file "$file" \ + --jsonArray || echo "Failed to import $file, continuing..." + fi + done + fi + + echo "Mongo seed job finished." + exit 0 + volumeMounts: + - name: seed-volume + mountPath: /opt/opencloud/seed-data + volumes: + - name: seed-volume + configMap: + name: mongo-seed-data + restartPolicy: Never \ No newline at end of file diff --git a/opencloud/cmd b/opencloud/cmd new file mode 100755 index 0000000..28d36cb Binary files /dev/null and b/opencloud/cmd differ diff --git a/opencloud/main b/opencloud/main new file mode 100755 index 0000000..52879ef Binary files /dev/null and b/opencloud/main differ diff --git a/opencloud/templates/oc-front/config.yaml b/opencloud/templates/oc-front/config.yaml deleted file mode 100644 index cda0b3a..0000000 --- a/opencloud/templates/oc-front/config.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if index .Values.ocFront.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: front-config -data: - config.json: | - { - "WORKSPACE_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/workspace", - "WORKFLOW_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/workflow", - "CATALOG_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/catalog", - "SCHEDULER_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/scheduler", - "PEER_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/peers", - "DATACENTER_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/datacenter", - "COLLABORATIVE_AREA_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/shared", - "HOST": "{{ .Values.scheme }}://{{ .Values.host }}", - "AUTH_HOST": "{{ .Values.scheme }}://{{ .Values.host }}/auth" - } -{{- end }} diff --git a/opencloud/values.yaml.template b/opencloud/values.yaml.template index 3de2b8a..a1d9fb6 100644 --- a/opencloud/values.yaml.template +++ b/opencloud/values.yaml.template @@ -1,5 +1,6 @@ env: ${RELEASE:-prod} # For storage class provisioning -host: ${HOST:-beta.opencloud.com} # For reverse proxy rule +name: ${CLUSTER_NAME:-opencloud} +host: ${HOST:-beta.opencloud.com} registryHost: ${REGISTRY_HOST:-oc} # For reverse proxy rule scheme: https # For reverse proxy rule diff --git a/opencloud/values/test-values.yaml b/opencloud/values/test-values.yaml index bc6df97..194fb3e 100644 --- a/opencloud/values/test-values.yaml +++ b/opencloud/values/test-values.yaml @@ -1,5 +1,6 @@ env: test # For storage class provisioning -host: beta.opencloud.com # For reverse proxy rule +name: opencloud +host: beta.opencloud.com registryHost: oc # For reverse proxy rule scheme: https # For reverse proxy rule @@ -76,23 +77,6 @@ nats: # name is the volume name used in volumeMounts; keep it simple name: nats-jetstream -reloader: - enabled: false - image: "natsio/nats-server-config-reloader:0.16.0-debian" - # Override ENTRYPOINT so we can raise ulimit before starting the real binary - command: - - /bin/sh - - -c - args: - - -pid - - /var/run/nats/nats.pid - - -config - - /etc/nats-config/nats.conf - - # Required to allow ulimit raise - securityContext: - runAsUser: 0 - openldap: enabled: true test: diff --git a/utils/assets/.helmignore b/utils/assets/.helmignore new file mode 100644 index 0000000..3af93d5 --- /dev/null +++ b/utils/assets/.helmignore @@ -0,0 +1,26 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +#custom +templates/registry/dockerconfigjson \ No newline at end of file diff --git a/utils/assets/Chart.yaml b/utils/assets/Chart.yaml new file mode 100644 index 0000000..50cceb5 --- /dev/null +++ b/utils/assets/Chart.yaml @@ -0,0 +1,56 @@ +apiVersion: v2 +name: opencloud +description: Helm chart for opencloud services deployment +type: application +version: 0.0.1 +appVersion: "0.0.1" + +dependencies: +- name: openldap + repository: https://jp-gouin.github.io/helm-openldap/ + version: "2.0.4" + condition: openldap.enabled +- name: traefik + version: "33.0.0" + repository: "https://helm.traefik.io/traefik" + condition: traefik.enabled +- name: nats + version: "1.2.6" + repository: "https://nats-io.github.io/k8s/helm/charts/" + condition: nats.enabled +- name: mongodb + version: "16.3.1" + repository: "https://charts.bitnami.com/bitnami" + condition: mongodb.enabled +- name: mongo-express + version: "6.5.2" + repository: "https://cowboysysop.github.io/charts/" + condition: mongo-express.enabled +- name: hydra + version: "0.50.6" + repository: "https://k8s.ory.sh/helm/charts" + condition: hydra.enabled +- name: keto + version: "0.50.2" + repository: "https://k8s.ory.sh/helm/charts" + condition: keto.enabled +- name: loki + version: "6.23.0" + repository: "https://grafana.github.io/helm-charts" + condition: loki.enabled +- name: grafana + version: "8.6.4" + repository: "https://grafana.github.io/helm-charts" + condition: grafana.enabled +- name: argo-workflows + version: "0.45.4" + repository: "https://argoproj.github.io/argo-helm" + condition: argo-workflows.enabled +- name: docker-registry-ui + version: 1.1.3 + repository: "https://helm.joxit.dev/" + condition: docker-registry-ui.enabled +- name: prometheus + version: "27.45.0" + repository: "https://prometheus-community.github.io/helm-charts" + condition: prometheus.enabled diff --git a/utils/assets/README.md b/utils/assets/README.md new file mode 100644 index 0000000..430a271 --- /dev/null +++ b/utils/assets/README.md @@ -0,0 +1,129 @@ +# HOW TO MAKE YOUR PROPER VALUES.YAML + +Use command : +``` +oc-k8s create values [release] [env_file (optionnal)] +``` +or +``` +./oc-k8s.sh create values [release] [env_file (optionnal)] +``` + +Map in a env file, any Variable you wish to override and give the path. + +## ENV VARIABLE + +| Variable | Default | Purpose / Explanation | +| -------------- | ---------------------- | --------------------------------------------------------------------------------- | +| `HOST` | `exemple.com` | Domain for reverse proxy rules (Traefik). | +| `REGISTRY_HOST` | `registry.exemple.com` | Docker registry URL for reverse proxy and pull secrets. | + +## MONGO VARIABLE + +| Variable | Default | Purpose / Explanation | +| ------------------- | ----------- | ------------------------------------------ | +| `OC_MONGO_ENABLED` | `true` | Enable/disable MongoDB deployment. | +| `OC_MONGO_ADMIN` | `admin` | Root username for MongoDB. | +| `OC_MONGO_PWD` | `admin` | Root password. | +| `OC_MONGO_DATABASE` | `opencloud` | Default database to create. | +| `OC_MONGO_SIZE` | `5000Mi` | Persistent storage size for MongoDB. | + +## MONGO EXPRESS VARIABLE + +| Variable | Default | Purpose / Explanation | +| ----------------------------------------- | -------------------------------------------------------- | ------------------------------------------- | +| `OC_MONGOEXPRESS_ENABLED` | `true` | Enable mongo-express UI. | +| `OC_MONGOEXPRESS_ADMIN` | `${OC_MONGO_ADMIN:-admin}` | Admin username to connect to MongoDB. | +| `OC_MONGOEXPRESS_PWD` | `${OC_MONGO_PWD:-admin}` | Admin password. | + +## NATS VARIABLE + +| Variable | Default | Explanation | +| ----------------- | ------- | -------------------------------------- | +| `OC_NATS_ENABLED` | `true` | Deploy NATS cluster. | +| `OC_NATS_SIZE` | `20Mi` | Storage size for JetStream file store. | + +## OpenLDAP VARIABLE + +| Variable | Default | Explanation | +| --------------------------- | ---------------------------- | -------------------------------------------------------- | +| `OC_LDAP_ENABLED` | `true` | Deploy OpenLDAP server. | +| `OC_LDAP_IMAGE` | `osixia/openldap` | Docker image for OpenLDAP. | +| `OC_LDAP_ORGANISATION` | `Opencloud` | LDAP organization name. | +| `OC_LDAP_DOMAIN` | `opencloud.com` | LDAP domain. | +| `OC_LDAP_TLS` | `false` | Enable TLS for LDAP. | +| `OC_LDAP_ADMIN_PWD` | `admin` | LDAP admin password. | +| `OC_LDAP_CONFIG_PWD` | `config` | Password for configuration account. | +| `OC_LDAP_EXTERNAL` | `false` | Connect to external LDAP instead of internal deployment. | +| `OC_LDAP_EXTERNAL_ENDPOINT` | (none) | LDAP server URL. | +| `OC_LDAP_EXTERNAL_DN` | `cn=admin,dc=example,dc=com` | Bind DN for external LDAP. | +| `OC_LDAP_EXTERNAL_PWD` | `admin` | Bind password for external LDAP. | + +## Prometheus VARIABLE + +| Variable | Default | Explanation | +| ------------------------------- | ------- | ------------------------- | +| `OC_PROMETHEUS_ENABLED` | `true` | Enable Prometheus server. | +| `OC_PROMETHEUS_SIZE` | `5Gi` | Persistent volume size. | +| `OC_PROMETHEUS_LIMITS_CPU` | `500m` | CPU limit. | +| `OC_PROMETHEUS_LIMITS_MEMORY` | `512Mi` | Memory limit. | +| `OC_PROMETHEUS_REQUESTS_CPU` | `128m` | CPU request. | +| `OC_PROMETHEUS_REQUESTS_MEMORY` | `256Mi` | Memory request. | + +## Grafana VARIABLE + +| VARIABLE | DEFAULT | DESCRIPTION | +| -------------------------------------- | ----------- | ------------------------------------------------------------------------------------ | +| `OC_GRAFANA_ENABLED` | `true` | Enable or disable Grafana deployment. | +| `OC_GRAFANA_ADMIN_USER` | `admin` | Username for the Grafana admin account. | +| `OC_GRAFANA_ADMIN_PWD` | `admin` | Password for the Grafana admin account. | +| `OC_GRAFANA_SIZE` | `1Gi` | Size of the persistent volume for Grafana. | + +## Traefik VARIABLE + +| Variable | Default | Explanation | +| ------------------------------- | ------- | ------------------------- | +| `OC_TRAEFIK_ENABLED` | `true` | Enable Traefik server. | + +## Hydra VARIABLE + +| Variable | Default | Explanation | +| ------------------ | ------------------------------------------------------------------------ | ------------------------------------------- | +| `OC_HYDRA_ENABLED` | `true` | Deploy Hydra (OAuth2). | + +## Keto VARIABLE + +| VARIABLE | DEFAULT | DESCRIPTION | +| ---------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------- | +| `OC_KETO_ENABLED` | `true` | Enable or disable Keto deployment. | + +## Loki VARIABLE + +| VARIABLE | DEFAULT | DESCRIPTION | +| ---------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------- | +| `OC_LOKI_ENABLED` | `true` | Enable or disable Loki deployment. | +| `OC_LOKI_SIZE` | `1Gi` | Resource allowed. | + +## Minio VARIABLE + +| VARIABLE | DEFAULT | DESCRIPTION | +| ---------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------- | +| `OC_MINIO_ENABLED` | `true` | Enable or disable Minio deployment. | + +## Argo VARIABLE + +| VARIABLE | DEFAULT | DESCRIPTION | +| ------------------------------------------ | --------------- | ---------------------------------------------- | +| `OC_ARGO_ENABLED` | `false` | Enable or disable Argo Workflows deployment. | + +## OC API VARIABLE + +| Variable | Default | Explanation | +| ------------------------------------ | ------------ | --------------------------------- | +| `OC__ENABLED` | true | Deploy the service. | +| `OC__IMAGE` | registry URL | Docker image. | +| `OC__LIMITS_CPU/MEMORY` | 128m / 256Mi | Resource limits. | +| `OC__REQUESTS_CPU/MEMORY` | 128m / 256Mi | Resource requests. | +| `OC__REPLICAS_ENABLED` | true | Enable Horizontal Pod Autoscaler. | +| `OC__REPLICAS_MAX` | 5 | Max replicas. | +| `OC__REPLICAS_USAGE` | 80 | HPA target CPU usage (%). | diff --git a/utils/assets/charts/argo-workflows/.helmignore b/utils/assets/charts/argo-workflows/.helmignore new file mode 100644 index 0000000..ec59d66 --- /dev/null +++ b/utils/assets/charts/argo-workflows/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +ci/ +*.gotmpl diff --git a/utils/assets/charts/argo-workflows/Chart.yaml b/utils/assets/charts/argo-workflows/Chart.yaml new file mode 100644 index 0000000..27aa7ea --- /dev/null +++ b/utils/assets/charts/argo-workflows/Chart.yaml @@ -0,0 +1,20 @@ +annotations: + artifacthub.io/changes: | + - kind: added + description: Support configuring workflow events in the controller + artifacthub.io/signKey: | + fingerprint: 2B8F22F57260EFA67BE1C5824B11F800CD9D2252 + url: https://argoproj.github.io/argo-helm/pgp_keys.asc +apiVersion: v2 +appVersion: v3.6.2 +description: A Helm chart for Argo Workflows +home: https://github.com/argoproj/argo-helm +icon: https://argo-workflows.readthedocs.io/en/stable/assets/logo.png +maintainers: +- name: argoproj + url: https://argoproj.github.io/ +name: argo-workflows +sources: +- https://github.com/argoproj/argo-workflows +type: application +version: 0.45.4 diff --git a/utils/assets/charts/argo-workflows/README.md b/utils/assets/charts/argo-workflows/README.md new file mode 100644 index 0000000..323524c --- /dev/null +++ b/utils/assets/charts/argo-workflows/README.md @@ -0,0 +1,410 @@ +# Argo Workflows Chart + +This is a **community maintained** chart. It is used to set up argo and its needed dependencies through one command. This is used in conjunction with [helm](https://github.com/kubernetes/helm). + +If you want your deployment of this helm chart to most closely match the [argo CLI](https://github.com/argoproj/argo-workflows), you should deploy it in the `kube-system` namespace. + +## Pre-Requisites + +### Custom resource definitions + +Some users would prefer to install the CRDs _outside_ of the chart. You can disable the CRD installation of this chart by using `--set crds.install=false` when installing the chart. + +Helm cannot upgrade custom resource definitions in the `/crds` folder [by design](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations). Starting with 3.4.0 (chart version 0.19.0), the CRDs have been moved to `/templates` to address this design decision. + +If you are using Argo Workflows chart version prior to 3.4.0 (chart version 0.19.0) or have elected to manage the Argo Workflows CRDs outside of the chart, please use `kubectl` to upgrade CRDs manually from [templates/crds](templates/crds/) folder or via the manifests from the upstream project repo: + +```bash +kubectl apply -k "https://github.com/argoproj/argo-workflows/manifests/base/crds/full?ref=" + +# Eg. version v3.3.9 +kubectl apply -k "https://github.com/argoproj/argo-workflows/manifests/base/crds/full?ref=v3.3.9" +``` + +### ServiceAccount for Workflow Spec +In order for each Workflow run, you create ServiceAccount via `values.yaml` like below. + +```yaml +workflow: + serviceAccount: + create: true + name: "argo-workflow" + rbac: + create: true +controller: + workflowNamespaces: + - default + - foo + - bar +``` + +Set ServiceAccount on Workflow. + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: hello-world- +spec: + entrypoint: whalesay + serviceAccountName: argo-workflow # Set ServiceAccount + templates: + - name: whalesay + container: + image: docker/whalesay + command: [ cowsay ] + args: [ "hello world" ] +``` + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +$ helm repo add argo https://argoproj.github.io/argo-helm +"argo" has been added to your repositories + +$ helm install my-release argo/argo-workflows +NAME: my-release +... +``` + +## Changelog + +For full list of changes, please check ArtifactHub [changelog]. + +## Usage Notes + +### High Availability + +This chart installs the non-HA version of Argo Workflows by default. If you want to run in HA mode, you can use [these example values](ci/ha-values.yaml) as a starting point. +Please see the upstream [Operator Manual's High Availability page](https://argo-workflows.readthedocs.io/en/stable/high-availability/) to understand how to scale Argo Workflows in depth. + +### Workflow controller + +This chart defaults to setting the `controller.instanceID.enabled` to `false` now, which means the deployed controller will act upon any workflow deployed to the cluster. If you would like to limit the behavior and deploy multiple workflow controllers, please use the `controller.instanceID.enabled` attribute along with one of its configuration options to set the `instanceID` of the workflow controller to be properly scoped for your needs. + +### Argo Workflows server authentication + +Argo Workflows server provides some choices for authentication mechanism and you can configure `.Values.server.authModes`. By default, authentication mode is `[server]`, for local development purposes or cases where your gateway authentication is covered by some other means. +Please refer to [Argo Server Auth Mode] for more details. + +Argo Workflows server also supports SSO and you can enable it to configure `.Values.server.sso` and `.Values.server.authModes`. In order to manage access levels, you can optionally add RBAC to SSO. Please refer to [SSO RBAC] for more details. + +## Values + +The `values.yaml` contains items used to tweak a deployment of this chart. +Fields to note: + +- `controller.instanceID.enabled`: If set to true, the Argo Controller will **ONLY** monitor Workflow submissions with a `--instanceid` attribute +- `controller.instanceID.useReleaseName`: If set to true then chart set controller instance id to release name +- `controller.instanceID.explicitID`: Allows customization of an instance id for the workflow controller to monitor +- `singleNamespace`: When true, restricts the workflow controller to operate + in just the single namespace (that one of the Helm release). +- `controller.workflowNamespaces`: This is a list of namespaces where the + workflow controller will manage workflows. Only valid when `singleNamespace` + is false. + +### General parameters + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| apiVersionOverrides.autoscaling | string | `""` | String to override apiVersion of autoscaling rendered by this helm chart | +| apiVersionOverrides.cloudgoogle | string | `""` | String to override apiVersion of GKE resources rendered by this helm chart | +| apiVersionOverrides.monitoring | string | `""` | String to override apiVersion of monitoring CRDs (ServiceMonitor) rendered by this helm chart | +| commonLabels | object | `{}` | Labels to set on all resources | +| crds.annotations | object | `{}` | Annotations to be added to all CRDs | +| crds.install | bool | `true` | Install and upgrade CRDs | +| crds.keep | bool | `true` | Keep CRDs on chart uninstall | +| createAggregateRoles | bool | `true` | Create clusterroles that extend existing clusterroles to interact with argo-cd crds | +| emissary.images | list | `[]` | The command/args for each image on workflow, needed when the command is not specified and the emissary executor is used. | +| extraObjects | list | `[]` | Array of extra K8s manifests to deploy | +| fullnameOverride | string | `nil` | String to fully override "argo-workflows.fullname" template | +| images.pullPolicy | string | `"Always"` | imagePullPolicy to apply to all containers | +| images.pullSecrets | list | `[]` | Secrets with credentials to pull images from a private registry | +| images.tag | string | `""` | Common tag for Argo Workflows images. Defaults to `.Chart.AppVersion`. | +| kubeVersionOverride | string | `""` | Override the Kubernetes version, which is used to evaluate certain manifests | +| nameOverride | string | `nil` | String to partially override "argo-workflows.fullname" template | +| namespaceOverride | string | `.Release.Namespace` | Override the namespace | +| singleNamespace | bool | `false` | Restrict Argo to operate only in a single namespace (the namespace of the Helm release) by apply Roles and RoleBindings instead of the Cluster equivalents, and start workflow-controller with the --namespaced flag. Use it in clusters with strict access policy. | + +### Workflow + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| workflow.namespace | string | `nil` | Deprecated; use controller.workflowNamespaces instead. | +| workflow.rbac.agentPermissions | bool | `false` | Allows permissions for the Argo Agent. Only required if using http/plugin templates | +| workflow.rbac.artifactGC | bool | `false` | Allows permissions for the Argo Artifact GC pod. Only required if using artifact gc | +| workflow.rbac.create | bool | `true` | Adds Role and RoleBinding for the above specified service account to be able to run workflows. A Role and Rolebinding pair is also created for each namespace in controller.workflowNamespaces (see below) | +| workflow.rbac.serviceAccounts | list | `[]` | Extra service accounts to be added to the RoleBinding | +| workflow.serviceAccount.annotations | object | `{}` | Annotations applied to created service account | +| workflow.serviceAccount.create | bool | `false` | Specifies whether a service account should be created | +| workflow.serviceAccount.labels | object | `{}` | Labels applied to created service account | +| workflow.serviceAccount.name | string | `"argo-workflow"` | Service account which is used to run workflows | +| workflow.serviceAccount.pullSecrets | list | `[]` | Secrets with credentials to pull images from a private registry. Same format as `.Values.images.pullSecrets` | + +### Workflow Controller + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| controller.affinity | object | `{}` | Assign custom [affinity] rules | +| controller.clusterWorkflowTemplates.enabled | bool | `true` | Create a ClusterRole and CRB for the controller to access ClusterWorkflowTemplates. | +| controller.clusterWorkflowTemplates.serviceAccounts | list | `[]` | Extra service accounts to be added to the ClusterRoleBinding | +| controller.columns | list | `[]` | Configure Argo Server to show custom [columns] | +| controller.configMap.annotations | object | `{}` | ConfigMap annotations | +| controller.configMap.create | bool | `true` | Create a ConfigMap for the controller | +| controller.configMap.name | string | `""` | ConfigMap name | +| controller.cronWorkflowWorkers | string | `nil` | Number of cron workflow workers Only valid for 3.5+ | +| controller.deploymentAnnotations | object | `{}` | deploymentAnnotations is an optional map of annotations to be applied to the controller Deployment | +| controller.extraArgs | list | `[]` | Extra arguments to be added to the controller | +| controller.extraContainers | list | `[]` | Extra containers to be added to the controller deployment | +| controller.extraEnv | list | `[]` | Extra environment variables to provide to the controller container | +| controller.extraInitContainers | list | `[]` | Enables init containers to be added to the controller deployment | +| controller.image.registry | string | `"quay.io"` | Registry to use for the controller | +| controller.image.repository | string | `"argoproj/workflow-controller"` | Registry to use for the controller | +| controller.image.tag | string | `""` | Image tag for the workflow controller. Defaults to `.Values.images.tag`. | +| controller.initialDelay | string | `nil` | Resolves ongoing, uncommon AWS EKS bug: https://github.com/argoproj/argo-workflows/pull/4224 | +| controller.instanceID.enabled | bool | `false` | Configures the controller to filter workflow submissions to only those which have a matching instanceID attribute. | +| controller.instanceID.explicitID | string | `""` | Use a custom instanceID | +| controller.instanceID.useReleaseName | bool | `false` | Use ReleaseName as instanceID | +| controller.kubeConfig | object | `{}` (See [values.yaml]) | Configure when workflow controller runs in a different k8s cluster with the workflow workloads, or needs to communicate with the k8s apiserver using an out-of-cluster kubeconfig secret. | +| controller.links | list | `[]` | Configure Argo Server to show custom [links] | +| controller.livenessProbe | object | See [values.yaml] | Configure liveness [probe] for the controller | +| controller.loadBalancerClass | string | `""` | The class of the load balancer implementation | +| controller.loadBalancerSourceRanges | list | `[]` | Source ranges to allow access to service from. Only applies to service type `LoadBalancer` | +| controller.logging.format | string | `"text"` | Set the logging format (one of: `text`, `json`) | +| controller.logging.globallevel | string | `"0"` | Set the glog logging level | +| controller.logging.level | string | `"info"` | Set the logging level (one of: `debug`, `info`, `warn`, `error`) | +| controller.metricsConfig.enabled | bool | `false` | Enables prometheus metrics server | +| controller.metricsConfig.headlessService | bool | `false` | Flag to enable headless service | +| controller.metricsConfig.honorLabels | bool | `false` | When true, honorLabels preserves the metric’s labels when they collide with the target’s labels. | +| controller.metricsConfig.ignoreErrors | bool | `false` | Flag that instructs prometheus to ignore metric emission errors. | +| controller.metricsConfig.interval | string | `"30s"` | Frequency at which prometheus scrapes metrics | +| controller.metricsConfig.metricRelabelings | list | `[]` | ServiceMonitor metric relabel configs to apply to samples before ingestion | +| controller.metricsConfig.metricsTTL | string | `""` | How often custom metrics are cleared from memory | +| controller.metricsConfig.path | string | `"/metrics"` | Path is the path where metrics are emitted. Must start with a "/". | +| controller.metricsConfig.port | int | `9090` | Port is the port where metrics are emitted | +| controller.metricsConfig.portName | string | `"metrics"` | Container metrics port name | +| controller.metricsConfig.relabelings | list | `[]` | ServiceMonitor relabel configs to apply to samples before scraping | +| controller.metricsConfig.secure | bool | `false` | Flag that use a self-signed cert for TLS | +| controller.metricsConfig.servicePort | int | `8080` | Service metrics port | +| controller.metricsConfig.servicePortName | string | `"metrics"` | Service metrics port name | +| controller.metricsConfig.targetLabels | list | `[]` | ServiceMonitor will add labels from the service to the Prometheus metric | +| controller.name | string | `"workflow-controller"` | Workflow controller name string | +| controller.namespaceParallelism | string | `nil` | Limits the maximum number of incomplete workflows in a namespace | +| controller.navColor | string | `""` | Set ui navigation bar background color | +| controller.nodeEvents.enabled | bool | `true` | Enable to emit events on node completion. | +| controller.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | [Node selector] | +| controller.parallelism | string | `nil` | parallelism dictates how many workflows can be running at the same time | +| controller.pdb.enabled | bool | `false` | Configure [Pod Disruption Budget] for the controller pods | +| controller.persistence | object | `{}` | enable Workflow Archive to store the status of workflows. Postgres and MySQL (>= 5.7.8) are available. | +| controller.podAnnotations | object | `{}` | podAnnotations is an optional map of annotations to be applied to the controller Pods | +| controller.podCleanupWorkers | string | `nil` | Number of pod cleanup workers | +| controller.podGCDeleteDelayDuration | string | `5s` (Argo Workflows default) | The duration in seconds before the pods in the GC queue get deleted. A zero value indicates that the pods will be deleted immediately. | +| controller.podGCGracePeriodSeconds | string | `30` seconds (Kubernetes default) | Specifies the duration in seconds before a terminating pod is forcefully killed. A zero value indicates that the pod will be forcefully terminated immediately. | +| controller.podLabels | object | `{}` | Optional labels to add to the controller pods | +| controller.podSecurityContext | object | `{}` | SecurityContext to set on the controller pods | +| controller.priorityClassName | string | `""` | Leverage a PriorityClass to ensure your pods survive resource shortages. | +| controller.rbac.accessAllSecrets | bool | `false` | Allows controller to get, list and watch all k8s secrets. Can only be used if secretWhitelist is empty. | +| controller.rbac.create | bool | `true` | Adds Role and RoleBinding for the controller. | +| controller.rbac.secretWhitelist | list | `[]` | Allows controller to get, list, and watch certain k8s secrets | +| controller.rbac.writeConfigMaps | bool | `false` | Allows controller to create and update ConfigMaps. Enables memoization feature | +| controller.replicas | int | `1` | The number of controller pods to run | +| controller.resourceRateLimit | object | `{}` | Globally limits the rate at which pods are created. This is intended to mitigate flooding of the Kubernetes API server by workflows with a large amount of parallel nodes. | +| controller.resources | object | `{}` | Resource limits and requests for the controller | +| controller.retentionPolicy | object | `{}` | Workflow retention by number of workflows | +| controller.revisionHistoryLimit | int | `10` | The number of revisions to keep. | +| controller.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true}` | the controller container's securityContext | +| controller.serviceAccount.annotations | object | `{}` | Annotations applied to created service account | +| controller.serviceAccount.create | bool | `true` | Create a service account for the controller | +| controller.serviceAccount.labels | object | `{}` | Labels applied to created service account | +| controller.serviceAccount.name | string | `""` | Service account name | +| controller.serviceAnnotations | object | `{}` | Annotations to be applied to the controller Service | +| controller.serviceLabels | object | `{}` | Optional labels to add to the controller Service | +| controller.serviceMonitor.additionalLabels | object | `{}` | Prometheus ServiceMonitor labels | +| controller.serviceMonitor.enabled | bool | `false` | Enable a prometheus ServiceMonitor | +| controller.serviceMonitor.namespace | string | `""` | Prometheus ServiceMonitor namespace | +| controller.serviceType | string | `"ClusterIP"` | Service type of the controller Service | +| controller.telemetryConfig.enabled | bool | `false` | Enables prometheus telemetry server | +| controller.telemetryConfig.ignoreErrors | bool | `false` | Flag that instructs prometheus to ignore metric emission errors. | +| controller.telemetryConfig.interval | string | `"30s"` | Frequency at which prometheus scrapes telemetry data | +| controller.telemetryConfig.metricsTTL | string | `""` | How often custom metrics are cleared from memory | +| controller.telemetryConfig.path | string | `"/telemetry"` | telemetry path | +| controller.telemetryConfig.port | int | `8081` | telemetry container port | +| controller.telemetryConfig.secure | bool | `false` | Flag that use a self-signed cert for TLS | +| controller.telemetryConfig.servicePort | int | `8081` | telemetry service port | +| controller.telemetryConfig.servicePortName | string | `"telemetry"` | telemetry service port name | +| controller.tolerations | list | `[]` | [Tolerations] for use with node taints | +| controller.topologySpreadConstraints | list | `[]` | Assign custom [TopologySpreadConstraints] rules to the workflow controller | +| controller.volumeMounts | list | `[]` | Additional volume mounts to the controller main container | +| controller.volumes | list | `[]` | Additional volumes to the controller pod | +| controller.workflowDefaults | object | `{}` | Default values that will apply to all Workflows from this controller, unless overridden on the Workflow-level. Only valid for 2.7+ | +| controller.workflowEvents.enabled | bool | `true` | Enable to emit events on workflow status changes. | +| controller.workflowNamespaces | list | `["default"]` | Specify all namespaces where this workflow controller instance will manage workflows. This controls where the service account and RBAC resources will be created. Only valid when singleNamespace is false. | +| controller.workflowRestrictions | object | `{}` | Restricts the Workflows that the controller will process. Only valid for 2.9+ | +| controller.workflowTTLWorkers | string | `nil` | Number of workflow TTL workers | +| controller.workflowWorkers | string | `nil` | Number of workflow workers | + +### Workflow Main Container + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| mainContainer.env | list | `[]` | Adds environment variables for the Workflow main container | +| mainContainer.envFrom | list | `[]` | Adds reference environment variables for the Workflow main container | +| mainContainer.imagePullPolicy | string | `""` | imagePullPolicy to apply to Workflow main container. Defaults to `.Values.images.pullPolicy`. | +| mainContainer.resources | object | `{}` | Resource limits and requests for the Workflow main container | +| mainContainer.securityContext | object | `{}` | sets security context for the Workflow main container | + +### Workflow Executor + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| executor.args | list | `[]` | Passes arguments to the executor processes | +| executor.env | list | `[]` | Adds environment variables for the executor. | +| executor.image.pullPolicy | string | `""` | Image PullPolicy to use for the Workflow Executors. Defaults to `.Values.images.pullPolicy`. | +| executor.image.registry | string | `"quay.io"` | Registry to use for the Workflow Executors | +| executor.image.repository | string | `"argoproj/argoexec"` | Repository to use for the Workflow Executors | +| executor.image.tag | string | `""` | Image tag for the workflow executor. Defaults to `.Values.images.tag`. | +| executor.resources | object | `{}` | Resource limits and requests for the Workflow Executors | +| executor.securityContext | object | `{}` | sets security context for the executor container | + +### Workflow Server + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| server.GKEbackendConfig.enabled | bool | `false` | Enable BackendConfig custom resource for Google Kubernetes Engine | +| server.GKEbackendConfig.spec | object | `{}` | [BackendConfigSpec] | +| server.GKEfrontendConfig.enabled | bool | `false` | Enable FrontConfig custom resource for Google Kubernetes Engine | +| server.GKEfrontendConfig.spec | object | `{}` | [FrontendConfigSpec] | +| server.GKEmanagedCertificate.domains | list | `["argoworkflows.example.com"]` | Domains for the Google Managed Certificate | +| server.GKEmanagedCertificate.enabled | bool | `false` | Enable ManagedCertificate custom resource for Google Kubernetes Engine. | +| server.affinity | object | `{}` | Assign custom [affinity] rules | +| server.authMode | string | `""` | Deprecated; use server.authModes instead. | +| server.authModes | list | `[]` | A list of supported authentication modes. Available values are `server`, `client`, or `sso`. If you provide sso, please configure `.Values.server.sso` as well. | +| server.autoscaling.behavior | object | `{}` | Configures the scaling behavior of the target in both Up and Down directions. This is only available on HPA apiVersion `autoscaling/v2beta2` and newer | +| server.autoscaling.enabled | bool | `false` | Enable Horizontal Pod Autoscaler ([HPA]) for the Argo Server | +| server.autoscaling.maxReplicas | int | `5` | Maximum number of replicas for the Argo Server [HPA] | +| server.autoscaling.minReplicas | int | `1` | Minimum number of replicas for the Argo Server [HPA] | +| server.autoscaling.targetCPUUtilizationPercentage | int | `50` | Average CPU utilization percentage for the Argo Server [HPA] | +| server.autoscaling.targetMemoryUtilizationPercentage | int | `50` | Average memory utilization percentage for the Argo Server [HPA] | +| server.baseHref | string | `"/"` | Value for base href in index.html. Used if the server is running behind reverse proxy under subpath different from /. | +| server.clusterWorkflowTemplates.enableEditing | bool | `true` | Give the server permissions to edit ClusterWorkflowTemplates. | +| server.clusterWorkflowTemplates.enabled | bool | `true` | Create a ClusterRole and CRB for the server to access ClusterWorkflowTemplates. | +| server.deploymentAnnotations | object | `{}` | optional map of annotations to be applied to the ui Deployment | +| server.enabled | bool | `true` | Deploy the Argo Server | +| server.extraArgs | list | `[]` | Extra arguments to provide to the Argo server binary. | +| server.extraContainers | list | `[]` | Extra containers to be added to the server deployment | +| server.extraEnv | list | `[]` | Extra environment variables to provide to the argo-server container | +| server.extraInitContainers | list | `[]` | Enables init containers to be added to the server deployment | +| server.hostAliases | list | `[]` | Mapping between IP and hostnames that will be injected as entries in the pod's hosts files | +| server.image.registry | string | `"quay.io"` | Registry to use for the server | +| server.image.repository | string | `"argoproj/argocli"` | Repository to use for the server | +| server.image.tag | string | `""` | Image tag for the Argo Workflows server. Defaults to `.Values.images.tag`. | +| server.ingress.annotations | object | `{}` | Additional ingress annotations | +| server.ingress.enabled | bool | `false` | Enable an ingress resource | +| server.ingress.extraPaths | list | `[]` | Additional ingress paths | +| server.ingress.hosts | list | `[]` | List of ingress hosts | +| server.ingress.ingressClassName | string | `""` | Defines which ingress controller will implement the resource | +| server.ingress.labels | object | `{}` | Additional ingress labels | +| server.ingress.pathType | string | `"Prefix"` | Ingress path type. One of `Exact`, `Prefix` or `ImplementationSpecific` | +| server.ingress.paths | list | `["/"]` | List of ingress paths | +| server.ingress.tls | list | `[]` | Ingress TLS configuration | +| server.lifecycle | object | `{}` | Specify postStart and preStop lifecycle hooks for server container | +| server.loadBalancerClass | string | `""` | The class of the load balancer implementation | +| server.loadBalancerIP | string | `""` | Static IP address to assign to loadBalancer service type `LoadBalancer` | +| server.loadBalancerSourceRanges | list | `[]` | Source ranges to allow access to service from. Only applies to service type `LoadBalancer` | +| server.logging.format | string | `"text"` | Set the logging format (one of: `text`, `json`) | +| server.logging.globallevel | string | `"0"` | Set the glog logging level | +| server.logging.level | string | `"info"` | Set the logging level (one of: `debug`, `info`, `warn`, `error`) | +| server.name | string | `"server"` | Server name string | +| server.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | [Node selector] | +| server.pdb.enabled | bool | `false` | Configure [Pod Disruption Budget] for the server pods | +| server.podAnnotations | object | `{}` | optional map of annotations to be applied to the ui Pods | +| server.podLabels | object | `{}` | Optional labels to add to the UI pods | +| server.podSecurityContext | object | `{}` | SecurityContext to set on the server pods | +| server.priorityClassName | string | `""` | Leverage a PriorityClass to ensure your pods survive resource shortages | +| server.rbac.create | bool | `true` | Adds Role and RoleBinding for the server. | +| server.replicas | int | `1` | The number of server pods to run | +| server.resources | object | `{}` | Resource limits and requests for the server | +| server.revisionHistoryLimit | int | `10` | The number of revisions to keep. | +| server.secure | bool | `false` | Run the argo server in "secure" mode. Configure this value instead of `--secure` in extraArgs. | +| server.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":false,"runAsNonRoot":true}` | Servers container-level security context | +| server.serviceAccount.annotations | object | `{}` | Annotations applied to created service account | +| server.serviceAccount.create | bool | `true` | Create a service account for the server | +| server.serviceAccount.labels | object | `{}` | Labels applied to created service account | +| server.serviceAccount.name | string | `""` | Service account name | +| server.serviceAnnotations | object | `{}` | Annotations to be applied to the UI Service | +| server.serviceLabels | object | `{}` | Optional labels to add to the UI Service | +| server.serviceNodePort | string | `nil` | Service node port | +| server.servicePort | int | `2746` | Service port for server | +| server.servicePortName | string | `""` | Service port name | +| server.serviceType | string | `"ClusterIP"` | Service type for server pods | +| server.sso.clientId.key | string | `"client-id"` | Key of secret to retrieve the app OIDC client ID | +| server.sso.clientId.name | string | `"argo-server-sso"` | Name of secret to retrieve the app OIDC client ID | +| server.sso.clientSecret.key | string | `"client-secret"` | Key of a secret to retrieve the app OIDC client secret | +| server.sso.clientSecret.name | string | `"argo-server-sso"` | Name of a secret to retrieve the app OIDC client secret | +| server.sso.customGroupClaimName | string | `""` | Override claim name for OIDC groups | +| server.sso.enabled | bool | `false` | Create SSO configuration. If you set `true` , please also set `.Values.server.authMode` as `sso`. | +| server.sso.filterGroupsRegex | list | `[]` | Filter the groups returned by the OIDC provider | +| server.sso.insecureSkipVerify | bool | `false` | Skip TLS verification for the HTTP client | +| server.sso.issuer | string | `"https://accounts.google.com"` | The root URL of the OIDC identity provider | +| server.sso.issuerAlias | string | `""` | Alternate root URLs that can be included for some OIDC providers | +| server.sso.rbac.enabled | bool | `true` | Adds ServiceAccount Policy to server (Cluster)Role. | +| server.sso.rbac.secretWhitelist | list | `[]` | Whitelist to allow server to fetch Secrets | +| server.sso.redirectUrl | string | `""` | The OIDC redirect URL. Should be in the form /oauth2/callback. | +| server.sso.scopes | list | `[]` | Scopes requested from the SSO ID provider | +| server.sso.sessionExpiry | string | `""` | Define how long your login is valid for (in hours) | +| server.sso.userInfoPath | string | `""` | Specify the user info endpoint that contains the groups claim | +| server.terminationGracePeriodSeconds | int | `30` | terminationGracePeriodSeconds for container lifecycle hook | +| server.tmpVolume | object | `{"emptyDir":{}}` | Volume to be mounted in Pods for temporary files. | +| server.tolerations | list | `[]` | [Tolerations] for use with node taints | +| server.topologySpreadConstraints | list | `[]` | Assign custom [TopologySpreadConstraints] rules to the argo server | +| server.volumeMounts | list | `[]` | Additional volume mounts to the server main container. | +| server.volumes | list | `[]` | Additional volumes to the server pod. | + +### Artifact Repository + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| artifactRepository.archiveLogs | bool | `false` | Archive the main container logs as an artifact | +| artifactRepository.azure | object | `{}` (See [values.yaml]) | Store artifact in Azure Blob Storage | +| artifactRepository.gcs | object | `{}` (See [values.yaml]) | Store artifact in a GCS object store | +| artifactRepository.s3 | object | See [values.yaml] | Store artifact in a S3-compliant object store | +| artifactRepositoryRef | object | `{}` (See [values.yaml]) | The section of [artifact repository ref](https://argo-workflows.readthedocs.io/en/stable/artifact-repository-ref/). Each map key is the name of configmap | +| customArtifactRepository | object | `{}` | The section of custom artifact repository. Utilize a custom artifact repository that is not one of the current base ones (s3, gcs, azure) | +| useStaticCredentials | bool | `true` | Use static credentials for S3 (eg. when not using AWS IRSA) | + +## Breaking changes from the deprecated `argo` chart + +1. the `installCRD` value has been removed. CRDs are now only installed from the conventional crds/ directory +1. the CRDs were updated to `apiextensions.k8s.io/v1` +1. the container image registry/project/tag format was changed to be more in line with the more common + + ```yaml + image: + registry: quay.io + repository: argoproj/argocli + tag: v3.0.1 + ``` + + this also makes it easier for automatic update tooling (eg. renovate bot) to detect and update images. + +1. switched to quay.io as the default registry for all images +1. removed any included usage of Minio +1. aligned the configuration of serviceAccounts with the argo-cd chart, ie: what used to be `server.createServiceAccount` is now `server.serviceAccount.create` +1. moved the field previously known as `telemetryServicePort` inside the `telemetryConfig` as `telemetryConfig.servicePort` - same for `metricsConfig` + +[affinity]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ +[BackendConfigSpec]: https://cloud.google.com/kubernetes-engine/docs/concepts/backendconfig#backendconfigspec_v1beta1_cloudgooglecom +[FrontendConfigSpec]: https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#configuring_ingress_features_through_frontendconfig_parameters +[links]: https://argo-workflows.readthedocs.io/en/stable/links/ +[columns]: https://github.com/argoproj/argo-workflows/pull/10693 +[Node selector]: https://kubernetes.io/docs/user-guide/node-selection/ +[Pod Disruption Budget]: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +[probe]: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +[Tolerations]: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +[TopologySpreadConstraints]: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +[values.yaml]: values.yaml +[changelog]: https://artifacthub.io/packages/helm/argo/argo-workflows?modal=changelog +[SSO RBAC]: https://argo-workflows.readthedocs.io/en/stable/argo-server-sso/ +[Argo Server Auth Mode]: https://argo-workflows.readthedocs.io/en/stable/argo-server-auth-mode/ diff --git a/utils/assets/charts/argo-workflows/templates/NOTES.txt b/utils/assets/charts/argo-workflows/templates/NOTES.txt new file mode 100644 index 0000000..43c1c8f --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/NOTES.txt @@ -0,0 +1,11 @@ +{{- if .Values.server.authMode }} +DEPRECATED option server.authMode - Use server.authModes +{{- end }} + +1. Get Argo Server external IP/domain by running: + +kubectl --namespace {{ .Release.Namespace }} get services -o wide | grep {{ template "argo-workflows.server.fullname" . }} + +2. Submit the hello-world workflow by running: + +argo submit https://raw.githubusercontent.com/argoproj/argo-workflows/master/examples/hello-world.yaml --watch diff --git a/utils/assets/charts/argo-workflows/templates/_helpers.tpl b/utils/assets/charts/argo-workflows/templates/_helpers.tpl new file mode 100644 index 0000000..ebbba97 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/_helpers.tpl @@ -0,0 +1,211 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Create argo workflows server name and version as used by the chart label. +*/}} +{{- define "argo-workflows.server.fullname" -}} +{{- printf "%s-%s" (include "argo-workflows.fullname" .) .Values.server.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create controller name and version as used by the chart label. +*/}} +{{- define "argo-workflows.controller.fullname" -}} +{{- printf "%s-%s" (include "argo-workflows.fullname" .) .Values.controller.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "argo-workflows.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "argo-workflows.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "argo-workflows.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create kubernetes friendly chart version label for the controller. +Examples: +image.tag = v3.4.4 +output = v3.4.4 + +image.tag = v3.4.4@sha256:d06860f1394a94ac3ff8401126ef32ba28915aa6c3c982c7e607ea0b4dadb696 +output = v3.4.4 +*/}} +{{- define "argo-workflows.controller_chart_version_label" -}} +{{- regexReplaceAll "[^a-zA-Z0-9-_.]+" (regexReplaceAll "@sha256:[a-f0-9]+" (default (include "argo-workflows.defaultTag" .) .Values.controller.image.tag) "") "" | trunc 63 | quote -}} +{{- end -}} + +{{/* +Create kubernetes friendly chart version label for the server. +Examples: +image.tag = v3.4.4 +output = v3.4.4 + +image.tag = v3.4.4@sha256:d06860f1394a94ac3ff8401126ef32ba28915aa6c3c982c7e607ea0b4dadb696 +output = v3.4.4 +*/}} +{{- define "argo-workflows.server_chart_version_label" -}} +{{- regexReplaceAll "[^a-zA-Z0-9-_.]+" (regexReplaceAll "@sha256:[a-f0-9]+" (default (include "argo-workflows.defaultTag" .) .Values.server.image.tag) "") "" | trunc 63 | quote -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "argo-workflows.labels" -}} +helm.sh/chart: {{ include "argo-workflows.chart" .context }} +{{ include "argo-workflows.selectorLabels" (dict "context" .context "component" .component "name" .name) }} +app.kubernetes.io/managed-by: {{ .context.Release.Service }} +app.kubernetes.io/part-of: argo-workflows +{{- with .context.Values.commonLabels }} +{{ toYaml .}} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "argo-workflows.selectorLabels" -}} +{{- if .name -}} +app.kubernetes.io/name: {{ include "argo-workflows.name" .context }}-{{ .name }} +{{ end -}} +app.kubernetes.io/instance: {{ .context.Release.Name }} +{{- if .component }} +app.kubernetes.io/component: {{ .component }} +app: {{ .component }} +{{- end }} +{{- end }} + +{{/* +Create the name of the controller configMap +*/}} +{{- define "argo-workflows.controller.config-map.name" -}} +{{- .Values.controller.configMap.name | default (printf "%s-%s" (include "argo-workflows.controller.fullname" .) "configmap") | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the server service account to use +*/}} +{{- define "argo-workflows.serverServiceAccountName" -}} +{{- if .Values.server.serviceAccount.create -}} + {{ default (include "argo-workflows.server.fullname" .) .Values.server.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.server.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the controller service account to use +*/}} +{{- define "argo-workflows.controllerServiceAccountName" -}} +{{- if .Values.controller.serviceAccount.create -}} + {{ default (include "argo-workflows.controller.fullname" .) .Values.controller.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.controller.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress +*/}} +{{- define "argo-workflows.ingress.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "argo-workflows.kubeVersion" $) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "argo-workflows.kubeVersion" $) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "argo-workflows.kubeVersion" -}} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride }} +{{- end -}} + +{{/* +Return the default Argo Workflows app version +*/}} +{{- define "argo-workflows.defaultTag" -}} + {{- default .Chart.AppVersion .Values.images.tag }} +{{- end -}} + +{{/* +Return full image name including or excluding registry based on existence +*/}} +{{- define "argo-workflows.image" -}} +{{- if and .image.registry .image.repository -}} + {{ .image.registry }}/{{ .image.repository }} +{{- else -}} + {{ .image.repository }} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for autoscaling +*/}} +{{- define "argo-workflows.apiVersion.autoscaling" -}} +{{- if .Values.apiVersionOverrides.autoscaling -}} +{{- print .Values.apiVersionOverrides.autoscaling -}} +{{- else if semverCompare "<1.23-0" (include "argo-workflows.kubeVersion" .) -}} +{{- print "autoscaling/v2beta1" -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for GKE resources +*/}} +{{- define "argo-workflows.apiVersions.cloudgoogle" -}} +{{- if .Values.apiVersionOverrides.cloudgoogle -}} +{{- print .Values.apiVersionOverrides.cloudgoogle -}} +{{- else if .Capabilities.APIVersions.Has "cloud.google.com/v1" -}} +{{- print "cloud.google.com/v1" -}} +{{- else -}} +{{- print "cloud.google.com/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for monitoring CRDs +*/}} +{{- define "argo-workflows.apiVersions.monitoring" -}} +{{- if .Values.apiVersionOverrides.monitoring -}} +{{- print .Values.apiVersionOverrides.monitoring -}} +{{- else -}} +{{- print "monitoring.coreos.com/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Expand the namespace of the release. +Allows overriding it for multi-namespace deployments in combined charts. +*/}} +{{- define "argo-workflows.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/agent-rb.yaml b/utils/assets/charts/argo-workflows/templates/controller/agent-rb.yaml new file mode 100644 index 0000000..67e4995 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/agent-rb.yaml @@ -0,0 +1,29 @@ +{{- if .Values.workflow.rbac.agentPermissions -}} + {{- range $namespace := or .Values.singleNamespace false | ternary (list "") (append .Values.controller.workflowNamespaces (coalesce .Values.workflow.namespace (include "argo-workflows.namespace" .)) | uniq) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "argo-workflows.fullname" $ }}-workflow-agent + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $.Values.controller.name) | nindent 4 }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "argo-workflows.fullname" $ }}-workflow-agent +subjects: + - kind: ServiceAccount + name: {{ $.Values.workflow.serviceAccount.name }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} + {{- range $.Values.workflow.rbac.serviceAccounts }} + - kind: ServiceAccount + name: {{ .name }} + namespace: {{ .namespace | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/agent-role.yaml b/utils/assets/charts/argo-workflows/templates/controller/agent-role.yaml new file mode 100644 index 0000000..577567b --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/agent-role.yaml @@ -0,0 +1,29 @@ +{{- if .Values.workflow.rbac.agentPermissions -}} + {{- range $namespace := or .Values.singleNamespace false | ternary (list "") (append .Values.controller.workflowNamespaces (coalesce .Values.workflow.namespace (include "argo-workflows.namespace" .)) | uniq) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "argo-workflows.fullname" $ }}-workflow-agent + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $.Values.controller.name) | nindent 4 }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} +rules: + - apiGroups: + - argoproj.io + resources: + - workflowtasksets + verbs: + - list + - watch + - apiGroups: + - argoproj.io + resources: + - workflowtasksets/status + verbs: + - patch + {{- end }} + +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/artifact-gc-rb.yaml b/utils/assets/charts/argo-workflows/templates/controller/artifact-gc-rb.yaml new file mode 100644 index 0000000..279b2c5 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/artifact-gc-rb.yaml @@ -0,0 +1,29 @@ +{{- if .Values.workflow.rbac.artifactGC -}} + {{- range $namespace := or .Values.singleNamespace false | ternary (list "") (append .Values.controller.workflowNamespaces (coalesce .Values.workflow.namespace (include "argo-workflows.namespace" .)) | uniq) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "argo-workflows.fullname" $ }}-wf-artifactgc + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $.Values.controller.name) | nindent 4 }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "argo-workflows.fullname" $ }}-wf-artifactgc +subjects: + - kind: ServiceAccount + name: {{ $.Values.workflow.serviceAccount.name }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} + {{- range $.Values.workflow.rbac.serviceAccounts }} + - kind: ServiceAccount + name: {{ .name }} + namespace: {{ .namespace | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/artifact-gc-role.yaml b/utils/assets/charts/argo-workflows/templates/controller/artifact-gc-role.yaml new file mode 100644 index 0000000..48218b8 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/artifact-gc-role.yaml @@ -0,0 +1,29 @@ +{{- if .Values.workflow.rbac.artifactGC -}} + {{- range $namespace := or .Values.singleNamespace false | ternary (list "") (append .Values.controller.workflowNamespaces (coalesce .Values.workflow.namespace (include "argo-workflows.namespace" .)) | uniq) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "argo-workflows.fullname" $ }}-wf-artifactgc + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $.Values.controller.name) | nindent 4 }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} +rules: + - apiGroups: + - argoproj.io + resources: + - workflowartifactgctasks + verbs: + - list + - watch + - apiGroups: + - argoproj.io + resources: + - workflowartifactgctasks/status + verbs: + - patch + {{- end }} + +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/artifact-repository-ref-cm.yaml b/utils/assets/charts/argo-workflows/templates/controller/artifact-repository-ref-cm.yaml new file mode 100644 index 0000000..81c1d0a --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/artifact-repository-ref-cm.yaml @@ -0,0 +1,19 @@ +{{- range $cm_name, $cm_val := .Values.artifactRepositoryRef }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $cm_name }} + namespace: {{ include "argo-workflows.namespace" $ | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $cm_name) | nindent 4 }} + {{- with $cm_val.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + {{- range $data_key, $data_val := (omit $cm_val "annotations") }} + {{- $data_key | nindent 2 }}: | + {{- toYaml $data_val | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-aggregate-roles.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-aggregate-roles.yaml new file mode 100644 index 0000000..2a407b1 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-aggregate-roles.yaml @@ -0,0 +1,107 @@ +{{- if .Values.createAggregateRoles }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "argo-workflows.fullname" . }}-view + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-view: "true" +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtasksets + - workflowtasksets/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + - workflowartifactgctasks + - workflowartifactgctasks/finalizers + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "argo-workflows.fullname" . }}-edit + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtasksets + - workflowtasksets/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + - workflowartifactgctasks + - workflowartifactgctasks/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "argo-workflows.fullname" . }}-admin + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workfloweventbindings + - workfloweventbindings/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + - workflowtasksets + - workflowtasksets/finalizers + - workflowtaskresults + - workflowtaskresults/finalizers + - workflowartifactgctasks + - workflowartifactgctasks/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-cluster-roles.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-cluster-roles.yaml new file mode 100644 index 0000000..1e8f764 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-cluster-roles.yaml @@ -0,0 +1,220 @@ +{{- if .Values.controller.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +{{- if .Values.singleNamespace }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ template "argo-workflows.controller.fullname" . }} + {{- if .Values.singleNamespace }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + {{- end }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - pods/exec + verbs: + - create +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - watch + - list + {{- if .Values.controller.rbac.writeConfigMaps }} + - create + - update + {{- end}} +- apiGroups: + - "" + resources: + - persistentvolumeclaims + - persistentvolumeclaims/finalizers + verbs: + - create + - update + - delete + - get +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workflowtasksets + - workflowtasksets/finalizers + - workflowartifactgctasks + verbs: + - get + - list + - watch + - update + - patch + - delete + - create +- apiGroups: + - argoproj.io + resources: + - workflowtemplates + - workflowtemplates/finalizers + verbs: + - get + - list + - watch +- apiGroups: + - argoproj.io + resources: + - workflowtaskresults + - workflowtaskresults/finalizers + verbs: + - list + - watch + - deletecollection +- apiGroups: + - argoproj.io + resources: + - cronworkflows + - cronworkflows/finalizers + verbs: + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list +- apiGroups: + - "policy" + resources: + - poddisruptionbudgets + verbs: + - create + - get + - delete +{{- if .Values.controller.persistence }} +- apiGroups: + - "" + resources: + - secrets + resourceNames: + {{- if .Values.controller.persistence.postgresql }} + - {{ .Values.controller.persistence.postgresql.userNameSecret.name }} + - {{ .Values.controller.persistence.postgresql.passwordSecret.name }} + {{- end}} + {{- if .Values.controller.persistence.mysql }} + - {{ .Values.controller.persistence.mysql.userNameSecret.name }} + - {{ .Values.controller.persistence.mysql.passwordSecret.name }} + {{- end}} + verbs: + - get +{{- end}} +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + {{- if .Values.controller.instanceID.enabled }} + {{- if .Values.controller.instanceID.useReleaseName }} + - workflow-controller-{{ .Release.Name }} + - workflow-controller-lease-{{ .Release.Name }} + {{- else }} + - workflow-controller-{{ .Values.controller.instanceID.explicitID }} + - workflow-controller-lease-{{ .Values.controller.instanceID.explicitID }} + {{- end }} + {{- else }} + - workflow-controller + - workflow-controller-lease + {{- end }} + verbs: + - get + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + resourceNames: + {{/* for HTTP templates */}} + - argo-workflows-agent-ca-certificates +{{- with .Values.controller.rbac.secretWhitelist }} +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + resourceNames: {{- toYaml . | nindent 4 }} +{{- end }} +{{- if and (not .Values.controller.rbac.secretWhitelist) (.Values.controller.rbac.accessAllSecrets) }} +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch +{{- end }} + +{{- if and .Values.controller.clusterWorkflowTemplates.enabled (not .Values.singleNamespace) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "argo-workflows.controller.fullname" . }}-cluster-template + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} +rules: +- apiGroups: + - argoproj.io + resources: + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + verbs: + - get + - list + - watch +{{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-config-map.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-config-map.yaml new file mode 100644 index 0000000..4961676 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-config-map.yaml @@ -0,0 +1,214 @@ +{{- if .Values.controller.configMap.create }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "argo-workflows.controller.config-map.name" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" "cm") | nindent 4 }} + {{- with .Values.controller.configMap.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + config: | + {{- if .Values.controller.instanceID.enabled }} + {{- if .Values.controller.instanceID.useReleaseName }} + instanceID: {{ .Release.Name }} + {{- else }} + instanceID: {{ .Values.controller.instanceID.explicitID }} + {{- end }} + {{- end }} + {{- if .Values.controller.parallelism }} + parallelism: {{ .Values.controller.parallelism }} + {{- end }} + {{- if .Values.controller.resourceRateLimit }} + resourceRateLimit: {{- toYaml .Values.controller.resourceRateLimit | nindent 6 }} + {{- end }} + {{- with .Values.controller.namespaceParallelism }} + namespaceParallelism: {{ . }} + {{- end }} + {{- with .Values.controller.initialDelay }} + initialDelay: {{ . }} + {{- end }} + {{- if or .Values.mainContainer.resources .Values.mainContainer.env .Values.mainContainer.envFrom .Values.mainContainer.securityContext}} + mainContainer: + imagePullPolicy: {{ default (.Values.images.pullPolicy) .Values.mainContainer.imagePullPolicy }} + {{- with .Values.mainContainer.resources }} + resources: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.mainContainer.env }} + env: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.mainContainer.envFrom }} + envFrom: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.mainContainer.securityContext }} + securityContext: {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if or .Values.executor.resources .Values.executor.env .Values.executor.args .Values.executor.securityContext}} + executor: + imagePullPolicy: {{ default (.Values.images.pullPolicy) .Values.executor.image.pullPolicy }} + {{- with .Values.executor.resources }} + resources: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.executor.args }} + args: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.executor.env }} + env: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.executor.securityContext }} + securityContext: {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if or .Values.artifactRepository.s3 .Values.artifactRepository.gcs .Values.artifactRepository.azure .Values.customArtifactRepository }} + artifactRepository: + {{- if .Values.artifactRepository.archiveLogs }} + archiveLogs: {{ .Values.artifactRepository.archiveLogs }} + {{- end }} + {{- with .Values.artifactRepository.gcs }} + gcs: {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + {{- with .Values.artifactRepository.azure }} + azure: {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + {{- if .Values.artifactRepository.s3 }} + s3: + {{- if .Values.useStaticCredentials }} + accessKeySecret: + key: {{ tpl .Values.artifactRepository.s3.accessKeySecret.key . }} + name: {{ tpl .Values.artifactRepository.s3.accessKeySecret.name . }} + secretKeySecret: + key: {{ tpl .Values.artifactRepository.s3.secretKeySecret.key . }} + name: {{ tpl .Values.artifactRepository.s3.secretKeySecret.name . }} + {{- if .Values.artifactRepository.s3.sessionTokenSecret }} + sessionTokenSecret: + key: {{ tpl .Values.artifactRepository.s3.sessionTokenSecret.key . }} + name: {{ tpl .Values.artifactRepository.s3.sessionTokenSecret.name . }} + {{- end }} + {{- end }} + bucket: {{ tpl (.Values.artifactRepository.s3.bucket | default "") . }} + endpoint: {{ tpl (.Values.artifactRepository.s3.endpoint | default "") . }} + insecure: {{ .Values.artifactRepository.s3.insecure }} + {{- if .Values.artifactRepository.s3.caSecret }} + caSecret: + name: {{ tpl .Values.artifactRepository.s3.caSecret.name . }} + key: {{ tpl .Values.artifactRepository.s3.caSecret.key . }} + {{- end }} + {{- if .Values.artifactRepository.s3.keyFormat }} + keyFormat: {{ .Values.artifactRepository.s3.keyFormat | quote }} + {{- end }} + {{- if .Values.artifactRepository.s3.region }} + region: {{ tpl .Values.artifactRepository.s3.region $ }} + {{- end }} + {{- if .Values.artifactRepository.s3.roleARN }} + roleARN: {{ .Values.artifactRepository.s3.roleARN }} + {{- end }} + {{- if .Values.artifactRepository.s3.useSDKCreds }} + useSDKCreds: {{ .Values.artifactRepository.s3.useSDKCreds }} + {{- end }} + {{- with .Values.artifactRepository.s3.encryptionOptions }} + encryptionOptions: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- if .Values.customArtifactRepository }} + {{- toYaml .Values.customArtifactRepository | nindent 6 }} + {{- end }} + {{- end }} + {{- if .Values.controller.metricsConfig.enabled }} + metricsConfig: + enabled: {{ .Values.controller.metricsConfig.enabled }} + path: {{ .Values.controller.metricsConfig.path }} + port: {{ .Values.controller.metricsConfig.port }} + {{- if .Values.controller.metricsConfig.metricsTTL }} + metricsTTL: {{ .Values.controller.metricsConfig.metricsTTL }} + {{- end }} + ignoreErrors: {{ .Values.controller.metricsConfig.ignoreErrors }} + secure: {{ .Values.controller.metricsConfig.secure }} + {{- end }} + {{- if .Values.controller.telemetryConfig.enabled }} + telemetryConfig: + enabled: {{ .Values.controller.telemetryConfig.enabled }} + path: {{ .Values.controller.telemetryConfig.path }} + port: {{ .Values.controller.telemetryConfig.port }} + {{- if .Values.controller.telemetryConfig.metricsTTL }} + metricsTTL: {{ .Values.controller.telemetryConfig.metricsTTL }} + {{- end }} + ignoreErrors: {{ .Values.controller.telemetryConfig.ignoreErrors }} + secure: {{ .Values.controller.telemetryConfig.secure }} + {{- end }} + {{- if .Values.controller.persistence }} + persistence: +{{ toYaml .Values.controller.persistence | indent 6 }}{{- end }} + {{- if .Values.controller.workflowDefaults }} + workflowDefaults: +{{ toYaml .Values.controller.workflowDefaults | indent 6 }}{{- end }} + {{- if .Values.server.sso.enabled }} + sso: + issuer: {{ .Values.server.sso.issuer }} + clientId: + name: {{ .Values.server.sso.clientId.name }} + key: {{ .Values.server.sso.clientId.key }} + clientSecret: + name: {{ .Values.server.sso.clientSecret.name }} + key: {{ .Values.server.sso.clientSecret.key }} + redirectUrl: {{ .Values.server.sso.redirectUrl | quote }} + rbac: + enabled: {{ .Values.server.sso.rbac.enabled }} + {{- with .Values.server.sso.scopes }} + scopes: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.sso.issuerAlias }} + issuerAlias: {{ toYaml . }} + {{- end }} + {{- with .Values.server.sso.sessionExpiry }} + sessionExpiry: {{ toYaml . }} + {{- end }} + {{- with .Values.server.sso.customGroupClaimName }} + customGroupClaimName: {{ toYaml . }} + {{- end }} + {{- with .Values.server.sso.userInfoPath }} + userInfoPath: {{ toYaml . }} + {{- end }} + {{- with .Values.server.sso.insecureSkipVerify }} + insecureSkipVerify: {{ toYaml . }} + {{- end }} + {{- with .Values.server.sso.filterGroupsRegex }} + filterGroupsRegex: {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.controller.workflowRestrictions }} + workflowRestrictions: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.links }} + links: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.columns }} + columns: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.navColor }} + navColor: {{ . }} + {{- end }} + {{- with .Values.controller.retentionPolicy }} + retentionPolicy: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.emissary.images }} + images: {{- toYaml . | nindent 6 }} + {{- end }} + nodeEvents: + enabled: {{ .Values.controller.nodeEvents.enabled }} + workflowEvents: + enabled: {{ .Values.controller.workflowEvents.enabled }} + {{- with .Values.controller.kubeConfig }} + kubeConfig: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.podGCGracePeriodSeconds }} + podGCGracePeriodSeconds: {{ . }} + {{- end }} + {{- with .Values.controller.podGCDeleteDelayDuration }} + podGCDeleteDelayDuration: {{ . }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-crb.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-crb.yaml new file mode 100644 index 0000000..93e0557 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-crb.yaml @@ -0,0 +1,50 @@ +{{- if .Values.controller.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +{{- if .Values.singleNamespace }} +kind: RoleBinding +{{ else }} +kind: ClusterRoleBinding +{{- end }} +metadata: + name: {{ template "argo-workflows.controller.fullname" . }} + {{- if .Values.singleNamespace }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + {{- end }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + {{- if .Values.singleNamespace }} + kind: Role + {{ else }} + kind: ClusterRole + {{- end }} + name: {{ template "argo-workflows.controller.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "argo-workflows.controllerServiceAccountName" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + +{{- if .Values.controller.clusterWorkflowTemplates.enabled }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "argo-workflows.controller.fullname" . }}-cluster-template + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "argo-workflows.controller.fullname" . }}-cluster-template +subjects: + - kind: ServiceAccount + name: {{ template "argo-workflows.controllerServiceAccountName" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} +{{- range .Values.controller.clusterWorkflowTemplates.serviceAccounts }} + - kind: ServiceAccount + name: {{ .name }} + namespace: {{ .namespace | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-deployment-pdb.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-deployment-pdb.yaml new file mode 100644 index 0000000..bee7c19 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-deployment-pdb.yaml @@ -0,0 +1,20 @@ +{{- if .Values.controller.pdb.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ template "argo-workflows.controller.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} +spec: + {{- if .Values.controller.pdb.minAvailable }} + minAvailable: {{ .Values.controller.pdb.minAvailable }} + {{- else if .Values.controller.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.controller.pdb.maxUnavailable }} + {{- else }} + minAvailable: 0 + {{- end }} + selector: + matchLabels: + {{- include "argo-workflows.selectorLabels" (dict "context" . "name" .Values.controller.name) | nindent 6 }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-deployment.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-deployment.yaml new file mode 100644 index 0000000..b3db5f4 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-deployment.yaml @@ -0,0 +1,146 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "argo-workflows.controller.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} + app.kubernetes.io/version: {{ include "argo-workflows.controller_chart_version_label" . }} + {{- with .Values.controller.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.controller.replicas }} + revisionHistoryLimit: {{ .Values.controller.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "argo-workflows.selectorLabels" (dict "context" . "name" .Values.controller.name) | nindent 6 }} + template: + metadata: + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 8 }} + app.kubernetes.io/version: {{ include "argo-workflows.controller_chart_version_label" . }} + {{- with.Values.controller.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "argo-workflows.controllerServiceAccountName" . }} + {{- with .Values.controller.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.extraInitContainers }} + initContainers: + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + containers: + - name: controller + image: "{{- include "argo-workflows.image" (dict "context" . "image" .Values.controller.image) }}:{{ default (include "argo-workflows.defaultTag" .) .Values.controller.image.tag }}" + imagePullPolicy: {{ .Values.images.pullPolicy }} + command: [ "workflow-controller" ] + args: + - "--configmap" + - "{{ template "argo-workflows.controller.config-map.name" . }}" + - "--executor-image" + - "{{- include "argo-workflows.image" (dict "context" . "image" .Values.executor.image) }}:{{ default (include "argo-workflows.defaultTag" .) .Values.executor.image.tag }}" + - "--loglevel" + - "{{ .Values.controller.logging.level }}" + - "--gloglevel" + - "{{ .Values.controller.logging.globallevel }}" + - "--log-format" + - "{{ .Values.controller.logging.format }}" + {{- if .Values.singleNamespace }} + - "--namespaced" + {{- end }} + {{- with .Values.controller.workflowWorkers }} + - "--workflow-workers" + - {{ . | quote }} + {{- end }} + {{- with .Values.controller.workflowTTLWorkers }} + - "--workflow-ttl-workers" + - {{ . | quote }} + {{- end }} + {{- with .Values.controller.podCleanupWorkers }} + - "--pod-cleanup-workers" + - {{ . | quote }} + {{- end }} + {{- with .Values.controller.cronWorkflowWorkers }} + - "--cron-workflow-workers" + - {{ . | quote }} + {{- end }} + {{- with .Values.controller.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + {{- toYaml .Values.controller.securityContext | nindent 12 }} + env: + - name: ARGO_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: LEADER_ELECTION_IDENTITY + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + {{- if eq (int .Values.controller.replicas) 1 }} + - name: LEADER_ELECTION_DISABLE + value: "true" + {{- end }} + {{- with .Values.controller.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.controller.resources | nindent 12 }} + {{- with .Values.controller.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 10 }} + {{- end }} + ports: + - name: {{ .Values.controller.metricsConfig.portName }} + containerPort: {{ .Values.controller.metricsConfig.port }} + - containerPort: 6060 + livenessProbe: {{ .Values.controller.livenessProbe | toYaml | nindent 12 }} + {{- with .Values.controller.extraContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.images.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.volumes }} + volumes: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := . }} + - {{ toYaml $constraint | nindent 8 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + {{- include "argo-workflows.selectorLabels" (dict "context" $ "name" $.Values.controller.name) | nindent 12 }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.controller.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-sa.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-sa.yaml new file mode 100644 index 0000000..fd1db89 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-sa.yaml @@ -0,0 +1,16 @@ +{{- if .Values.controller.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "argo-workflows.controllerServiceAccountName" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} + {{- with .Values.controller.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{ with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml .| nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-service.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-service.yaml new file mode 100644 index 0000000..4a1290b --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-service.yaml @@ -0,0 +1,47 @@ +{{- if or .Values.controller.metricsConfig.enabled .Values.controller.telemetryConfig.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "argo-workflows.controller.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} + app.kubernetes.io/version: {{ include "argo-workflows.controller_chart_version_label" . }} + {{- with .Values.controller.serviceLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.controller.serviceAnnotations }} + annotations: + {{- toYaml . | nindent 4}} + {{- end }} +spec: + ports: + {{- if .Values.controller.metricsConfig.enabled }} + - name: {{ .Values.controller.metricsConfig.servicePortName }} + port: {{ .Values.controller.metricsConfig.servicePort }} + protocol: TCP + targetPort: {{ .Values.controller.metricsConfig.port }} + {{- end }} + {{- if .Values.controller.telemetryConfig.enabled }} + - name: {{ .Values.controller.telemetryConfig.servicePortName }} + port: {{ .Values.controller.telemetryConfig.servicePort }} + protocol: TCP + targetPort: {{ .Values.controller.telemetryConfig.port }} + {{- end }} + selector: + {{- include "argo-workflows.selectorLabels" (dict "context" . "name" .Values.controller.name) | nindent 4 }} + sessionAffinity: None + type: {{ .Values.controller.serviceType }} + {{- if and (eq .Values.controller.serviceType "ClusterIP") .Values.controller.metricsConfig.headlessService }} + clusterIP: None + {{- end }} + {{- if eq .Values.controller.serviceType "LoadBalancer" }} + {{- with .Values.controller.loadBalancerClass }} + loadBalancerClass: {{ . }} + {{- end }} + {{- if .Values.controller.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml .Values.controller.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-servicemonitor.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-servicemonitor.yaml new file mode 100644 index 0000000..46fd18d --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-controller-servicemonitor.yaml @@ -0,0 +1,53 @@ +{{- $apiVersion := include "argo-workflows.apiVersions.monitoring" . }} +{{- if and (.Capabilities.APIVersions.Has $apiVersion) (or .Values.controller.metricsConfig.enabled .Values.controller.telemetryConfig.enabled) .Values.controller.serviceMonitor.enabled }} +apiVersion: {{ $apiVersion }} +kind: ServiceMonitor +metadata: + name: {{ template "argo-workflows.controller.fullname" . }} + namespace: {{ default (include "argo-workflows.namespace" .) .Values.controller.serviceMonitor.namespace | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.controller.name "name" .Values.controller.name) | nindent 4 }} + {{- with .Values.controller.serviceMonitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + {{- if .Values.controller.metricsConfig.enabled }} + - port: {{ .Values.controller.metricsConfig.servicePortName }} + path: {{ .Values.controller.metricsConfig.path }} + interval: {{ .Values.controller.metricsConfig.interval }} + {{- with .Values.controller.metricsConfig.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.metricsConfig.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + honorLabels: {{ .Values.controller.metricsConfig.honorLabels }} + {{- end }} + {{- if .Values.controller.telemetryConfig.enabled }} + - port: telemetry + path: {{ .Values.controller.telemetryConfig.path }} + interval: {{ .Values.controller.telemetryConfig.interval }} + {{- with .Values.controller.metricsConfig.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.metricsConfig.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + honorLabels: {{ .Values.controller.metricsConfig.honorLabels }} + {{- end }} + {{- with .Values.controller.metricsConfig.targetLabels }} + targetLabels: + {{- toYaml . | nindent 8 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "argo-workflows.namespace" . | quote }} + selector: + matchLabels: + {{- include "argo-workflows.selectorLabels" (dict "context" . "name" .Values.controller.name) | nindent 6 }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-rb.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-rb.yaml new file mode 100644 index 0000000..d1d0e32 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-rb.yaml @@ -0,0 +1,29 @@ +{{- if .Values.workflow.rbac.create -}} + {{- range $namespace := or .Values.singleNamespace false | ternary (list "") (append .Values.controller.workflowNamespaces (coalesce .Values.workflow.namespace (include "argo-workflows.namespace" .)) | uniq) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "argo-workflows.fullname" $ }}-workflow + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $.Values.controller.name) | nindent 4 }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "argo-workflows.fullname" $ }}-workflow +subjects: + - kind: ServiceAccount + name: {{ $.Values.workflow.serviceAccount.name }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} + {{- range $.Values.workflow.rbac.serviceAccounts }} + - kind: ServiceAccount + name: {{ .name }} + namespace: {{ .namespace | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-role.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-role.yaml new file mode 100644 index 0000000..81c2004 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-role.yaml @@ -0,0 +1,23 @@ +{{- if .Values.workflow.rbac.create -}} + {{- range $namespace := or .Values.singleNamespace false | ternary (list "") (append .Values.controller.workflowNamespaces (coalesce .Values.workflow.namespace (include "argo-workflows.namespace" .)) | uniq) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "argo-workflows.fullname" $ }}-workflow + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $.Values.controller.name) | nindent 4 }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} +rules: + - apiGroups: + - argoproj.io + resources: + - workflowtaskresults + verbs: + - create + - patch + {{- end }} + +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/controller/workflow-sa.yaml b/utils/assets/charts/argo-workflows/templates/controller/workflow-sa.yaml new file mode 100644 index 0000000..c6fff69 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/controller/workflow-sa.yaml @@ -0,0 +1,25 @@ +{{- if .Values.workflow.serviceAccount.create -}} + {{- range $namespace := or .Values.singleNamespace false | ternary (list "") (append .Values.controller.workflowNamespaces (coalesce .Values.workflow.namespace (include "argo-workflows.namespace" .)) | uniq) }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $.Values.workflow.serviceAccount.name }} + labels: + {{- include "argo-workflows.labels" (dict "context" $ "component" $.Values.controller.name "name" $.Values.controller.name) | nindent 4 }} + {{- with $.Values.workflow.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $namespace }} + namespace: {{ . }} + {{- end }} + {{- with $.Values.workflow.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $.Values.workflow.serviceAccount.pullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_clusterworkflowtemplates.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_clusterworkflowtemplates.yaml new file mode 100644 index 0000000..9264eab --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_clusterworkflowtemplates.yaml @@ -0,0 +1,47 @@ +{{- if .Values.crds.install }} +{{- if or (.Values.server.clusterWorkflowTemplates.enabled) (.Values.controller.clusterWorkflowTemplates.enabled) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterworkflowtemplates.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: ClusterWorkflowTemplate + listKind: ClusterWorkflowTemplateList + plural: clusterworkflowtemplates + shortNames: + - clusterwftmpl + - cwft + singular: clusterworkflowtemplate + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + required: + - metadata + - spec + type: object + served: true + storage: true +{{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_cronworkflows.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_cronworkflows.yaml new file mode 100644 index 0000000..7b932d8 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_cronworkflows.yaml @@ -0,0 +1,49 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: cronworkflows.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: CronWorkflow + listKind: CronWorkflowList + plural: cronworkflows + shortNames: + - cwf + - cronwf + singular: cronworkflow + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + required: + - metadata + - spec + type: object + served: true + storage: true +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowartifactgctasks.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowartifactgctasks.yaml new file mode 100644 index 0000000..6a47471 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowartifactgctasks.yaml @@ -0,0 +1,1146 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: workflowartifactgctasks.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: WorkflowArtifactGCTask + listKind: WorkflowArtifactGCTaskList + plural: workflowartifactgctasks + shortNames: + - wfat + singular: workflowartifactgctask + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + artifactsByNode: + additionalProperties: + properties: + archiveLocation: + properties: + archiveLogs: + type: boolean + artifactory: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + url: + type: string + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - url + type: object + azure: + properties: + accountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + blob: + type: string + container: + type: string + endpoint: + type: string + useSDKCreds: + type: boolean + required: + - blob + - container + - endpoint + type: object + gcs: + properties: + bucket: + type: string + key: + type: string + serviceAccountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - key + type: object + git: + properties: + branch: + type: string + depth: + format: int64 + type: integer + disableSubmodules: + type: boolean + fetch: + items: + type: string + type: array + insecureIgnoreHostKey: + type: boolean + insecureSkipTLS: + type: boolean + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + repo: + type: string + revision: + type: string + singleBranch: + type: boolean + sshPrivateKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - repo + type: object + hdfs: + properties: + addresses: + items: + type: string + type: array + dataTransferProtection: + type: string + force: + type: boolean + hdfsUser: + type: string + krbCCacheSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbConfigConfigMap: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbKeytabSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbRealm: + type: string + krbServicePrincipalName: + type: string + krbUsername: + type: string + path: + type: string + required: + - path + type: object + http: + properties: + auth: + properties: + basicAuth: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientCert: + properties: + clientCertSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + oauth2: + properties: + clientIDSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientSecretSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + items: + properties: + key: + type: string + value: + type: string + required: + - key + type: object + type: array + scopes: + items: + type: string + type: array + tokenURLSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + type: object + headers: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + url: + type: string + required: + - url + type: object + oss: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + createBucketIfNotPresent: + type: boolean + endpoint: + type: string + key: + type: string + lifecycleRule: + properties: + markDeletionAfterDays: + format: int32 + type: integer + markInfrequentAccessAfterDays: + format: int32 + type: integer + type: object + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + securityToken: + type: string + useSDKCreds: + type: boolean + required: + - key + type: object + raw: + properties: + data: + type: string + required: + - data + type: object + s3: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + caSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + createBucketIfNotPresent: + properties: + objectLocking: + type: boolean + type: object + encryptionOptions: + properties: + enableEncryption: + type: boolean + kmsEncryptionContext: + type: string + kmsKeyId: + type: string + serverSideCustomerKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + endpoint: + type: string + insecure: + type: boolean + key: + type: string + region: + type: string + roleARN: + type: string + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + sessionTokenSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + useSDKCreds: + type: boolean + type: object + type: object + artifacts: + additionalProperties: + properties: + archive: + properties: + none: + type: object + tar: + properties: + compressionLevel: + format: int32 + type: integer + type: object + zip: + type: object + type: object + archiveLogs: + type: boolean + artifactGC: + properties: + podMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + serviceAccountName: + type: string + strategy: + enum: + - "" + - OnWorkflowCompletion + - OnWorkflowDeletion + - Never + type: string + type: object + artifactory: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + url: + type: string + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - url + type: object + azure: + properties: + accountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + blob: + type: string + container: + type: string + endpoint: + type: string + useSDKCreds: + type: boolean + required: + - blob + - container + - endpoint + type: object + deleted: + type: boolean + from: + type: string + fromExpression: + type: string + gcs: + properties: + bucket: + type: string + key: + type: string + serviceAccountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - key + type: object + git: + properties: + branch: + type: string + depth: + format: int64 + type: integer + disableSubmodules: + type: boolean + fetch: + items: + type: string + type: array + insecureIgnoreHostKey: + type: boolean + insecureSkipTLS: + type: boolean + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + repo: + type: string + revision: + type: string + singleBranch: + type: boolean + sshPrivateKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - repo + type: object + globalName: + type: string + hdfs: + properties: + addresses: + items: + type: string + type: array + dataTransferProtection: + type: string + force: + type: boolean + hdfsUser: + type: string + krbCCacheSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbConfigConfigMap: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbKeytabSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbRealm: + type: string + krbServicePrincipalName: + type: string + krbUsername: + type: string + path: + type: string + required: + - path + type: object + http: + properties: + auth: + properties: + basicAuth: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientCert: + properties: + clientCertSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + oauth2: + properties: + clientIDSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientSecretSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + items: + properties: + key: + type: string + value: + type: string + required: + - key + type: object + type: array + scopes: + items: + type: string + type: array + tokenURLSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + type: object + headers: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + url: + type: string + required: + - url + type: object + mode: + format: int32 + type: integer + name: + type: string + optional: + type: boolean + oss: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + createBucketIfNotPresent: + type: boolean + endpoint: + type: string + key: + type: string + lifecycleRule: + properties: + markDeletionAfterDays: + format: int32 + type: integer + markInfrequentAccessAfterDays: + format: int32 + type: integer + type: object + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + securityToken: + type: string + useSDKCreds: + type: boolean + required: + - key + type: object + path: + type: string + raw: + properties: + data: + type: string + required: + - data + type: object + recurseMode: + type: boolean + s3: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + caSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + createBucketIfNotPresent: + properties: + objectLocking: + type: boolean + type: object + encryptionOptions: + properties: + enableEncryption: + type: boolean + kmsEncryptionContext: + type: string + kmsKeyId: + type: string + serverSideCustomerKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + endpoint: + type: string + insecure: + type: boolean + key: + type: string + region: + type: string + roleARN: + type: string + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + sessionTokenSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + useSDKCreds: + type: boolean + type: object + subPath: + type: string + required: + - name + type: object + type: object + type: object + type: object + type: object + status: + properties: + artifactResultsByNode: + additionalProperties: + properties: + artifactResults: + additionalProperties: + properties: + error: + type: string + name: + type: string + success: + type: boolean + required: + - name + type: object + type: object + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workfloweventbindings.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workfloweventbindings.yaml new file mode 100644 index 0000000..f11df95 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workfloweventbindings.yaml @@ -0,0 +1,690 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: workfloweventbindings.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: WorkflowEventBinding + listKind: WorkflowEventBindingList + plural: workfloweventbindings + shortNames: + - wfeb + singular: workfloweventbinding + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + event: + properties: + selector: + type: string + required: + - selector + type: object + submit: + properties: + arguments: + properties: + artifacts: + items: + properties: + archive: + properties: + none: + type: object + tar: + properties: + compressionLevel: + format: int32 + type: integer + type: object + zip: + type: object + type: object + archiveLogs: + type: boolean + artifactGC: + properties: + podMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + serviceAccountName: + type: string + strategy: + enum: + - "" + - OnWorkflowCompletion + - OnWorkflowDeletion + - Never + type: string + type: object + artifactory: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + url: + type: string + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - url + type: object + azure: + properties: + accountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + blob: + type: string + container: + type: string + endpoint: + type: string + useSDKCreds: + type: boolean + required: + - blob + - container + - endpoint + type: object + deleted: + type: boolean + from: + type: string + fromExpression: + type: string + gcs: + properties: + bucket: + type: string + key: + type: string + serviceAccountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - key + type: object + git: + properties: + branch: + type: string + depth: + format: int64 + type: integer + disableSubmodules: + type: boolean + fetch: + items: + type: string + type: array + insecureIgnoreHostKey: + type: boolean + insecureSkipTLS: + type: boolean + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + repo: + type: string + revision: + type: string + singleBranch: + type: boolean + sshPrivateKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - repo + type: object + globalName: + type: string + hdfs: + properties: + addresses: + items: + type: string + type: array + dataTransferProtection: + type: string + force: + type: boolean + hdfsUser: + type: string + krbCCacheSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbConfigConfigMap: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbKeytabSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbRealm: + type: string + krbServicePrincipalName: + type: string + krbUsername: + type: string + path: + type: string + required: + - path + type: object + http: + properties: + auth: + properties: + basicAuth: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientCert: + properties: + clientCertSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + oauth2: + properties: + clientIDSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientSecretSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + items: + properties: + key: + type: string + value: + type: string + required: + - key + type: object + type: array + scopes: + items: + type: string + type: array + tokenURLSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + type: object + headers: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + url: + type: string + required: + - url + type: object + mode: + format: int32 + type: integer + name: + type: string + optional: + type: boolean + oss: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + createBucketIfNotPresent: + type: boolean + endpoint: + type: string + key: + type: string + lifecycleRule: + properties: + markDeletionAfterDays: + format: int32 + type: integer + markInfrequentAccessAfterDays: + format: int32 + type: integer + type: object + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + securityToken: + type: string + useSDKCreds: + type: boolean + required: + - key + type: object + path: + type: string + raw: + properties: + data: + type: string + required: + - data + type: object + recurseMode: + type: boolean + s3: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + caSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + createBucketIfNotPresent: + properties: + objectLocking: + type: boolean + type: object + encryptionOptions: + properties: + enableEncryption: + type: boolean + kmsEncryptionContext: + type: string + kmsKeyId: + type: string + serverSideCustomerKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + endpoint: + type: string + insecure: + type: boolean + key: + type: string + region: + type: string + roleARN: + type: string + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + sessionTokenSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + useSDKCreds: + type: boolean + type: object + subPath: + type: string + required: + - name + type: object + type: array + parameters: + items: + properties: + default: + type: string + description: + type: string + enum: + items: + type: string + type: array + globalName: + type: string + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + default: + type: string + event: + type: string + expression: + type: string + jqFilter: + type: string + jsonPath: + type: string + parameter: + type: string + path: + type: string + supplied: + type: object + type: object + required: + - name + type: object + type: array + type: object + metadata: + type: object + workflowTemplateRef: + properties: + clusterScope: + type: boolean + name: + type: string + type: object + required: + - workflowTemplateRef + type: object + required: + - event + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflows.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflows.yaml new file mode 100644 index 0000000..85b71f9 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflows.yaml @@ -0,0 +1,64 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: workflows.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: Workflow + listKind: WorkflowList + plural: workflows + shortNames: + - wf + singular: workflow + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Status of the workflow + jsonPath: .status.phase + name: Status + type: string + - description: When the workflow was started + format: date-time + jsonPath: .status.startedAt + name: Age + type: date + - description: Human readable message indicating details about why the workflow + is in this condition. + jsonPath: .status.message + name: Message + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: {} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtaskresults.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtaskresults.yaml new file mode 100644 index 0000000..02f3f08 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtaskresults.yaml @@ -0,0 +1,671 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: workflowtaskresults.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: WorkflowTaskResult + listKind: WorkflowTaskResultList + plural: workflowtaskresults + singular: workflowtaskresult + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + message: + type: string + metadata: + type: object + outputs: + properties: + artifacts: + items: + properties: + archive: + properties: + none: + type: object + tar: + properties: + compressionLevel: + format: int32 + type: integer + type: object + zip: + type: object + type: object + archiveLogs: + type: boolean + artifactGC: + properties: + podMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + serviceAccountName: + type: string + strategy: + enum: + - "" + - OnWorkflowCompletion + - OnWorkflowDeletion + - Never + type: string + type: object + artifactory: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + url: + type: string + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - url + type: object + azure: + properties: + accountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + blob: + type: string + container: + type: string + endpoint: + type: string + useSDKCreds: + type: boolean + required: + - blob + - container + - endpoint + type: object + deleted: + type: boolean + from: + type: string + fromExpression: + type: string + gcs: + properties: + bucket: + type: string + key: + type: string + serviceAccountKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - key + type: object + git: + properties: + branch: + type: string + depth: + format: int64 + type: integer + disableSubmodules: + type: boolean + fetch: + items: + type: string + type: array + insecureIgnoreHostKey: + type: boolean + insecureSkipTLS: + type: boolean + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + repo: + type: string + revision: + type: string + singleBranch: + type: boolean + sshPrivateKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + required: + - repo + type: object + globalName: + type: string + hdfs: + properties: + addresses: + items: + type: string + type: array + dataTransferProtection: + type: string + force: + type: boolean + hdfsUser: + type: string + krbCCacheSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbConfigConfigMap: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbKeytabSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + krbRealm: + type: string + krbServicePrincipalName: + type: string + krbUsername: + type: string + path: + type: string + required: + - path + type: object + http: + properties: + auth: + properties: + basicAuth: + properties: + passwordSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + usernameSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientCert: + properties: + clientCertSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + oauth2: + properties: + clientIDSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clientSecretSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + items: + properties: + key: + type: string + value: + type: string + required: + - key + type: object + type: array + scopes: + items: + type: string + type: array + tokenURLSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + type: object + headers: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + url: + type: string + required: + - url + type: object + mode: + format: int32 + type: integer + name: + type: string + optional: + type: boolean + oss: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + createBucketIfNotPresent: + type: boolean + endpoint: + type: string + key: + type: string + lifecycleRule: + properties: + markDeletionAfterDays: + format: int32 + type: integer + markInfrequentAccessAfterDays: + format: int32 + type: integer + type: object + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + securityToken: + type: string + useSDKCreds: + type: boolean + required: + - key + type: object + path: + type: string + raw: + properties: + data: + type: string + required: + - data + type: object + recurseMode: + type: boolean + s3: + properties: + accessKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + bucket: + type: string + caSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + createBucketIfNotPresent: + properties: + objectLocking: + type: boolean + type: object + encryptionOptions: + properties: + enableEncryption: + type: boolean + kmsEncryptionContext: + type: string + kmsKeyId: + type: string + serverSideCustomerKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + endpoint: + type: string + insecure: + type: boolean + key: + type: string + region: + type: string + roleARN: + type: string + secretKeySecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + sessionTokenSecret: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + useSDKCreds: + type: boolean + type: object + subPath: + type: string + required: + - name + type: object + type: array + exitCode: + type: string + parameters: + items: + properties: + default: + type: string + description: + type: string + enum: + items: + type: string + type: array + globalName: + type: string + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + default: + type: string + event: + type: string + expression: + type: string + jqFilter: + type: string + jsonPath: + type: string + parameter: + type: string + path: + type: string + supplied: + type: object + type: object + required: + - name + type: object + type: array + result: + type: string + type: object + phase: + type: string + progress: + type: string + required: + - metadata + type: object + served: true + storage: true +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtasksets.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtasksets.yaml new file mode 100644 index 0000000..7469294 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtasksets.yaml @@ -0,0 +1,50 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: workflowtasksets.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: WorkflowTaskSet + listKind: WorkflowTaskSetList + plural: workflowtasksets + shortNames: + - wfts + singular: workflowtaskset + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtemplates.yaml b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtemplates.yaml new file mode 100644 index 0000000..810e6f5 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/crds/argoproj.io_workflowtemplates.yaml @@ -0,0 +1,44 @@ +{{- if .Values.crds.install }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: workflowtemplates.argoproj.io + annotations: + {{- if .Values.crds.keep }} + "helm.sh/resource-policy": keep + {{- end }} + {{- with .Values.crds.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + group: argoproj.io + names: + kind: WorkflowTemplate + listKind: WorkflowTemplateList + plural: workflowtemplates + shortNames: + - wftmpl + singular: workflowtemplate + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + x-kubernetes-map-type: atomic + x-kubernetes-preserve-unknown-fields: true + required: + - metadata + - spec + type: object + served: true + storage: true +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/extra-manifests.yaml b/utils/assets/charts/argo-workflows/templates/extra-manifests.yaml new file mode 100644 index 0000000..fc9a76b --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/extra-manifests.yaml @@ -0,0 +1,8 @@ +{{ range .Values.extraObjects }} +--- +{{ if typeIs "string" . }} + {{- tpl . $ }} +{{- else }} + {{- tpl (toYaml .) $ }} +{{- end }} +{{ end }} diff --git a/utils/assets/charts/argo-workflows/templates/server/gke/backendconfig.yaml b/utils/assets/charts/argo-workflows/templates/server/gke/backendconfig.yaml new file mode 100644 index 0000000..0d439b6 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/gke/backendconfig.yaml @@ -0,0 +1,11 @@ +{{- if .Values.server.GKEbackendConfig.enabled }} +apiVersion: {{ include "argo-workflows.apiVersions.cloudgoogle" . }} +kind: BackendConfig +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +spec: + {{- toYaml .Values.server.GKEbackendConfig.spec | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/server/gke/frontendconfig.yaml b/utils/assets/charts/argo-workflows/templates/server/gke/frontendconfig.yaml new file mode 100644 index 0000000..32cfc3a --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/gke/frontendconfig.yaml @@ -0,0 +1,11 @@ +{{- if .Values.server.GKEfrontendConfig.enabled }} +apiVersion: networking.gke.io/v1beta1 +kind: FrontendConfig +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +spec: + {{- toYaml .Values.server.GKEfrontendConfig.spec | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/server/gke/managedcertificate.yaml b/utils/assets/charts/argo-workflows/templates/server/gke/managedcertificate.yaml new file mode 100644 index 0000000..4d1f840 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/gke/managedcertificate.yaml @@ -0,0 +1,12 @@ +{{- if .Values.server.GKEmanagedCertificate.enabled }} +apiVersion: networking.gke.io/v1 +kind: ManagedCertificate +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} +spec: + domains: + {{- with .Values.server.GKEmanagedCertificate.domains }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-cluster-roles.yaml b/utils/assets/charts/argo-workflows/templates/server/server-cluster-roles.yaml new file mode 100644 index 0000000..f095309 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-cluster-roles.yaml @@ -0,0 +1,145 @@ +{{- if and .Values.server.enabled .Values.server.rbac.create}} +apiVersion: rbac.authorization.k8s.io/v1 + {{- if .Values.singleNamespace }} +kind: Role + {{- else }} +kind: ClusterRole + {{- end }} +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + {{- if .Values.singleNamespace }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + {{- end }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + - events + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - delete +- apiGroups: + - "" + resources: + - pods/log + verbs: + - get + - list +{{- if .Values.server.sso.enabled }} +- apiGroups: + - "" + resources: + - secrets + resourceNames: + - sso + verbs: + - get +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + {{- if .Values.server.sso.rbac.enabled }} +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list + - watch + {{- end }} +{{- end }} +- apiGroups: + - "" + resources: + - secrets + verbs: + - get +{{- if and .Values.server.sso.enabled .Values.server.sso.rbac.enabled }} + {{- with .Values.server.sso.rbac.secretWhitelist }} + resourceNames: {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +- apiGroups: + - "" + resources: + - events + verbs: + - watch + - create + - patch +{{- if .Values.controller.persistence }} +- apiGroups: + - "" + resources: + - secrets + resourceNames: + {{- with .Values.controller.persistence.postgresql }} + - {{ .userNameSecret.name }} + - {{ .passwordSecret.name }} + {{- end}} + {{- with .Values.controller.persistence.mysql }} + - {{ .userNameSecret.name }} + - {{ .passwordSecret.name }} + {{- end}} + verbs: + - get +{{- end}} +- apiGroups: + - argoproj.io + resources: + - eventsources + - sensors + - workflows + - workfloweventbindings + - workflowtemplates + - cronworkflows + verbs: + - create + - get + - list + - watch + - update + - patch + - delete + +{{- if and .Values.server.clusterWorkflowTemplates.enabled (not .Values.singleNamespace) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "argo-workflows.server.fullname" . }}-cluster-template + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +rules: +- apiGroups: + - argoproj.io + resources: + - clusterworkflowtemplates + verbs: + - get + - list + - watch + {{- if .Values.server.clusterWorkflowTemplates.enableEditing }} + - create + - update + - patch + - delete + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-crb.yaml b/utils/assets/charts/argo-workflows/templates/server/server-crb.yaml new file mode 100644 index 0000000..4ffb910 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-crb.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.server.enabled .Values.server.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +{{- if .Values.singleNamespace }} +kind: RoleBinding +{{ else }} +kind: ClusterRoleBinding +{{- end }} +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + {{- if .Values.singleNamespace }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + {{- end }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + {{- if .Values.singleNamespace }} + kind: Role + {{ else }} + kind: ClusterRole + {{- end }} + name: {{ template "argo-workflows.server.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ template "argo-workflows.serverServiceAccountName" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + +{{- if .Values.server.clusterWorkflowTemplates.enabled }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "argo-workflows.server.fullname" . }}-cluster-template + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "argo-workflows.server.fullname" . }}-cluster-template +subjects: +- kind: ServiceAccount + name: {{ template "argo-workflows.serverServiceAccountName" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-deployment-hpa.yaml b/utils/assets/charts/argo-workflows/templates/server/server-deployment-hpa.yaml new file mode 100644 index 0000000..142bc31 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-deployment-hpa.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.server.enabled .Values.server.autoscaling.enabled }} +apiVersion: {{ include "argo-workflows.apiVersion.autoscaling" . }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "argo-workflows.server.fullname" . }} + minReplicas: {{ .Values.server.autoscaling.minReplicas }} + maxReplicas: {{ .Values.server.autoscaling.maxReplicas }} + metrics: + {{- with .Values.server.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if eq (include "argo-workflows.apiVersion.autoscaling" $) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ . }} + {{- else }} + target: + averageUtilization: {{ . }} + type: Utilization + {{- end }} + {{- end }} + {{- with .Values.server.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if eq (include "argo-workflows.apiVersion.autoscaling" $) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ . }} + {{- else }} + target: + averageUtilization: {{ . }} + type: Utilization + {{- end }} + {{- end }} + {{- with .Values.server.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-deployment-pdb.yaml b/utils/assets/charts/argo-workflows/templates/server/server-deployment-pdb.yaml new file mode 100644 index 0000000..47f8394 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-deployment-pdb.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.server.enabled .Values.server.pdb.enabled -}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} +spec: + {{- if .Values.server.pdb.minAvailable }} + minAvailable: {{ .Values.server.pdb.minAvailable }} + {{- else if .Values.server.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.server.pdb.maxUnavailable }} + {{- else }} + minAvailable: 0 + {{- end }} + selector: + matchLabels: + {{- include "argo-workflows.selectorLabels" (dict "context" . "name" .Values.server.name) | nindent 6 }} +{{- end -}} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-deployment.yaml b/utils/assets/charts/argo-workflows/templates/server/server-deployment.yaml new file mode 100644 index 0000000..b9a2541 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-deployment.yaml @@ -0,0 +1,157 @@ +{{- if .Values.server.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} + app.kubernetes.io/version: {{ include "argo-workflows.server_chart_version_label" . }} + {{- with .Values.server.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if not .Values.server.autoscaling.enabled }} + replicas: {{ .Values.server.replicas }} + {{- end }} + revisionHistoryLimit: {{ .Values.server.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "argo-workflows.selectorLabels" (dict "context" . "name" .Values.server.name) | nindent 6 }} + template: + metadata: + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 8 }} + app.kubernetes.io/version: {{ include "argo-workflows.server_chart_version_label" . }} + {{- with .Values.server.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "argo-workflows.serverServiceAccountName" . }} + {{- with .Values.server.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.extraInitContainers }} + initContainers: + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + containers: + - name: argo-server + image: "{{- include "argo-workflows.image" (dict "context" . "image" .Values.server.image) }}:{{ default (include "argo-workflows.defaultTag" .) .Values.server.image.tag }}" + imagePullPolicy: {{ .Values.images.pullPolicy }} + securityContext: + {{- toYaml .Values.server.securityContext | nindent 12 }} + args: + - server + - --configmap={{ template "argo-workflows.controller.config-map.name" . }} + {{- with .Values.server.extraArgs }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.server.authMode }} + - "--auth-mode={{ .Values.server.authMode }}" + {{- end }} + {{- range .Values.server.authModes }} + - "--auth-mode={{ . }}" + {{- end }} + - "--secure={{ .Values.server.secure }}" + {{- if .Values.singleNamespace }} + - "--namespaced" + {{- end }} + - "--loglevel" + - "{{ .Values.server.logging.level }}" + - "--gloglevel" + - "{{ .Values.server.logging.globallevel }}" + - "--log-format" + - "{{ .Values.server.logging.format }}" + ports: + - name: web + containerPort: 2746 + readinessProbe: + httpGet: + path: / + port: 2746 + {{- if .Values.server.secure }} + scheme: HTTPS + {{- else }} + scheme: HTTP + {{- end }} + initialDelaySeconds: 10 + periodSeconds: 20 + env: + - name: IN_CLUSTER + value: "true" + - name: ARGO_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ARGO_BASE_HREF + value: {{ .Values.server.baseHref | quote }} + {{- with .Values.server.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.server.resources | nindent 12 }} + volumeMounts: + - name: tmp + mountPath: /tmp + {{- with .Values.server.volumeMounts }} + {{- toYaml . | nindent 10}} + {{- end }} + {{- with .Values.server.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.server.extraContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ . }} + {{- end }} + {{- with .Values.images.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: tmp + {{- toYaml .Values.server.tmpVolume | nindent 8 }} + {{- with .Values.server.volumes }} + {{- toYaml . | nindent 6}} + {{- end }} + {{- with .Values.server.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := . }} + - {{ toYaml $constraint | nindent 8 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + {{- include "argo-workflows.selectorLabels" (dict "context" $ "name" $.Values.server.name) | nindent 12 }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.server.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-ingress.yaml b/utils/assets/charts/argo-workflows/templates/server/server-ingress.yaml new file mode 100644 index 0000000..db69b01 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-ingress.yaml @@ -0,0 +1,90 @@ +{{- if .Values.server.ingress.enabled -}} +{{- $serviceName := include "argo-workflows.server.fullname" . -}} +{{- $servicePort := .Values.server.servicePort -}} +{{- $paths := .Values.server.ingress.paths -}} +{{- $extraPaths := .Values.server.ingress.extraPaths -}} +{{- $pathType := .Values.server.ingress.pathType -}} +apiVersion: {{ include "argo-workflows.ingress.apiVersion" . }} +kind: Ingress +metadata: +{{- if .Values.server.ingress.annotations }} + annotations: + {{- range $key, $value := .Values.server.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} + {{- if .Values.server.ingress.labels }} + {{- toYaml .Values.server.ingress.labels | nindent 4 }} + {{- end }} +spec: + {{- if eq (include "argo-workflows.ingress.apiVersion" $) "networking.k8s.io/v1" }} + {{- with .Values.server.ingress.ingressClassName }} + ingressClassName: {{ . }} + {{- end }} + {{- end }} + rules: + {{- if .Values.server.ingress.hosts }} + {{- range $host := .Values.server.ingress.hosts }} + - host: {{ $host }} + http: + paths: + {{- if $extraPaths }} + {{- toYaml $extraPaths | nindent 10 }} + {{- end }} + {{- range $p := $paths }} + - path: {{ $p }} + {{- if eq (include "argo-workflows.ingress.apiVersion" $) "networking.k8s.io/v1" }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if eq (include "argo-workflows.ingress.apiVersion" $) "networking.k8s.io/v1" }} + service: + name: {{ $serviceName }} + port: + {{- if kindIs "float64" $servicePort }} + number: {{ $servicePort }} + {{- else }} + name: {{ $servicePort }} + {{- end }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- else }} + - http: + paths: + {{- if $extraPaths }} + {{- toYaml $extraPaths | nindent 10 }} + {{- end }} + {{- range $p := $paths }} + - path: {{ $p }} + {{- if eq (include "argo-workflows.ingress.apiVersion" $) "networking.k8s.io/v1" }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if eq (include "argo-workflows.ingress.apiVersion" $) "networking.k8s.io/v1" }} + service: + name: {{ $serviceName }} + port: + {{- if kindIs "float64" $servicePort }} + number: {{ $servicePort }} + {{- else }} + name: {{ $servicePort }} + {{- end }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- if .Values.server.ingress.tls }} + tls: + {{- toYaml .Values.server.ingress.tls | nindent 4 }} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-sa.yaml b/utils/assets/charts/argo-workflows/templates/server/server-sa.yaml new file mode 100644 index 0000000..d2c9c53 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-sa.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.server.enabled .Values.server.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "argo-workflows.serverServiceAccountName" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} + {{- with .Values.server.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.server.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/argo-workflows/templates/server/server-service.yaml b/utils/assets/charts/argo-workflows/templates/server/server-service.yaml new file mode 100644 index 0000000..39c3779 --- /dev/null +++ b/utils/assets/charts/argo-workflows/templates/server/server-service.yaml @@ -0,0 +1,43 @@ +{{- if .Values.server.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "argo-workflows.server.fullname" . }} + namespace: {{ include "argo-workflows.namespace" . | quote }} + labels: + {{- include "argo-workflows.labels" (dict "context" . "component" .Values.server.name "name" .Values.server.name) | nindent 4 }} + app.kubernetes.io/version: {{ include "argo-workflows.server_chart_version_label" . }} + {{- with .Values.server.serviceLabels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.server.serviceAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ports: + - port: {{ .Values.server.servicePort }} + {{- with .Values.server.servicePortName }} + name: {{ . }} + {{- end }} + targetPort: 2746 + {{- if and (eq .Values.server.serviceType "NodePort") .Values.server.serviceNodePort }} + nodePort: {{ .Values.server.serviceNodePort }} + {{- end }} + selector: + {{- include "argo-workflows.selectorLabels" (dict "context" . "name" .Values.server.name) | nindent 4 }} + sessionAffinity: None + type: {{ .Values.server.serviceType }} + {{- if eq .Values.server.serviceType "LoadBalancer" }} + {{- with .Values.controller.loadBalancerClass }} + loadBalancerClass: {{ . }} + {{- end }} + {{- with .Values.server.loadBalancerIP }} + loadBalancerIP: {{ . | quote }} + {{- end }} + {{- if .Values.server.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml .Values.server.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/argo-workflows/values.yaml b/utils/assets/charts/argo-workflows/values.yaml new file mode 100644 index 0000000..cf9b08d --- /dev/null +++ b/utils/assets/charts/argo-workflows/values.yaml @@ -0,0 +1,943 @@ +images: + # -- Common tag for Argo Workflows images. Defaults to `.Chart.AppVersion`. + tag: "" + # -- imagePullPolicy to apply to all containers + pullPolicy: Always + # -- Secrets with credentials to pull images from a private registry + pullSecrets: [] + # - name: argo-pull-secret + +## Custom resource configuration +crds: + # -- Install and upgrade CRDs + install: true + # -- Keep CRDs on chart uninstall + keep: true + # -- Annotations to be added to all CRDs + annotations: {} + +# -- Create clusterroles that extend existing clusterroles to interact with argo-cd crds +## Ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles +createAggregateRoles: true + +# -- String to partially override "argo-workflows.fullname" template +nameOverride: + +# -- String to fully override "argo-workflows.fullname" template +fullnameOverride: + +# -- Override the namespace +# @default -- `.Release.Namespace` +namespaceOverride: "" + +# -- Labels to set on all resources +commonLabels: {} + +# -- Override the Kubernetes version, which is used to evaluate certain manifests +kubeVersionOverride: "" + +# Override APIVersions +apiVersionOverrides: + # -- String to override apiVersion of autoscaling rendered by this helm chart + autoscaling: "" # autoscaling/v2 + # -- String to override apiVersion of GKE resources rendered by this helm chart + cloudgoogle: "" # cloud.google.com/v1 + # -- String to override apiVersion of monitoring CRDs (ServiceMonitor) rendered by this helm chart + monitoring: "" # monitoring.coreos.com/v1 + +# -- Restrict Argo to operate only in a single namespace (the namespace of the +# Helm release) by apply Roles and RoleBindings instead of the Cluster +# equivalents, and start workflow-controller with the --namespaced flag. Use it +# in clusters with strict access policy. +singleNamespace: false + +workflow: + # -- Deprecated; use controller.workflowNamespaces instead. + namespace: + serviceAccount: + # -- Specifies whether a service account should be created + create: false + # -- Labels applied to created service account + labels: {} + # -- Annotations applied to created service account + annotations: {} + # -- Service account which is used to run workflows + name: "argo-workflow" + # -- Secrets with credentials to pull images from a private registry. Same format as `.Values.images.pullSecrets` + pullSecrets: [] + rbac: + # -- Adds Role and RoleBinding for the above specified service account to be able to run workflows. + # A Role and Rolebinding pair is also created for each namespace in controller.workflowNamespaces (see below) + create: true + # -- Allows permissions for the Argo Agent. Only required if using http/plugin templates + agentPermissions: false + # -- Allows permissions for the Argo Artifact GC pod. Only required if using artifact gc + artifactGC: false + # -- Extra service accounts to be added to the RoleBinding + serviceAccounts: [] + # - name: my-service-account + # namespace: my-namespace + +controller: + image: + # -- Registry to use for the controller + registry: quay.io + # -- Registry to use for the controller + repository: argoproj/workflow-controller + # -- Image tag for the workflow controller. Defaults to `.Values.images.tag`. + tag: "" + # -- parallelism dictates how many workflows can be running at the same time + parallelism: + # -- Globally limits the rate at which pods are created. + # This is intended to mitigate flooding of the Kubernetes API server by workflows with a large amount of + # parallel nodes. + resourceRateLimit: {} + # limit: 10 + # burst: 1 + + rbac: + # -- Adds Role and RoleBinding for the controller. + create: true + # -- Allows controller to get, list, and watch certain k8s secrets + secretWhitelist: [] + # -- Allows controller to get, list and watch all k8s secrets. Can only be used if secretWhitelist is empty. + accessAllSecrets: false + # -- Allows controller to create and update ConfigMaps. Enables memoization feature + writeConfigMaps: false + + configMap: + # -- Create a ConfigMap for the controller + create: true + # -- ConfigMap name + name: "" + # -- ConfigMap annotations + annotations: {} + + # -- Limits the maximum number of incomplete workflows in a namespace + namespaceParallelism: + # -- Resolves ongoing, uncommon AWS EKS bug: https://github.com/argoproj/argo-workflows/pull/4224 + initialDelay: + # -- deploymentAnnotations is an optional map of annotations to be applied to the controller Deployment + deploymentAnnotations: {} + # -- podAnnotations is an optional map of annotations to be applied to the controller Pods + podAnnotations: {} + # -- Optional labels to add to the controller pods + podLabels: {} + # -- SecurityContext to set on the controller pods + podSecurityContext: {} + # podPortName: http + metricsConfig: + # -- Enables prometheus metrics server + enabled: false + # -- Path is the path where metrics are emitted. Must start with a "/". + path: /metrics + # -- Frequency at which prometheus scrapes metrics + interval: 30s + # -- Port is the port where metrics are emitted + port: 9090 + # -- How often custom metrics are cleared from memory + metricsTTL: "" + # -- Flag that instructs prometheus to ignore metric emission errors. + ignoreErrors: false + # -- Flag that use a self-signed cert for TLS + secure: false + # -- Container metrics port name + portName: metrics + # -- Service metrics port + servicePort: 8080 + # -- Service metrics port name + servicePortName: metrics + # -- Flag to enable headless service + headlessService: false + # -- When true, honorLabels preserves the metric’s labels when they collide with the target’s labels. + ## Ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#honorlabels + honorLabels: false + # -- ServiceMonitor relabel configs to apply to samples before scraping + ## Ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + relabelings: [] + # -- ServiceMonitor metric relabel configs to apply to samples before ingestion + ## Ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#endpoint + metricRelabelings: [] + # -- ServiceMonitor will add labels from the service to the Prometheus metric + ## Ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#servicemonitorspec + targetLabels: [] + # -- the controller container's securityContext + securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + # -- enable Workflow Archive to store the status of workflows. Postgres and MySQL (>= 5.7.8) are available. + ## Ref: https://argo-workflows.readthedocs.io/en/stable/workflow-archive/ + persistence: {} + # connectionPool: + # maxIdleConns: 100 + # maxOpenConns: 0 + # # save the entire workflow into etcd and DB + # nodeStatusOffLoad: false + # # enable archiving of old workflows + # archive: false + # postgresql: + # host: localhost + # port: 5432 + # database: postgres + # tableName: argo_workflows + # # the database secrets must be in the same namespace of the controller + # userNameSecret: + # name: argo-postgres-config + # key: username + # passwordSecret: + # name: argo-postgres-config + # key: password + # ssl: true + # # sslMode must be one of: disable, require, verify-ca, verify-full + # # you can find more information about those ssl options here: https://godoc.org/github.com/lib/pq + # sslMode: require + # mysql: + # host: localhost + # port: 3306 + # database: argo + # tableName: argo_workflows + # userNameSecret: + # name: argo-mysql-config + # key: username + # passwordSecret: + # name: argo-mysql-config + # key: password + + # -- Default values that will apply to all Workflows from this controller, unless overridden on the Workflow-level. + # Only valid for 2.7+ + ## See more: https://argo-workflows.readthedocs.io/en/stable/default-workflow-specs/ + workflowDefaults: {} + # spec: + # ttlStrategy: + # secondsAfterCompletion: 86400 + # # Ref: https://argo-workflows.readthedocs.io/en/stable/artifact-repository-ref/ + # artifactRepositoryRef: + # configMap: my-artifact-repository # default is "artifact-repositories" + # key: v2-s3-artifact-repository # default can be set by the `workflows.argoproj.io/default-artifact-repository` annotation in config map. + + # -- Number of workflow workers + workflowWorkers: # 32 + # -- Number of workflow TTL workers + workflowTTLWorkers: # 4 + # -- Number of pod cleanup workers + podCleanupWorkers: # 4 + # -- Number of cron workflow workers + # Only valid for 3.5+ + cronWorkflowWorkers: # 8 + # -- Restricts the Workflows that the controller will process. + # Only valid for 2.9+ + workflowRestrictions: {} + # templateReferencing: Strict|Secure + + # telemetryConfig controls the path and port for prometheus telemetry. Telemetry is enabled and emitted in the same endpoint + # as metrics by default, but can be overridden using this config. + telemetryConfig: + # -- Enables prometheus telemetry server + enabled: false + # -- telemetry path + path: /telemetry + # -- Frequency at which prometheus scrapes telemetry data + interval: 30s + # -- telemetry container port + port: 8081 + # -- How often custom metrics are cleared from memory + metricsTTL: "" + # -- Flag that instructs prometheus to ignore metric emission errors. + ignoreErrors: false + # -- Flag that use a self-signed cert for TLS + secure: false + # -- telemetry service port + servicePort: 8081 + # -- telemetry service port name + servicePortName: telemetry + serviceMonitor: + # -- Enable a prometheus ServiceMonitor + enabled: false + # -- Prometheus ServiceMonitor labels + additionalLabels: {} + # -- Prometheus ServiceMonitor namespace + namespace: "" # "monitoring" + serviceAccount: + # -- Create a service account for the controller + create: true + # -- Service account name + name: "" + # -- Labels applied to created service account + labels: {} + # -- Annotations applied to created service account + annotations: {} + + # -- Workflow controller name string + name: workflow-controller + + # -- Specify all namespaces where this workflow controller instance will manage + # workflows. This controls where the service account and RBAC resources will + # be created. Only valid when singleNamespace is false. + workflowNamespaces: + - default + + instanceID: + # -- Configures the controller to filter workflow submissions + # to only those which have a matching instanceID attribute. + ## NOTE: If `instanceID.enabled` is set to `true` then either `instanceID.userReleaseName` + ## or `instanceID.explicitID` must be defined. + enabled: false + # -- Use ReleaseName as instanceID + useReleaseName: false + # useReleaseName: true + + # -- Use a custom instanceID + explicitID: "" + # explicitID: unique-argo-controller-identifier + + logging: + # -- Set the logging level (one of: `debug`, `info`, `warn`, `error`) + level: info + # -- Set the glog logging level + globallevel: "0" + # -- Set the logging format (one of: `text`, `json`) + format: "text" + + # -- Service type of the controller Service + serviceType: ClusterIP + # -- Annotations to be applied to the controller Service + serviceAnnotations: {} + # -- Optional labels to add to the controller Service + serviceLabels: {} + # -- The class of the load balancer implementation + loadBalancerClass: "" + # -- Source ranges to allow access to service from. Only applies to service type `LoadBalancer` + loadBalancerSourceRanges: [] + + # -- Resource limits and requests for the controller + resources: {} + + # -- Configure liveness [probe] for the controller + # @default -- See [values.yaml] + livenessProbe: + httpGet: + port: 6060 + path: /healthz + failureThreshold: 3 + initialDelaySeconds: 90 + periodSeconds: 60 + timeoutSeconds: 30 + + # -- Extra environment variables to provide to the controller container + extraEnv: [] + # - name: FOO + # value: "bar" + + # -- Extra arguments to be added to the controller + extraArgs: [] + # -- Additional volume mounts to the controller main container + volumeMounts: [] + # -- Additional volumes to the controller pod + volumes: [] + # -- The number of controller pods to run + replicas: 1 + # -- The number of revisions to keep. + revisionHistoryLimit: 10 + + pdb: + # -- Configure [Pod Disruption Budget] for the controller pods + enabled: false + # minAvailable: 1 + # maxUnavailable: 1 + + # -- [Node selector] + nodeSelector: + kubernetes.io/os: linux + # -- [Tolerations] for use with node taints + tolerations: [] + # -- Assign custom [affinity] rules + affinity: {} + + # -- Assign custom [TopologySpreadConstraints] rules to the workflow controller + ## 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 + + # -- Leverage a PriorityClass to ensure your pods survive resource shortages. + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + priorityClassName: "" + + # -- Configure Argo Server to show custom [links] + ## Ref: https://argo-workflows.readthedocs.io/en/stable/links/ + links: [] + # -- Configure Argo Server to show custom [columns] + ## Ref: https://github.com/argoproj/argo-workflows/pull/10693 + columns: [] + # -- Set ui navigation bar background color + navColor: "" + clusterWorkflowTemplates: + # -- Create a ClusterRole and CRB for the controller to access ClusterWorkflowTemplates. + enabled: true + # -- Extra service accounts to be added to the ClusterRoleBinding + serviceAccounts: [] + # - name: my-service-account + # namespace: my-namespace + # -- Extra containers to be added to the controller deployment + extraContainers: [] + + # -- Enables init containers to be added to the controller deployment + extraInitContainers: [] + + # -- Workflow retention by number of workflows + retentionPolicy: {} + # completed: 10 + # failed: 3 + # errored: 3 + + nodeEvents: + # -- Enable to emit events on node completion. + ## This can take up a lot of space in k8s (typically etcd) resulting in errors when trying to create new events: + ## "Unable to create audit event: etcdserver: mvcc: database space exceeded" + enabled: true + + workflowEvents: + # -- Enable to emit events on workflow status changes. + ## This can take up a lot of space in k8s (typically etcd), resulting in errors when trying to create new events: + ## "Unable to create audit event: etcdserver: mvcc: database space exceeded" + enabled: true + + # -- Configure when workflow controller runs in a different k8s cluster with the workflow workloads, + # or needs to communicate with the k8s apiserver using an out-of-cluster kubeconfig secret. + # @default -- `{}` (See [values.yaml]) + kubeConfig: {} + # # name of the kubeconfig secret, may not be empty when kubeConfig specified + # secretName: kubeconfig-secret + # # key of the kubeconfig secret, may not be empty when kubeConfig specified + # secretKey: kubeconfig + # # mounting path of the kubeconfig secret, default to /kube/config + # mountPath: /kubeconfig/mount/path + # # volume name when mounting the secret, default to kubeconfig + # volumeName: kube-config-volume + + # -- Specifies the duration in seconds before a terminating pod is forcefully killed. A zero value indicates that the pod will be forcefully terminated immediately. + # @default -- `30` seconds (Kubernetes default) + podGCGracePeriodSeconds: + + # -- The duration in seconds before the pods in the GC queue get deleted. A zero value indicates that the pods will be deleted immediately. + # @default -- `5s` (Argo Workflows default) + podGCDeleteDelayDuration: "" + +# mainContainer adds default config for main container that could be overriden in workflows template +mainContainer: + # -- imagePullPolicy to apply to Workflow main container. Defaults to `.Values.images.pullPolicy`. + imagePullPolicy: "" + # -- Resource limits and requests for the Workflow main container + resources: {} + # -- Adds environment variables for the Workflow main container + env: [] + # -- Adds reference environment variables for the Workflow main container + envFrom: [] + # -- sets security context for the Workflow main container + securityContext: {} + +# executor controls how the init and wait container should be customized +executor: + image: + # -- Registry to use for the Workflow Executors + registry: quay.io + # -- Repository to use for the Workflow Executors + repository: argoproj/argoexec + # -- Image tag for the workflow executor. Defaults to `.Values.images.tag`. + tag: "" + # -- Image PullPolicy to use for the Workflow Executors. Defaults to `.Values.images.pullPolicy`. + pullPolicy: "" + # -- Resource limits and requests for the Workflow Executors + resources: {} + # -- Passes arguments to the executor processes + args: [] + # -- Adds environment variables for the executor. + env: [] + # -- sets security context for the executor container + securityContext: {} + +server: + # -- Deploy the Argo Server + enabled: true + # -- Value for base href in index.html. Used if the server is running behind reverse proxy under subpath different from /. + ## only updates base url of resources on client side, + ## it's expected that a proxy server rewrites the request URL and gets rid of this prefix + ## https://github.com/argoproj/argo-workflows/issues/716#issuecomment-433213190 + baseHref: / + image: + # -- Registry to use for the server + registry: quay.io + # -- Repository to use for the server + repository: argoproj/argocli + # -- Image tag for the Argo Workflows server. Defaults to `.Values.images.tag`. + tag: "" + # -- optional map of annotations to be applied to the ui Deployment + deploymentAnnotations: {} + # -- optional map of annotations to be applied to the ui Pods + podAnnotations: {} + # -- Optional labels to add to the UI pods + podLabels: {} + # -- SecurityContext to set on the server pods + podSecurityContext: {} + rbac: + # -- Adds Role and RoleBinding for the server. + create: true + # -- Servers container-level security context + securityContext: + readOnlyRootFilesystem: false + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + # -- Server name string + name: server + # -- Service type for server pods + serviceType: ClusterIP + # -- Service port for server + servicePort: 2746 + # -- Service node port + serviceNodePort: # 32746 + # -- Service port name + servicePortName: "" # http + + # -- Mapping between IP and hostnames that will be injected as entries in the pod's hosts files + hostAliases: [] + # - ip: 10.20.30.40 + # hostnames: + # - git.myhostname + + serviceAccount: + # -- Create a service account for the server + create: true + # -- Service account name + name: "" + # -- Labels applied to created service account + labels: {} + # -- Annotations applied to created service account + annotations: {} + + # -- Annotations to be applied to the UI Service + serviceAnnotations: {} + # -- Optional labels to add to the UI Service + serviceLabels: {} + # -- The class of the load balancer implementation + loadBalancerClass: "" + # -- Static IP address to assign to loadBalancer service type `LoadBalancer` + loadBalancerIP: "" + # -- Source ranges to allow access to service from. Only applies to service type `LoadBalancer` + loadBalancerSourceRanges: [] + # -- Resource limits and requests for the server + resources: {} + # -- The number of server pods to run + replicas: 1 + # -- The number of revisions to keep. + revisionHistoryLimit: 10 + ## Argo Server Horizontal Pod Autoscaler + autoscaling: + # -- Enable Horizontal Pod Autoscaler ([HPA]) for the Argo Server + enabled: false + # -- Minimum number of replicas for the Argo Server [HPA] + minReplicas: 1 + # -- Maximum number of replicas for the Argo Server [HPA] + maxReplicas: 5 + # -- Average CPU utilization percentage for the Argo Server [HPA] + targetCPUUtilizationPercentage: 50 + # -- Average memory utilization percentage for the Argo Server [HPA] + targetMemoryUtilizationPercentage: 50 + # -- Configures the scaling behavior of the target in both Up and Down directions. + # This is only available on HPA apiVersion `autoscaling/v2beta2` and newer + behavior: {} + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 2 + pdb: + # -- Configure [Pod Disruption Budget] for the server pods + enabled: false + # minAvailable: 1 + # maxUnavailable: 1 + + # -- [Node selector] + nodeSelector: + kubernetes.io/os: linux + + # -- [Tolerations] for use with node taints + tolerations: [] + + # -- Assign custom [affinity] rules + affinity: {} + + # -- Assign custom [TopologySpreadConstraints] rules to the argo server + ## 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 + + # -- Leverage a PriorityClass to ensure your pods survive resource shortages + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + priorityClassName: "" + + # -- Run the argo server in "secure" mode. Configure this value instead of `--secure` in extraArgs. + ## See the following documentation for more details on secure mode: + ## https://argo-workflows.readthedocs.io/en/stable/tls/ + secure: false + + # -- Extra environment variables to provide to the argo-server container + extraEnv: [] + # - name: FOO + # value: "bar" + + # -- Deprecated; use server.authModes instead. + authMode: "" + + # -- A list of supported authentication modes. Available values are `server`, `client`, or `sso`. If you provide sso, please configure `.Values.server.sso` as well. + ## Ref: https://argo-workflows.readthedocs.io/en/stable/argo-server-auth-mode/ + authModes: [] + + # -- Extra arguments to provide to the Argo server binary. + ## Ref: https://argo-workflows.readthedocs.io/en/stable/argo-server/#options + extraArgs: [] + + logging: + # -- Set the logging level (one of: `debug`, `info`, `warn`, `error`) + level: info + # -- Set the glog logging level + globallevel: "0" + # -- Set the logging format (one of: `text`, `json`) + format: "text" + + # -- Volume to be mounted in Pods for temporary files. + tmpVolume: + emptyDir: {} + # -- Additional volume mounts to the server main container. + volumeMounts: [] + # -- Additional volumes to the server pod. + volumes: [] + + ## Ingress configuration. + # ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ + ingress: + # -- Enable an ingress resource + enabled: false + # -- Additional ingress annotations + annotations: {} + # -- Additional ingress labels + labels: {} + # -- Defines which ingress controller will implement the resource + ingressClassName: "" + + # -- List of ingress hosts + ## Hostnames must be provided if Ingress is enabled. + ## Secrets must be manually created in the namespace + hosts: [] + # - argoworkflows.example.com + + # -- List of ingress paths + paths: + - / + + # -- Ingress path type. One of `Exact`, `Prefix` or `ImplementationSpecific` + pathType: Prefix + # -- Additional ingress paths + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + ## for Kubernetes >=1.19 (when "networking.k8s.io/v1" is used) + # - path: /* + # pathType: Prefix + # backend: + # service + # name: ssl-redirect + # port: + # name: use-annotation + + # -- Ingress TLS configuration + tls: [] + # - secretName: argoworkflows-example-tls + # hosts: + # - argoworkflows.example.com + + ## Create a Google Backendconfig for use with the GKE Ingress Controller + ## https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-configuration#configuring_ingress_features_through_backendconfig_parameters + GKEbackendConfig: + # -- Enable BackendConfig custom resource for Google Kubernetes Engine + enabled: false + # -- [BackendConfigSpec] + spec: {} + # spec: + # iap: + # enabled: true + # oauthclientCredentials: + # secretName: argoworkflows-secret + + ## Create a Google Managed Certificate for use with the GKE Ingress Controller + ## https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs + GKEmanagedCertificate: + # -- Enable ManagedCertificate custom resource for Google Kubernetes Engine. + enabled: false + # -- Domains for the Google Managed Certificate + domains: + - argoworkflows.example.com + + ## Create a Google FrontendConfig Custom Resource, for use with the GKE Ingress Controller + ## https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#configuring_ingress_features_through_frontendconfig_parameters + GKEfrontendConfig: + # -- Enable FrontConfig custom resource for Google Kubernetes Engine + enabled: false + # -- [FrontendConfigSpec] + spec: {} + # spec: + # redirectToHttps: + # enabled: true + # responseCodeName: RESPONSE_CODE + + clusterWorkflowTemplates: + # -- Create a ClusterRole and CRB for the server to access ClusterWorkflowTemplates. + enabled: true + # -- Give the server permissions to edit ClusterWorkflowTemplates. + enableEditing: true + + # SSO configuration when SSO is specified as a server auth mode. + sso: + # -- Create SSO configuration. If you set `true` , please also set `.Values.server.authMode` as `sso`. + enabled: false + # -- The root URL of the OIDC identity provider + issuer: https://accounts.google.com + clientId: + # -- Name of secret to retrieve the app OIDC client ID + name: argo-server-sso + # -- Key of secret to retrieve the app OIDC client ID + key: client-id + clientSecret: + # -- Name of a secret to retrieve the app OIDC client secret + name: argo-server-sso + # -- Key of a secret to retrieve the app OIDC client secret + key: client-secret + # -- The OIDC redirect URL. Should be in the form /oauth2/callback. + redirectUrl: "" + rbac: + # -- Adds ServiceAccount Policy to server (Cluster)Role. + enabled: true + # -- Whitelist to allow server to fetch Secrets + ## When present, restricts secrets the server can read to a given list. + ## You can use it to restrict the server to only be able to access the + ## service account token secrets that are associated with service accounts + ## used for authorization. + secretWhitelist: [] + # -- Scopes requested from the SSO ID provider + ## The 'groups' scope requests group membership information, which is usually used for authorization decisions. + scopes: [] + # - groups + # -- Define how long your login is valid for (in hours) + ## If omitted, defaults to 10h. + sessionExpiry: "" + # -- Alternate root URLs that can be included for some OIDC providers + issuerAlias: "" + # -- Override claim name for OIDC groups + customGroupClaimName: "" + # -- Specify the user info endpoint that contains the groups claim + ## Configure this if your OIDC provider provides groups information only using the user-info endpoint (e.g. Okta) + userInfoPath: "" + # -- Skip TLS verification for the HTTP client + insecureSkipVerify: false + # -- Filter the groups returned by the OIDC provider + ## A logical "OR" is used between each regex in the list + filterGroupsRegex: [] + # - ".*argo-wf.*" + # - ".*argo-workflow.*" + + # -- Extra containers to be added to the server deployment + extraContainers: [] + + # -- Enables init containers to be added to the server deployment + extraInitContainers: [] + + # -- Specify postStart and preStop lifecycle hooks for server container + lifecycle: {} + + # -- terminationGracePeriodSeconds for container lifecycle hook + terminationGracePeriodSeconds: 30 + +# -- Array of extra K8s manifests to deploy +extraObjects: [] + # - apiVersion: secrets-store.csi.x-k8s.io/v1 + # kind: SecretProviderClass + # metadata: + # name: argo-server-sso + # spec: + # provider: aws + # parameters: + # objects: | + # - objectName: "argo/server/sso" + # objectType: "secretsmanager" + # jmesPath: + # - path: "client_id" + # objectAlias: "client_id" + # - path: "client_secret" + # objectAlias: "client_secret" + # secretObjects: + # - data: + # - key: client_id + # objectName: client_id + # - key: client_secret + # objectName: client_secret + # secretName: argo-server-sso-secrets-store + # type: Opaque + +# -- Use static credentials for S3 (eg. when not using AWS IRSA) +useStaticCredentials: true +artifactRepository: + # -- Archive the main container logs as an artifact + archiveLogs: false + # -- Store artifact in a S3-compliant object store + # @default -- See [values.yaml] + s3: {} + # # Note the `key` attribute is not the actual secret, it's the PATH to + # # the contents in the associated secret, as defined by the `name` attribute. + # accessKeySecret: + # name: "{{ .Release.Name }}-minio" + # key: accesskey + # secretKeySecret: + # name: "{{ .Release.Name }}-minio" + # key: secretkey + # sessionTokenSecret: + # name: "{{ .Release.Name }}-minio" + # key: sessionToken + # # insecure will disable TLS. Primarily used for minio installs not configured with TLS + # insecure: false + # caSecret: + # name: ca-root + # key: cert.pem + # bucket: + # endpoint: + # region: + # roleARN: + # useSDKCreds: true + # encryptionOptions: + # enableEncryption: true + # -- Store artifact in a GCS object store + # @default -- `{}` (See [values.yaml]) + gcs: {} + # bucket: -argo + # keyFormat: "{{ \"{{workflow.namespace}}/{{workflow.name}}/{{pod.name}}\" }}" + # # serviceAccountKeySecret is a secret selector. + # # It references the k8s secret named 'my-gcs-credentials'. + # # This secret is expected to have have the key 'serviceAccountKey', + # # containing the base64 encoded credentials + # # to the bucket. + # # + # # If it's running on GKE and Workload Identity is used, + # # serviceAccountKeySecret is not needed. + # serviceAccountKeySecret: + # name: my-gcs-credentials + # key: serviceAccountKey + # -- Store artifact in Azure Blob Storage + # @default -- `{}` (See [values.yaml]) + azure: {} + # endpoint: https://mystorageaccountname.blob.core.windows.net + # container: my-container-name + # blobNameFormat: path/in/container + # # accountKeySecret is a secret selector. + # # It references the k8s secret named 'my-azure-storage-credentials'. + # # This secret is expected to have have the key 'account-access-key', + # # containing the base64 encoded credentials to the storage account. + # # If a managed identity has been assigned to the machines running the + # # workflow (e.g., https://docs.microsoft.com/en-us/azure/aks/use-managed-identity) + # # then accountKeySecret is not needed, and useSDKCreds should be + # # set to true instead: + # useSDKCreds: true + # accountKeySecret: + # name: my-azure-storage-credentials + # key: account-access-key + +# -- The section of custom artifact repository. +# Utilize a custom artifact repository that is not one of the current base ones (s3, gcs, azure) +customArtifactRepository: {} +# artifactory: +# repoUrl: https://artifactory.example.com/raw +# usernameSecret: +# name: artifactory-creds +# key: username +# passwordSecret: +# name: artifactory-creds +# key: password + +# -- The section of [artifact repository ref](https://argo-workflows.readthedocs.io/en/stable/artifact-repository-ref/). +# Each map key is the name of configmap +# @default -- `{}` (See [values.yaml]) +artifactRepositoryRef: {} + # # -- 1st ConfigMap + # # If you want to use this config map by default, name it "artifact-repositories". + # # Otherwise, you can provide a reference to a + # # different config map in `artifactRepositoryRef.configMap`. + # artifact-repositories: + # # -- v3.0 and after - if you want to use a specific key, put that key into this annotation. + # annotations: + # workflows.argoproj.io/default-artifact-repository: default-v1-s3-artifact-repository + # # 1st data of configmap. See above artifactRepository or customArtifactRepository. + # default-v1-s3-artifact-repository: + # archiveLogs: false + # s3: + # bucket: my-bucket + # endpoint: minio:9000 + # insecure: true + # accessKeySecret: + # name: my-minio-cred + # key: accesskey + # secretKeySecret: + # name: my-minio-cred + # key: secretkey + # # 2nd data + # oss-artifact-repository: + # archiveLogs: false + # oss: + # endpoint: http://oss-cn-zhangjiakou-internal.aliyuncs.com + # bucket: $mybucket + # # accessKeySecret and secretKeySecret are secret selectors. + # # It references the k8s secret named 'bucket-workflow-artifect-credentials'. + # # This secret is expected to have have the keys 'accessKey' + # # and 'secretKey', containing the base64 encoded credentials + # # to the bucket. + # accessKeySecret: + # name: $mybucket-credentials + # key: accessKey + # secretKeySecret: + # name: $mybucket-credentials + # key: secretKey + # # 2nd ConfigMap + # another-artifact-repositories: + # annotations: + # workflows.argoproj.io/default-artifact-repository: gcs + # gcs: + # bucket: my-bucket + # keyFormat: prefix/in/bucket/{{workflow.name}}/{{pod.name}} + # serviceAccountKeySecret: + # name: my-gcs-credentials + # key: serviceAccountKey + +emissary: + # -- The command/args for each image on workflow, needed when the command is not specified and the emissary executor is used. + ## See more: https://argo-workflows.readthedocs.io/en/stable/workflow-executors/#emissary-emissary + images: [] + # argoproj/argosay:v2: + # cmd: [/argosay] + # docker/whalesay:latest: + # cmd: [/bin/bash] diff --git a/utils/assets/charts/docker-registry-ui/.helmignore b/utils/assets/charts/docker-registry-ui/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/docker-registry-ui/Chart.yaml b/utils/assets/charts/docker-registry-ui/Chart.yaml new file mode 100644 index 0000000..1f463ef --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/Chart.yaml @@ -0,0 +1,30 @@ +annotations: + artifacthub.io/images: | + - name: docker-registry-ui + image: joxit/docker-registry-ui:2.5.2 + - name: registry + image: registry:2.8.2 + artifacthub.io/license: MIT + artifacthub.io/links: | + - name: Documentation + url: https://joxit.dev/docker-registry-ui + - name: Joxit/docker-registry-ui + url: https://github.com/Joxit/docker-registry-ui + - name: Joxit/helm-charts + url: https://github.com/Joxit/helm-charts + artifacthub.io/prerelease: "false" +apiVersion: v2 +appVersion: 2.5.2 +description: The simplest and most complete UI for your private registry +home: https://github.com/Joxit/docker-registry-ui +keywords: +- docker +- registry +- user-interface +- interface +kubeVersion: '>=1.19.0-0' +name: docker-registry-ui +sources: +- https://github.com/Joxit/docker-registry-ui +- https://github.com/Joxit/helm-charts +version: 1.1.3 diff --git a/utils/assets/charts/docker-registry-ui/README.md b/utils/assets/charts/docker-registry-ui/README.md new file mode 100644 index 0000000..a67cf52 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/README.md @@ -0,0 +1,140 @@ +# Docker Registry UI Chart + +[![Stars](https://img.shields.io/github/stars/joxit/docker-registry-ui.svg?logo=github&maxAge=86400)](https://github.com/Joxit/docker-registry-ui/stargazers) +[![Pulls](https://img.shields.io/docker/pulls/joxit/docker-registry-ui.svg?maxAge=86400)](https://hub.docker.com/r/joxit/docker-registry-ui) +[![Sponsor](https://joxit.dev/images/sponsor.svg)](https://github.com/sponsors/Joxit) +[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/joxit)](https://artifacthub.io/packages/helm/joxit/docker-registry-ui) + +## Overview + +This project aims to provide a simple and complete user interface for your private docker registry. You can customize the interface with various options. The major option is `ui.singleRegistry` which allows you to disable the dynamic selection of docker registeries. + +If you like my work and want to support it, don't hesitate to [sponsor me](https://github.com/sponsors/Joxit). + +## [Project Page](https://joxit.dev/docker-registry-ui), [Live Demo](https://joxit.dev/docker-registry-ui/demo/), [Examples](https://github.com/Joxit/docker-registry-ui/tree/main/examples), [Helm Chart](https://helm.joxit.dev/charts/docker-registry-ui/) + +![preview](https://raw.github.com/Joxit/docker-registry-ui/main/docker-registry-ui.gif "Preview of Docker Registry UI") + +## Prerequisites + + * **Helm 3.2+** (Helm 2 is not supported) + * **Kubernetes 1.19+** - This is the earliest version of Kubernetes tested. + It is possible that this chart works with earlier versions but it is untested. + +## Usage + +1. Add my Helm repository (named `joxit`) +``` +helm repo add joxit https://helm.joxit.dev +``` +2. Ensure you have access to the Helm chart and you see the latest chart version listed. If you have previously added the Helm repository, run `helm repo update`. +``` +helm search repo joxit/docker-registry-ui +``` +3. Now you're ready to install the Docker Registry UI! To install Docker Registry UI with the default configuration using Helm 3.2 run the following command below. This will deploy the Docker Registry UI on the default namespace. +``` +helm upgrade --install docker-registry-ui joxit/docker-registry-ui +``` + +## Configuration + +### Global + +| Value | Default | Description | +| --- | --- | --- | +| `global.name` | `null` | Set the prefix used for all resources in the Helm chart. If not set, the prefix will be ``. | +| `global.imagePullSecrets` | `[]` | The default array of objects containing image pull secret names that will be applied. | +| `global.imagePullPolicy` | `IfNotPresent` | The default image policy for images: `IfNotPresent`, `Always`, `Never` | + +### User Interface + +| Value | Default | Description | +| --- | --- | --- | +| `ui.replicas` | `1` | Number of replicas for the Deployment. | +| `ui.title` | `"Docker registry UI"` | Title of the registry | +| `ui.proxy` | `false` | UI behave as a proxy of the registry | +| `ui.dockerRegistryUrl` | `null` | The URL of your docker registry, may be a service (when proxy is on) or an external URL. | +| `ui.pullUrl` | `null` | Override the pull URL | +| `ui.singleRegistry` | `true` | Remove the menu that show the dialogs to add, remove and change the endpoint of your docker registry. | +| `ui.registrySecured` | `false` | By default, the UI will check on every requests if your registry is secured or not (you will see `401` responses in your console). Set to `true` if your registry uses Basic Authentication and divide by two the number of call to your registry. | +| `ui.showCatalogNbTags` | `false` | Show number of tags per images on catalog page. This will produce + nb images requests, not recommended on large registries. | +| `ui.catalogElementsLimit` | `1000` | Limit the number of elements in the catalog page. | +| `ui.catalogDefaultExpanded` | `false` | Expand by default all repositories in catalog | +| `ui.catalogMinBranches` | `1` | Set the minimum repository/namespace to expand (e.g. `joxit/docker-registry-ui` `joxit/` is the repository/namespace). Can be 0 to disable branching. | +| `ui.catalogMaxBranches` | `1` | Set the maximum repository/namespace to expand (e.g. `joxit/docker-registry-ui` `joxit/` is the repository/namespace). Can be 0 to disable branching. | +| `ui.deleteImages` | `false` | Allow delete of images | +| `ui.showContentDigest` | `false` | Show content digest in docker tag list. | +| `ui.taglistOrder` | `alpha-asc;num-desc` | Set the default order for the taglist page, could be `num-asc;alpha-asc`, `num-desc;alpha-asc`, `num-asc;alpha-desc`, `num-desc;alpha-desc`, `alpha-asc;num-asc`, `alpha-asc;num-desc`, `alpha-desc;num-asc` or `alpha-desc;num-desc`. | +| `ui.taglistPageSize` | `100` | Set the number of tags to display in one page. | +| `ui.historyCustomLabels` | `[]` | Expose custom labels in history page, custom labels will be processed like maintainer label. | +| `ui.nginxProxyHeaders` | `[]` | Update the default Nginx configuration and **set custom headers** for your backend docker registry. Only when `ui.proxy` is used. Example: nginxProxyHeaders: [ { my-heeader-name: my-header-value } ] | +| `ui.nginxProxyPassHeaders` | `[]` | Update the default Nginx configuration and **forward custom headers** to your backend docker registry. Only when `ui.proxy` is used. Example: nginxProxyPassHeaders: [ my-first-header, my-second-header ] | +| `ui.useControlCacheHeader` | `false` | Add header Control-Cache: no-store, no-cache on requests to registry server. This needs to update your registry configuration with : `Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']` | +| `ui.runAsRoot` | `true` | Use root or nginx user inside the container, when this is false the target port must be greater or equal to 1024. | +| `ui.defaultTheme` | `"auto"` | Select the default theme to apply, values can be `auto`, `dark` and `light` | +| `ui.theme.background` | `""` | Custom background color for the UI | +| `ui.theme.primaryText` | `""` | Custom primary text color for the UI | +| `ui.theme.neutralText` | `""` | Custom netral color for the UI (icons) | +| `ui.theme.accentText` | `""` | Custom accent color for the UI (buttons) | +| `ui.theme.hoverBackground` | `""` | Custom hover background color for the UI | +| `ui.theme.headerBackground` | `""` | Custom header background color for the UI | +| `ui.theme.headerText` | `""` | Custom header text color for the UI | +| `ui.theme.footerBackground` | `""` | Custom footer background color for the UI | +| `ui.theme.footerText` | `""` | Custom footer text color for the UI | +| `ui.theme.footerNeutralText` | `""` | Custom footer neutral color for the UI (links) | +| `ui.image` | `joxit/docker-registry-ui:2.5.2` | The name and tag of the docker image of the interface | +| `ui.imagePullSecrets` | `"-"` | Override default image pull secrets | +| `ui.imagePullPolicy` | `"-"` | Override default pull policy | +| `ui.resources` | `{}` | The resource settings for user interface pod. | +| `ui.nodeSelector` | `{}` | Optional YAML string to specify a nodeSelector config. | +| `ui.tolerations` | `[]` | Optional YAML string to specify tolerations. | +| `ui.affinity` | `{}` | This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) for server pods. | +| `ui.annotations` | `{}` | Annotations to apply to the user interface deployment. | +| `ui.additionalSpec` | `{}` | Optional YAML string that will be appended to the deployment spec. | +| `ui.service.type` | `ClusterIP` | Type of service: `LoadBalancer`, `ClusterIP` or `NodePort`. If using `NodePort` service type, you must set the desired `nodePorts` setting below. | +| `ui.service.port` | `80` | Ports that will be exposed on the service | +| `ui.service.targetPort` | `80` | The port to listhen on the container. If under 1024, the user must be root | +| `ui.service.nodePort` | `null` | If using a `NodePort` service type, you must specify the desired `nodePort` for each exposed port. | +| `ui.service.annotations` | `{}` | Annotations to apply to the user interface service. | +| `ui.service.additionalSpec` | `{}` | Optional YAML string that will be appended to the Service spec. | +| `ui.ingress.enabled` | `false` | Enable the ingress for the user interface. | +| `ui.ingress.host` | `null` | Fully qualified domain name of a network host. | +| `ui.ingress.path` | `/` | Path is matched against the path of an incoming request. | +| `ui.ingress.pathType` | `Prefix` | Determines the interpretation of the Path matching, must be Prefix to serve assets. | +| `ui.ingress.ingressClassName` | `nginx` | The name of an IngressClass cluster resource. | +| `ui.ingress.tls` | `[]` | TLS configuration | +| `ui.ingress.annotations` | `{}` | Annotations to apply to the user interface ingress. | + +### Registry Server + +| Value | Default | Description | +| --- | --- | --- | +| `registry.enabled` | `false` | Enable the registry server. | +| `registry.image` | `registry:2.8.2` | The name and tag of the docker registry server image | +| `registry.imagePullSecrets` | `"-"` | Override default image pull secrets | +| `registry.imagePullPolicy` | `"-"` | Override default pull policy | +| `registry.dataVolume` | `null` | Configuration for the data directory. When null it will create an emptyDir. | +| `registry.resources` | `{}` | The resource settings for registry server pod. | +| `registry.nodeSelector` | `{}` | Optional YAML string to specify a nodeSelector config. | +| `registry.tolerations` | `[]` | Optional YAML string to specify tolerations. | +| `registry.affinity` | `{}` | This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) for server pods. | +| `registry.annotations` | `{}` | Annotations to apply to the registry server deployment. | +| `registry.additionalSpec` | `{}` | Optional YAML string that will be appended to the deployment spec. | +| `registry.extraEnv` | `[]` | Extra Environmental Variables for Registry | +| `registry.auth.basic.enabled` | `false` | Enable basic auth for Registry. | +| `registry.auth.basic.realm` | `Docker registry` | Basic auth realm. | +| `registry.auth.basic.htpasswdPath` | `/etc/docker/registry/auth/htpasswd` | Full path for htpasswd file. Note that filename should match the secret key. | +| `registry.auth.basic.secretName` | `''` | htpasswd secret name volume to mount. | +| `registry.service.type` | `ClusterIP` | Type of service: `LoadBalancer`, `ClusterIP` or `NodePort`. If using `NodePort` service type, you must set the desired `nodePorts` setting below. | +| `registry.service.port` | `5000` | Ports that will be exposed on the service | +| `registry.service.targetPort` | `5000` | The port to listhen on the container. | +| `registry.service.nodePort` | `null` | If using a `NodePort` service type, you must specify the desired `nodePort` for each exposed port. | +| `registry.service.annotations` | `{}` | Annotations to apply to the registry server service. | +| `registry.service.additionalSpec` | `{}` | Optional YAML string that will be appended to the Service spec. | +| `registry.ingress.enabled` | `false` | Enable the ingress for the registry server. | +| `registry.ingress.host` | `null` | Fully qualified domain name of a network host. | +| `registry.ingress.path` | `/v2/` | Path is matched against the path of an incoming request. | +| `registry.ingress.pathType` | `Prefix` | Determines the interpretation of the Path matching, must be Prefix to serve assets. | +| `registry.ingress.ingressClassName` | `nginx` | The name of an IngressClass cluster resource. | +| `registry.ingress.tls` | `[]` | TLS configuration | +| `registry.ingress.annotations` | `{}` | Annotations to apply to the registry server ingress. | diff --git a/utils/assets/charts/docker-registry-ui/README.tmpl b/utils/assets/charts/docker-registry-ui/README.tmpl new file mode 100644 index 0000000..e2c1cd1 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/README.tmpl @@ -0,0 +1,28 @@ +# {{ prettyName }} Chart + +[![Stars](https://img.shields.io/github/stars/joxit/docker-registry-ui.svg?logo=github&maxAge=86400)](https://github.com/Joxit/docker-registry-ui/stargazers) +[![Pulls](https://img.shields.io/docker/pulls/joxit/docker-registry-ui.svg?maxAge=86400)](https://hub.docker.com/r/joxit/docker-registry-ui) +[![Sponsor](https://joxit.dev/images/sponsor.svg)](https://github.com/sponsors/Joxit) +[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/joxit)](https://artifacthub.io/packages/helm/joxit/docker-registry-ui) + +## Overview + +This project aims to provide a simple and complete user interface for your private docker registry. You can customize the interface with various options. The major option is `ui.singleRegistry` which allows you to disable the dynamic selection of docker registeries. + +If you like my work and want to support it, don't hesitate to [sponsor me](https://github.com/sponsors/Joxit). + +## [Project Page](https://joxit.dev/docker-registry-ui), [Live Demo](https://joxit.dev/docker-registry-ui/demo/), [Examples](https://github.com/Joxit/docker-registry-ui/tree/main/examples), [Helm Chart](https://helm.joxit.dev/charts/docker-registry-ui/) + +![preview](https://raw.github.com/Joxit/docker-registry-ui/main/docker-registry-ui.gif "Preview of Docker Registry UI") + +## Prerequisites + +{{ prerequisites }} + +## Usage + +{{ usage }} + +## Configuration + +{{ configuration }} diff --git a/utils/assets/charts/docker-registry-ui/templates/NOTES.txt b/utils/assets/charts/docker-registry-ui/templates/NOTES.txt new file mode 100644 index 0000000..9b179e3 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/NOTES.txt @@ -0,0 +1,8 @@ +Thank you for installing Joxit's Docker Registry UI! + +Your release is named {{ .Release.Name }}. + +To learn more about the release, run: + + $ helm status {{ .Release.Name }} {{- if .Release.Namespace }} --namespace {{ .Release.Namespace }}{{ end }} + $ helm get all {{ .Release.Name }} {{- if .Release.Namespace }} --namespace {{ .Release.Namespace }}{{ end }} diff --git a/utils/assets/charts/docker-registry-ui/templates/_helpers.tpl b/utils/assets/charts/docker-registry-ui/templates/_helpers.tpl new file mode 100644 index 0000000..4fd7015 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/_helpers.tpl @@ -0,0 +1,43 @@ +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to +this (by the DNS naming spec). Supports the legacy fullnameOverride setting +as well as the global.name setting. +*/}} +{{- define "docker-registry-ui.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else if .Values.global.name -}} +{{- .Values.global.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "docker-registry-ui.chart" -}} +{{- printf "%s-helm" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "docker-registry-ui.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels. +*/}} +{{- define "docker-registry-ui.labels" -}} +app.kubernetes.io/name: {{ include "docker-registry-ui.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ include "docker-registry-ui.chart" . }} +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/docker-registry-ui/templates/registry-deployment.yaml b/utils/assets/charts/docker-registry-ui/templates/registry-deployment.yaml new file mode 100644 index 0000000..9f1f723 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/registry-deployment.yaml @@ -0,0 +1,101 @@ +{{- if .Values.registry.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "docker-registry-ui.fullname" . }}-registry-server + labels: + app.kubernetes.io/component : registry-server + {{- include "docker-registry-ui.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.registry.replicas }} + selector: + matchLabels: + app.kubernetes.io/component : registry-server + {{- include "docker-registry-ui.labels" . | nindent 6 }} + template: + metadata: + labels: + app.kubernetes.io/component : registry-server + {{- include "docker-registry-ui.labels" . | nindent 8 }} + {{- if .Values.registry.annotations }} + annotations: + {{- toYaml .Values.registry.annotations | nindent 8 }} + {{- end }} + spec: + {{- if ne (.Values.registry.imagePullSecrets | toString) "-" }} + imagePullSecrets: + {{- toYaml .Values.registry.imagePullSecrets | nindent 8 }} + {{- else }} + imagePullSecrets: + {{- toYaml .Values.global.imagePullSecrets | nindent 8 }} + {{- end}} + containers: + - name: "registry-server" + image: {{ .Values.registry.image | quote }} + imagePullPolicy: {{ if ne (.Values.registry.imagePullPolicy | toString) "-" }}{{ .Values.registry.imagePullPolicy }}{{ else }}{{ .Values.global.imagePullPolicy }}{{ end }} + env: + - name: REGISTRY_HTTP_ADDR + value: {{ printf "%s:%d" "0.0.0.0" (.Values.registry.service.targetPort | int) }} + {{- if .Values.ui.deleteImages }} + - name: REGISTRY_STORAGE_DELETE_ENABLED + value: 'true' + {{- end }} + {{- if .Values.registry.auth.basic.enabled }} + - name: REGISTRY_AUTH + value: htpasswd + - name: REGISTRY_AUTH_HTPASSWD_REALM + value: {{ if ne (.Values.registry.auth.basic.realm | toString) "-" }}{{ .Values.registry.auth.basic.realm }}{{ else }}{{ "Docker registry" }}{{ end }} + - name: REGISTRY_AUTH_HTPASSWD_PATH + value: {{ if ne (.Values.registry.auth.basic.htpasswdPath | toString) "-" }}{{ .Values.registry.auth.basic.htpasswdPath }}{{ else }}{{ "/etc/docker/registry/auth/htpasswd" }}{{ end }} + {{- end }} + {{- range .Values.registry.extraEnv }} + - name: {{ .name | quote }} + value: {{ .value | quote }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.registry.service.targetPort }} + protocol: TCP + volumeMounts: + - mountPath: /var/lib/registry + name: data + {{- if .Values.registry.auth.basic.enabled }} + - name: htpasswd + mountPath: {{ if ne (.Values.registry.auth.basic.htpasswdPath | toString) "-" }}{{ dir .Values.registry.auth.basic.htpasswdPath }}{{ else }}{{ "/etc/docker/registry/auth" }}{{ end }} + readOnly: true + {{- end }} + resources: + {{- toYaml .Values.registry.resources | nindent 12 }} + volumes: + - name: data + {{- if .Values.registry.dataVolume }} + {{- toYaml .Values.registry.dataVolume | nindent 10 }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.registry.auth.basic.enabled }} + - name: htpasswd + secret: + secretName: {{ if .Values.registry.auth.basic.secretName }}{{ .Values.registry.auth.basic.secretName }}{{ else }}{{ fail "Basic auth secret name is required" }}{{ end }} + {{- end }} + {{- with .Values.registry.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.registry.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.registry.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.registry.runAsRoot }} + securityContext: + runAsUser: 101 + fsGroup: 101 + {{- end }} + {{- if .Values.registry.additionalSpec }} + {{ tpl .Values.registry.additionalSpec . | nindent 6 | trim }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/docker-registry-ui/templates/registry-ingress.yaml b/utils/assets/charts/docker-registry-ui/templates/registry-ingress.yaml new file mode 100644 index 0000000..9d55024 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/registry-ingress.yaml @@ -0,0 +1,38 @@ +{{- if .Values.registry.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "docker-registry-ui.fullname" . }}-registry-server + labels: + app.kubernetes.io/component : registry-server + {{- include "docker-registry-ui.labels" . | nindent 4 }} + {{- with .Values.registry.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.registry.ingress.ingressClassName }} + ingressClassName: {{ .Values.registry.ingress.ingressClassName }} + {{- end -}} +{{- if .Values.registry.ingress.tls }} + tls: +{{ tpl (toYaml .Values.registry.ingress.tls) $ | indent 4 }} +{{- end }} + rules: + - http: + paths: + - backend: + service: + name: {{ include "docker-registry-ui.fullname" . }}-registry-server + port: + number: {{ .Values.registry.service.port }} + {{- if .Values.registry.ingress.path }} + path: {{ .Values.registry.ingress.path }} + {{- end }} + {{- if .Values.registry.ingress.pathType }} + pathType: {{ .Values.registry.ingress.pathType }} + {{- end }} + {{- if .Values.registry.ingress.host }} + host: {{ .Values.registry.ingress.host | quote }} + {{- end -}} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/docker-registry-ui/templates/registry-service.yaml b/utils/assets/charts/docker-registry-ui/templates/registry-service.yaml new file mode 100644 index 0000000..5da1526 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/registry-service.yaml @@ -0,0 +1,29 @@ +{{- if .Values.registry.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "docker-registry-ui.fullname" . }}-registry-server + labels: + app.kubernetes.io/component : registry-server + {{- include "docker-registry-ui.labels" . | nindent 4 }} + {{- with .Values.registry.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + app.kubernetes.io/component : registry-server + {{- include "docker-registry-ui.labels" . | nindent 4 }} + type: {{ .Values.registry.service.type }} + ports: + - port: {{ .Values.registry.service.port }} + targetPort: {{ .Values.registry.service.targetPort }} + protocol: TCP + name: http + {{- if (and (eq .Values.registry.service.type "NodePort") .Values.registry.service.nodePort) }} + nodePort: {{ .Values.registry.service.nodePort }} + {{- end }} + {{- if .Values.registry.service.additionalSpec }} + {{ tpl .Values.registry.service.additionalSpec . | nindent 2 | trim }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/docker-registry-ui/templates/ui-deployment.yaml b/utils/assets/charts/docker-registry-ui/templates/ui-deployment.yaml new file mode 100644 index 0000000..43026e5 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/ui-deployment.yaml @@ -0,0 +1,139 @@ +{{- if and (not .Values.ui.runAsRoot) (lt (.Values.ui.service.targetPort | int) 1024) }} +{{ fail "When `ui.runAsRoot` is false `ui.service.targetPort` must be less than 1024." }} +{{- end }} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "docker-registry-ui.fullname" . }}-user-interface + labels: + app.kubernetes.io/component : user-interface + {{- include "docker-registry-ui.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.ui.replicas }} + selector: + matchLabels: + app.kubernetes.io/component : user-interface + {{- include "docker-registry-ui.labels" . | nindent 6 }} + template: + metadata: + labels: + app.kubernetes.io/component : user-interface + {{- include "docker-registry-ui.labels" . | nindent 8 }} + {{- if .Values.ui.annotations }} + annotations: + {{- toYaml .Values.ui.annotations | nindent 8 }} + {{- end }} + spec: + {{- if ne (.Values.ui.imagePullSecrets | toString) "-" }} + imagePullSecrets: + {{- toYaml .Values.ui.imagePullSecrets | nindent 8 }} + {{- else }} + imagePullSecrets: + {{- toYaml .Values.global.imagePullSecrets | nindent 8 }} + {{- end}} + containers: + - name: "registry-ui" + image: {{ .Values.ui.image | quote }} + imagePullPolicy: {{ if ne (.Values.ui.imagePullPolicy | toString) "-" }}{{ .Values.ui.imagePullPolicy }}{{ else }}{{ .Values.global.imagePullPolicy }}{{ end }} + env: + - name: REGISTRY_TITLE + value: {{ .Values.ui.title | quote }} + - name: DELETE_IMAGES + value: {{ .Values.ui.deleteImages | quote }} + {{- if .Values.ui.proxy }} + {{- if .Values.ui.dockerRegistryUrl }} + - name: NGINX_PROXY_PASS_URL + value: {{ .Values.ui.dockerRegistryUrl | quote }} + {{- else if .Values.registry.enabled }} + - name: NGINX_PROXY_PASS_URL + value: {{ printf "http://%s-registry-server:%d" (include "docker-registry-ui.fullname" .) (.Values.registry.service.port | int) }} + {{- end }} + {{- range $header := .Values.ui.nginxProxyHeaders }} + {{- range $key, $value := $header }} + - name: {{ printf "NGINX_PROXY_HEADER_%s" $key }} + value: {{ $value }} + {{- end }} + {{- end }} + {{- range $header := .Values.ui.nginxProxyPassHeaders }} + - name: {{ printf "NGINX_PROXY_PASS_HEADER_%s" $header }} + {{- end }} + {{- else }} + - name: REGISTRY_URL + value: {{ .Values.ui.dockerRegistryUrl | quote }} + {{- end }} + - name: PULL_URL + value: {{ .Values.ui.pullUrl | quote }} + - name: SHOW_CATALOG_NB_TAGS + value: {{ .Values.ui.showCatalogNbTags | quote }} + - name: SHOW_CONTENT_DIGEST + value: {{ .Values.ui.showContentDigest | quote }} + - name: SINGLE_REGISTRY + value: {{ .Values.ui.singleRegistry | quote }} + - name: CATALOG_ELEMENTS_LIMIT + value: {{ .Values.ui.catalogElementsLimit | quote }} + - name: HISTORY_CUSTOM_LABELS + value: {{ .Values.ui.historyCustomLabels | join "," }} + - name: NGINX_LISTEN_PORT + value: {{ .Values.ui.service.targetPort | quote }} + - name: USE_CONTROL_CACHE_HEADER + value: {{ .Values.ui.useControlCacheHeader | quote }} + - name: TAGLIST_ORDER + value: {{ .Values.ui.taglistOrder | quote }} + - name: CATALOG_DEFAULT_EXPANDED + value: {{ .Values.ui.catalogDefaultExpanded | quote }} + - name: CATALOG_MIN_BRANCHES + value: {{ .Values.ui.catalogMinBranches | quote }} + - name: CATALOG_MAX_BRANCHES + value: {{ .Values.ui.catalogMaxBranches | quote }} + - name: TAGLIST_PAGE_SIZE + value: {{ .Values.ui.taglistPageSize | quote }} + - name: REGISTRY_SECURED + value: {{ .Values.ui.registrySecured | quote }} + - name: THEME + value: {{ .Values.ui.defaultTheme | quote }} + - name: THEME_PRIMARY_TEXT + value: {{ .Values.ui.theme.primaryText | quote }} + - name: THEME_NEUTRAL_TEXT + value: {{ .Values.ui.theme.neutralText | quote }} + - name: THEME_BACKGROUND + value: {{ .Values.ui.theme.background | quote }} + - name: THEME_HOVER_BACKGROUND + value: {{ .Values.ui.theme.hoverBackground | quote }} + - name: THEME_ACCENT_TEXT + value: {{ .Values.ui.theme.accentText | quote }} + - name: THEME_HEADER_TEXT + value: {{ .Values.ui.theme.headerText | quote }} + - name: THEME_HEADER_BACKGROUND + value: {{ .Values.ui.theme.headerBackground | quote }} + - name: THEME_FOOTER_TEXT + value: {{ .Values.ui.theme.footerText | quote }} + - name: THEME_FOOTER_NEUTRAL_TEXT + value: {{ .Values.ui.theme.footerNeutralText | quote }} + - name: THEME_FOOTER_BACKGROUND + value: {{ .Values.ui.theme.footerBackground | quote }} + ports: + - name: http + containerPort: {{ .Values.ui.service.targetPort }} + protocol: TCP + resources: + {{- toYaml .Values.ui.resources | nindent 12 }} + {{- with .Values.ui.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ui.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ui.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.ui.runAsRoot }} + securityContext: + runAsUser: 101 + {{- end }} + {{- if .Values.ui.additionalSpec }} + {{ tpl .Values.ui.additionalSpec . | nindent 6 | trim }} + {{- end }} diff --git a/utils/assets/charts/docker-registry-ui/templates/ui-ingress.yaml b/utils/assets/charts/docker-registry-ui/templates/ui-ingress.yaml new file mode 100644 index 0000000..ac07f91 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/ui-ingress.yaml @@ -0,0 +1,38 @@ +{{- if .Values.ui.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "docker-registry-ui.fullname" . }}-user-interface + labels: + app.kubernetes.io/component : user-interface + {{- include "docker-registry-ui.labels" . | nindent 4 }} + {{- with .Values.ui.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ui.ingress.ingressClassName }} + ingressClassName: {{ .Values.ui.ingress.ingressClassName }} + {{- end -}} +{{- if .Values.ui.ingress.tls }} + tls: +{{ tpl (toYaml .Values.ui.ingress.tls) $ | indent 4 }} +{{- end }} + rules: + - http: + paths: + - backend: + service: + name: {{ include "docker-registry-ui.fullname" . }}-user-interface + port: + number: {{ .Values.ui.service.port }} + {{- if .Values.ui.ingress.path }} + path: {{ .Values.ui.ingress.path }} + {{- end }} + {{- if .Values.ui.ingress.pathType }} + pathType: {{ .Values.ui.ingress.pathType }} + {{- end }} + {{- if .Values.ui.ingress.host }} + host: {{ .Values.ui.ingress.host | quote }} + {{- end -}} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/docker-registry-ui/templates/ui-service.yaml b/utils/assets/charts/docker-registry-ui/templates/ui-service.yaml new file mode 100644 index 0000000..7031903 --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/templates/ui-service.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "docker-registry-ui.fullname" . }}-user-interface + labels: + app.kubernetes.io/component : user-interface + {{- include "docker-registry-ui.labels" . | nindent 4 }} + {{- with .Values.ui.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + app.kubernetes.io/component : user-interface + {{- include "docker-registry-ui.labels" . | nindent 4 }} + type: {{ .Values.ui.service.type }} + ports: + - port: {{ .Values.ui.service.port }} + targetPort: {{ .Values.ui.service.targetPort }} + protocol: TCP + name: http + {{- if (and (eq .Values.ui.service.type "NodePort") .Values.ui.service.nodePort) }} + nodePort: {{ .Values.ui.service.nodePort }} + {{- end }} + {{- if .Values.ui.service.additionalSpec }} + {{ tpl .Values.ui.service.additionalSpec . | nindent 2 | trim }} + {{- end }} diff --git a/utils/assets/charts/docker-registry-ui/values.yaml b/utils/assets/charts/docker-registry-ui/values.yaml new file mode 100644 index 0000000..1a0805c --- /dev/null +++ b/utils/assets/charts/docker-registry-ui/values.yaml @@ -0,0 +1,218 @@ +## Global +global: + # Set the prefix used for all resources in the Helm chart. If not set, + # the prefix will be ``. + name: null + # The default array of objects containing image pull secret names that will be applied. + imagePullSecrets: [] + # The default image policy for images: `IfNotPresent`, `Always`, `Never` + imagePullPolicy: IfNotPresent + +## User Interface +ui: + # Number of replicas for the Deployment. + replicas: 1 + # Title of the registry + title: "Docker registry UI" + # UI behave as a proxy of the registry + proxy: false + # The URL of your docker registry, may be a service (when proxy is on) or an external URL. + dockerRegistryUrl: null + # Override the pull URL + pullUrl: null + # Remove the menu that show the dialogs to add, remove and change the endpoint of your docker registry. + singleRegistry: true + # By default, the UI will check on every requests if your registry is secured or not (you will see `401` responses in your console). Set to `true` if your registry uses Basic Authentication and divide by two the number of call to your registry. + registrySecured: false + + # Show number of tags per images on catalog page. This will produce + nb images requests, not recommended on large registries. + showCatalogNbTags: false + # Limit the number of elements in the catalog page. + catalogElementsLimit: 1000 + # Expand by default all repositories in catalog + catalogDefaultExpanded: false + # Set the minimum repository/namespace to expand (e.g. `joxit/docker-registry-ui` `joxit/` is the repository/namespace). Can be 0 to disable branching. + catalogMinBranches: 1 + # Set the maximum repository/namespace to expand (e.g. `joxit/docker-registry-ui` `joxit/` is the repository/namespace). Can be 0 to disable branching. + catalogMaxBranches: 1 + + # Allow delete of images + deleteImages: false + # Show content digest in docker tag list. + showContentDigest: false + # Set the default order for the taglist page, could be `num-asc;alpha-asc`, `num-desc;alpha-asc`, `num-asc;alpha-desc`, `num-desc;alpha-desc`, `alpha-asc;num-asc`, `alpha-asc;num-desc`, `alpha-desc;num-asc` or `alpha-desc;num-desc`. + taglistOrder: alpha-asc;num-desc + # Set the number of tags to display in one page. + taglistPageSize: 100 + + # Expose custom labels in history page, custom labels will be processed like maintainer label. + historyCustomLabels: [] + + # Update the default Nginx configuration and **set custom headers** for your backend docker registry. Only when `ui.proxy` is used. + # Example: + # nginxProxyHeaders: + # [ { my-heeader-name: my-header-value } ] + nginxProxyHeaders: [] + # Update the default Nginx configuration and **forward custom headers** to your backend docker registry. Only when `ui.proxy` is used. + # Example: + # nginxProxyPassHeaders: [ my-first-header, my-second-header ] + nginxProxyPassHeaders: [] + # Add header Control-Cache: no-store, no-cache on requests to registry server. + # This needs to update your registry configuration with : `Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']` + useControlCacheHeader: false + # Use root or nginx user inside the container, when this is false the target port must be greater or equal to 1024. + runAsRoot: true + + # Select the default theme to apply, values can be `auto`, `dark` and `light` + defaultTheme: "auto" + + theme: + # Custom background color for the UI + background: "" + # Custom primary text color for the UI + primaryText: "" + # Custom netral color for the UI (icons) + neutralText: "" + # Custom accent color for the UI (buttons) + accentText: "" + # Custom hover background color for the UI + hoverBackground: "" + # Custom header background color for the UI + headerBackground: "" + # Custom header text color for the UI + headerText: "" + # Custom footer background color for the UI + footerBackground: "" + # Custom footer text color for the UI + footerText: "" + # Custom footer neutral color for the UI (links) + footerNeutralText: "" + + # The name and tag of the docker image of the interface + image: joxit/docker-registry-ui:2.5.2 + # Override default image pull secrets + imagePullSecrets: "-" + # Override default pull policy + imagePullPolicy: "-" + # The resource settings for user interface pod. + resources: {} + # Optional YAML string to specify a nodeSelector config. + nodeSelector: {} + # Optional YAML string to specify tolerations. + tolerations: [] + # This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) + # for server pods. + affinity: {} + # Annotations to apply to the user interface deployment. + annotations: {} + # Optional YAML string that will be appended to the deployment spec. + additionalSpec: {} + + service: + # Type of service: `LoadBalancer`, `ClusterIP` or `NodePort`. If using `NodePort` service + # type, you must set the desired `nodePorts` setting below. + type: ClusterIP + # Ports that will be exposed on the service + port: 80 + # The port to listhen on the container. If under 1024, the user must be root + targetPort: 80 + # If using a `NodePort` service type, you must specify the desired `nodePort` for each exposed port. + nodePort: null + # Annotations to apply to the user interface service. + annotations: {} + # Optional YAML string that will be appended to the Service spec. + additionalSpec: {} + + ingress: + # Enable the ingress for the user interface. + enabled: false + # Fully qualified domain name of a network host. + host: null + # Path is matched against the path of an incoming request. + path: / + # Determines the interpretation of the Path matching, must be Prefix to serve assets. + pathType: Prefix + # The name of an IngressClass cluster resource. + ingressClassName: nginx + # TLS configuration + tls: [] + # Annotations to apply to the user interface ingress. + annotations: {} + # If you want a custom path, you can try this example: + # path: /ui(/|$)(.*) + # annotations: + # { nginx.ingress.kubernetes.io/rewrite-target: /$2 } + +## Registry Server +registry: + # Enable the registry server. + enabled: false + # The name and tag of the docker registry server image + image: registry:2.8.2 + # Override default image pull secrets + imagePullSecrets: "-" + # Override default pull policy + imagePullPolicy: "-" + # Configuration for the data directory. When null it will create an emptyDir. + dataVolume: null + # The resource settings for registry server pod. + resources: {} + # Optional YAML string to specify a nodeSelector config. + nodeSelector: {} + # Optional YAML string to specify tolerations. + tolerations: [] + # This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) + # for server pods. + affinity: {} + # Annotations to apply to the registry server deployment. + annotations: {} + # Optional YAML string that will be appended to the deployment spec. + additionalSpec: {} + # Extra Environmental Variables for Registry + extraEnv: [] + + auth: + basic: + # Enable basic auth for Registry. + enabled: false + # Basic auth realm. + realm: Docker registry + # Full path for htpasswd file. Note that filename should match the secret key. + htpasswdPath: /etc/docker/registry/auth/htpasswd + # htpasswd secret name volume to mount. + secretName: '' + + service: + # Type of service: `LoadBalancer`, `ClusterIP` or `NodePort`. If using `NodePort` service + # type, you must set the desired `nodePorts` setting below. + type: ClusterIP + # Ports that will be exposed on the service + port: 5000 + # The port to listhen on the container. + targetPort: 5000 + # If using a `NodePort` service type, you must specify the desired `nodePort` for each exposed port. + nodePort: null + # Annotations to apply to the registry server service. + annotations: {} + # Optional YAML string that will be appended to the Service spec. + additionalSpec: {} + + ingress: + # Enable the ingress for the registry server. + enabled: false + # Fully qualified domain name of a network host. + host: null + # Path is matched against the path of an incoming request. + path: /v2/ + # Determines the interpretation of the Path matching, must be Prefix to serve assets. + pathType: Prefix + # The name of an IngressClass cluster resource. + ingressClassName: nginx + # TLS configuration + tls: [] + # Annotations to apply to the registry server ingress. + annotations: {} + # If you want a custom path, you can try this example: + # path: /api(/|$)(.*) + # annotations: + # { nginx.ingress.kubernetes.io/rewrite-target: /$2 } diff --git a/utils/assets/charts/grafana/.helmignore b/utils/assets/charts/grafana/.helmignore new file mode 100644 index 0000000..8cade13 --- /dev/null +++ b/utils/assets/charts/grafana/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.vscode +.project +.idea/ +*.tmproj +OWNERS diff --git a/utils/assets/charts/grafana/Chart.yaml b/utils/assets/charts/grafana/Chart.yaml new file mode 100644 index 0000000..76628eb --- /dev/null +++ b/utils/assets/charts/grafana/Chart.yaml @@ -0,0 +1,35 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/grafana/helm-charts + - name: Upstream Project + url: https://github.com/grafana/grafana +apiVersion: v2 +appVersion: 11.3.1 +description: The leading tool for querying and visualizing time series and metrics. +home: https://grafana.com +icon: https://artifacthub.io/image/b4fed1a7-6c8f-4945-b99d-096efa3e4116 +keywords: +- monitoring +- metric +kubeVersion: ^1.8.0-0 +maintainers: +- email: zanhsieh@gmail.com + name: zanhsieh +- email: rluckie@cisco.com + name: rtluckie +- email: maor.friedman@redhat.com + name: maorfr +- email: miroslav.hadzhiev@gmail.com + name: Xtigyro +- email: mail@torstenwalter.de + name: torstenwalter +- email: github@jkroepke.de + name: jkroepke +name: grafana +sources: +- https://github.com/grafana/grafana +- https://github.com/grafana/helm-charts +type: application +version: 8.6.4 diff --git a/utils/assets/charts/grafana/README.md b/utils/assets/charts/grafana/README.md new file mode 100644 index 0000000..a78b123 --- /dev/null +++ b/utils/assets/charts/grafana/README.md @@ -0,0 +1,783 @@ +# Grafana Helm Chart + +* Installs the web dashboarding system [Grafana](http://grafana.org/) + +## Get Repo Info + +```console +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release grafana/grafana +``` + +## Uninstalling the Chart + +To uninstall/delete the my-release deployment: + +```console +helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Upgrading an existing Release to a new major version + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an +incompatible breaking change needing manual actions. + +### To 4.0.0 (And 3.12.1) + +This version requires Helm >= 2.12.0. + +### To 5.0.0 + +You have to add --force to your helm upgrade command as the labels of the chart have changed. + +### To 6.0.0 + +This version requires Helm >= 3.1.0. + +### To 7.0.0 + +For consistency with other Helm charts, the `global.image.registry` parameter was renamed +to `global.imageRegistry`. If you were not previously setting `global.image.registry`, no action +is required on upgrade. If you were previously setting `global.image.registry`, you will +need to instead set `global.imageRegistry`. + +## Configuration + +| Parameter | Description | Default | +|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------| +| `replicas` | Number of nodes | `1` | +| `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` | +| `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `nil` | +| `podDisruptionBudget.apiVersion` | Pod disruption apiVersion | `nil` | +| `deploymentStrategy` | Deployment strategy | `{ "type": "RollingUpdate" }` | +| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` | +| `readinessProbe` | Readiness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`| +| `securityContext` | Deployment securityContext | `{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}` | +| `priorityClassName` | Name of Priority Class to assign pods | `nil` | +| `image.registry` | Image registry | `docker.io` | +| `image.repository` | Image repository | `grafana/grafana` | +| `image.tag` | Overrides the Grafana image tag whose default is the chart appVersion (`Must be >= 5.0.0`) | `` | +| `image.sha` | Image sha (optional) | `` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Image pull secrets (can be templated) | `[]` | +| `service.enabled` | Enable grafana service | `true` | +| `service.ipFamilies` | Kubernetes service IP families | `[]` | +| `service.ipFamilyPolicy` | Kubernetes service IP family policy | `""` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.port` | Kubernetes port where service is exposed | `80` | +| `service.portName` | Name of the port on the service | `service` | +| `service.appProtocol` | Adds the appProtocol field to the service | `` | +| `service.targetPort` | Internal service is port | `3000` | +| `service.nodePort` | Kubernetes service nodePort | `nil` | +| `service.annotations` | Service annotations (can be templated) | `{}` | +| `service.labels` | Custom labels | `{}` | +| `service.clusterIP` | internal cluster service IP | `nil` | +| `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `nil` | +| `service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to lb (if supported) | `[]` | +| `service.externalIPs` | service external IP addresses | `[]` | +| `service.externalTrafficPolicy` | change the default externalTrafficPolicy | `nil` | +| `headlessService` | Create a headless service | `false` | +| `extraExposePorts` | Additional service ports for sidecar containers| `[]` | +| `hostAliases` | adds rules to the pod's /etc/hosts | `[]` | +| `ingress.enabled` | Enables Ingress | `false` | +| `ingress.annotations` | Ingress annotations (values are templated) | `{}` | +| `ingress.labels` | Custom labels | `{}` | +| `ingress.path` | Ingress accepted path | `/` | +| `ingress.pathType` | Ingress type of path | `Prefix` | +| `ingress.hosts` | Ingress accepted hostnames | `["chart-example.local"]` | +| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.6/guide/ingress/annotations/#actions). Requires `ingress.hosts` to have one or more host entries. | `[]` | +| `ingress.tls` | Ingress TLS configuration | `[]` | +| `ingress.ingressClassName` | Ingress Class Name. MAY be required for Kubernetes versions >= 1.18 | `""` | +| `resources` | CPU/Memory resource requests/limits | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Toleration labels for pod assignment | `[]` | +| `affinity` | Affinity settings for pod assignment | `{}` | +| `extraInitContainers` | Init containers to add to the grafana pod | `{}` | +| `extraContainers` | Sidecar containers to add to the grafana pod | `""` | +| `extraContainerVolumes` | Volumes that can be mounted in sidecar containers | `[]` | +| `extraLabels` | Custom labels for all manifests | `{}` | +| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | +| `persistence.enabled` | Use persistent volume to store data | `false` | +| `persistence.type` | Type of persistence (`pvc` or `statefulset`) | `pvc` | +| `persistence.size` | Size of persistent volume claim | `10Gi` | +| `persistence.existingClaim` | Use an existing PVC to persist data (can be templated) | `nil` | +| `persistence.storageClassName` | Type of persistent volume claim | `nil` | +| `persistence.accessModes` | Persistence access modes | `[ReadWriteOnce]` | +| `persistence.annotations` | PersistentVolumeClaim annotations | `{}` | +| `persistence.finalizers` | PersistentVolumeClaim finalizers | `[ "kubernetes.io/pvc-protection" ]` | +| `persistence.extraPvcLabels` | Extra labels to apply to a PVC. | `{}` | +| `persistence.subPath` | Mount a sub dir of the persistent volume (can be templated) | `nil` | +| `persistence.inMemory.enabled` | If persistence is not enabled, whether to mount the local storage in-memory to improve performance | `false` | +| `persistence.inMemory.sizeLimit` | SizeLimit for the in-memory local storage | `nil` | +| `persistence.disableWarning` | Hide NOTES warning, useful when persisting to a database | `false` | +| `initChownData.enabled` | If false, don't reset data ownership at startup | true | +| `initChownData.image.registry` | init-chown-data container image registry | `docker.io` | +| `initChownData.image.repository` | init-chown-data container image repository | `busybox` | +| `initChownData.image.tag` | init-chown-data container image tag | `1.31.1` | +| `initChownData.image.sha` | init-chown-data container image sha (optional)| `""` | +| `initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` | +| `initChownData.resources` | init-chown-data pod resource requests & limits | `{}` | +| `schedulerName` | Alternate scheduler name | `nil` | +| `env` | Extra environment variables passed to pods | `{}` | +| `envValueFrom` | Environment variables from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` | +| `envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | +| `envFromSecrets` | List of Kubernetes secrets (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | +| `envFromConfigMaps` | List of Kubernetes ConfigMaps (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | +| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret. (passed through [tpl](https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function)) | `{}` | +| `enableServiceLinks` | Inject Kubernetes services as environment variables. | `true` | +| `extraSecretMounts` | Additional grafana server secret mounts | `[]` | +| `extraVolumeMounts` | Additional grafana server volume mounts | `[]` | +| `extraVolumes` | Additional Grafana server volumes | `[]` | +| `automountServiceAccountToken` | Mounted the service account token on the grafana pod. Mandatory, if sidecars are enabled | `true` | +| `createConfigmap` | Enable creating the grafana configmap | `true` | +| `extraConfigmapMounts` | Additional grafana server configMap volume mounts (values are templated) | `[]` | +| `extraEmptyDirMounts` | Additional grafana server emptyDir volume mounts | `[]` | +| `plugins` | Plugins to be loaded along with Grafana | `[]` | +| `datasources` | Configure grafana datasources (passed through tpl) | `{}` | +| `alerting` | Configure grafana alerting (passed through tpl) | `{}` | +| `notifiers` | Configure grafana notifiers | `{}` | +| `dashboardProviders` | Configure grafana dashboard providers | `{}` | +| `dashboards` | Dashboards to import | `{}` | +| `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` | +| `grafana.ini` | Grafana's primary configuration | `{}` | +| `global.imageRegistry` | Global image pull registry for all images. | `null` | +| `global.imagePullSecrets` | Global image pull secrets (can be templated). Allows either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). | `[]` | +| `ldap.enabled` | Enable LDAP authentication | `false` | +| `ldap.existingSecret` | The name of an existing secret containing the `ldap.toml` file, this must have the key `ldap-toml`. | `""` | +| `ldap.config` | Grafana's LDAP configuration | `""` | +| `annotations` | Deployment annotations | `{}` | +| `labels` | Deployment labels | `{}` | +| `podAnnotations` | Pod annotations | `{}` | +| `podLabels` | Pod labels | `{}` | +| `podPortName` | Name of the grafana port on the pod | `grafana` | +| `lifecycleHooks` | Lifecycle hooks for podStart and preStop [Example](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers) | `{}` | +| `sidecar.image.registry` | Sidecar image registry | `quay.io` | +| `sidecar.image.repository` | Sidecar image repository | `kiwigrid/k8s-sidecar` | +| `sidecar.image.tag` | Sidecar image tag | `1.28.0` | +| `sidecar.image.sha` | Sidecar image sha (optional) | `""` | +| `sidecar.imagePullPolicy` | Sidecar image pull policy | `IfNotPresent` | +| `sidecar.resources` | Sidecar resources | `{}` | +| `sidecar.securityContext` | Sidecar securityContext | `{}` | +| `sidecar.enableUniqueFilenames` | Sets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable. If set to `true` the sidecar will create unique filenames where duplicate data keys exist between ConfigMaps and/or Secrets within the same or multiple Namespaces. | `false` | +| `sidecar.alerts.enabled` | Enables the cluster wide search for alerts and adds/updates/deletes them in grafana |`false` | +| `sidecar.alerts.label` | Label that config maps with alerts should have to be added | `grafana_alert` | +| `sidecar.alerts.labelValue` | Label value that config maps with alerts should have to be added | `""` | +| `sidecar.alerts.searchNamespace` | Namespaces list. If specified, the sidecar will search for alerts config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` | +| `sidecar.alerts.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | +| `sidecar.alerts.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.alerts.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/alerting/reload"` | +| `sidecar.alerts.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.alerts.initAlerts` | Set to true to deploy the alerts sidecar as an initContainer. This is needed if skipReload is true, to load any alerts defined at startup time. | `false` | +| `sidecar.alerts.extraMounts` | Additional alerts sidecar volume mounts. | `[]` | +| `sidecar.dashboards.enabled` | Enables the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` | +| `sidecar.dashboards.SCProvider` | Enables creation of sidecar provider | `true` | +| `sidecar.dashboards.provider.name` | Unique name of the grafana provider | `sidecarProvider` | +| `sidecar.dashboards.provider.orgid` | Id of the organisation, to which the dashboards should be added | `1` | +| `sidecar.dashboards.provider.folder` | Logical folder in which grafana groups dashboards | `""` | +| `sidecar.dashboards.provider.folderUid` | Allows you to specify the static UID for the logical folder above | `""` | +| `sidecar.dashboards.provider.disableDelete` | Activate to avoid the deletion of imported dashboards | `false` | +| `sidecar.dashboards.provider.allowUiUpdates` | Allow updating provisioned dashboards from the UI | `false` | +| `sidecar.dashboards.provider.type` | Provider type | `file` | +| `sidecar.dashboards.provider.foldersFromFilesStructure` | Allow Grafana to replicate dashboard structure from filesystem. | `false` | +| `sidecar.dashboards.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | +| `sidecar.skipTlsVerify` | Set to true to skip tls verification for kube api calls | `nil` | +| `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `grafana_dashboard` | +| `sidecar.dashboards.labelValue` | Label value that config maps with dashboards should have to be added | `""` | +| `sidecar.dashboards.folder` | Folder in the pod that should hold the collected dashboards (unless `sidecar.dashboards.defaultFolderName` is set). This path will be mounted. | `/tmp/dashboards` | +| `sidecar.dashboards.folderAnnotation` | The annotation the sidecar will look for in configmaps to override the destination folder for files | `nil` | +| `sidecar.dashboards.defaultFolderName` | The default folder name, it will create a subfolder under the `sidecar.dashboards.folder` and put dashboards in there instead | `nil` | +| `sidecar.dashboards.searchNamespace` | Namespaces list. If specified, the sidecar will search for dashboards config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` | +| `sidecar.dashboards.script` | Absolute path to shell script to execute after a configmap got reloaded. | `nil` | +| `sidecar.dashboards.reloadURL` | Full url of dashboards configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/dashboards/reload"` | +| `sidecar.dashboards.skipReload` | Enabling this omits defining the REQ_USERNAME, REQ_PASSWORD, REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.dashboards.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.dashboards.extraMounts` | Additional dashboard sidecar volume mounts. | `[]` | +| `sidecar.datasources.enabled` | Enables the cluster wide search for datasources and adds/updates/deletes them in grafana |`false` | +| `sidecar.datasources.label` | Label that config maps with datasources should have to be added | `grafana_datasource` | +| `sidecar.datasources.labelValue` | Label value that config maps with datasources should have to be added | `""` | +| `sidecar.datasources.searchNamespace` | Namespaces list. If specified, the sidecar will search for datasources config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` | +| `sidecar.datasources.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | +| `sidecar.datasources.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.datasources.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/datasources/reload"` | +| `sidecar.datasources.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.datasources.initDatasources` | Set to true to deploy the datasource sidecar as an initContainer in addition to a container. This is needed if skipReload is true, to load any datasources defined at startup time. | `false` | +| `sidecar.notifiers.enabled` | Enables the cluster wide search for notifiers and adds/updates/deletes them in grafana | `false` | +| `sidecar.notifiers.label` | Label that config maps with notifiers should have to be added | `grafana_notifier` | +| `sidecar.notifiers.labelValue` | Label value that config maps with notifiers should have to be added | `""` | +| `sidecar.notifiers.searchNamespace` | Namespaces list. If specified, the sidecar will search for notifiers config-maps (or secrets) inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` | +| `sidecar.notifiers.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | +| `sidecar.notifiers.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.notifiers.reloadURL` | Full url of notifier configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/notifications/reload"` | +| `sidecar.notifiers.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.notifiers.initNotifiers` | Set to true to deploy the notifier sidecar as an initContainer in addition to a container. This is needed if skipReload is true, to load any notifiers defined at startup time. | `false` | +| `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials. | `""` | +| `smtp.userKey` | The key in the existing SMTP secret containing the username. | `"user"` | +| `smtp.passwordKey` | The key in the existing SMTP secret containing the password. | `"password"` | +| `admin.existingSecret` | The name of an existing secret containing the admin credentials (can be templated). | `""` | +| `admin.userKey` | The key in the existing admin secret containing the username. | `"admin-user"` | +| `admin.passwordKey` | The key in the existing admin secret containing the password. | `"admin-password"` | +| `serviceAccount.automountServiceAccountToken` | Automount the service account token on all pods where is service account is used | `false` | +| `serviceAccount.annotations` | ServiceAccount annotations | | +| `serviceAccount.create` | Create service account | `true` | +| `serviceAccount.labels` | ServiceAccount labels | `{}` | +| `serviceAccount.name` | Service account name to use, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `` | +| `serviceAccount.nameTest` | Service account name to use for test, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `nil` | +| `rbac.create` | Create and use RBAC resources | `true` | +| `rbac.namespaced` | Creates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the grafana instance | `false` | +| `rbac.useExistingRole` | Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. | `nil` | +| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `false` | +| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `false` | +| `rbac.extraRoleRules` | Additional rules to add to the Role | [] | +| `rbac.extraClusterRoleRules` | Additional rules to add to the ClusterRole | [] | +| `command` | Define command to be executed by grafana container at startup | `nil` | +| `args` | Define additional args if command is used | `nil` | +| `testFramework.enabled` | Whether to create test-related resources | `true` | +| `testFramework.image.registry` | `test-framework` image registry. | `docker.io` | +| `testFramework.image.repository` | `test-framework` image repository. | `bats/bats` | +| `testFramework.image.tag` | `test-framework` image tag. | `v1.4.1` | +| `testFramework.imagePullPolicy` | `test-framework` image pull policy. | `IfNotPresent` | +| `testFramework.securityContext` | `test-framework` securityContext | `{}` | +| `downloadDashboards.env` | Environment variables to be passed to the `download-dashboards` container | `{}` | +| `downloadDashboards.envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | +| `downloadDashboards.resources` | Resources of `download-dashboards` container | `{}` | +| `downloadDashboardsImage.registry` | Curl docker image registry | `docker.io` | +| `downloadDashboardsImage.repository` | Curl docker image repository | `curlimages/curl` | +| `downloadDashboardsImage.tag` | Curl docker image tag | `7.73.0` | +| `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` | +| `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` | +| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | +| `serviceMonitor.enabled` | Use servicemonitor from prometheus operator | `false` | +| `serviceMonitor.namespace` | Namespace this servicemonitor is installed in | | +| `serviceMonitor.interval` | How frequently Prometheus should scrape | `1m` | +| `serviceMonitor.path` | Path to scrape | `/metrics` | +| `serviceMonitor.scheme` | Scheme to use for metrics scraping | `http` | +| `serviceMonitor.tlsConfig` | TLS configuration block for the endpoint | `{}` | +| `serviceMonitor.labels` | Labels for the servicemonitor passed to Prometheus Operator | `{}` | +| `serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `30s` | +| `serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` | +| `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` | +| `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` | +| `imageRenderer.image.registry` | image-renderer Image registry | `docker.io` | +| `imageRenderer.image.repository` | image-renderer Image repository | `grafana/grafana-image-renderer` | +| `imageRenderer.image.tag` | image-renderer Image tag | `latest` | +| `imageRenderer.image.sha` | image-renderer Image sha (optional) | `""` | +| `imageRenderer.image.pullPolicy` | image-renderer ImagePullPolicy | `Always` | +| `imageRenderer.env` | extra env-vars for image-renderer | `{}` | +| `imageRenderer.envValueFrom` | Environment variables for image-renderer from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` | +| `imageRenderer.extraConfigmapMounts` | Additional image-renderer configMap volume mounts (values are templated) | `[]` | +| `imageRenderer.extraSecretMounts` | Additional image-renderer secret volume mounts | `[]` | +| `imageRenderer.extraVolumeMounts` | Additional image-renderer volume mounts | `[]` | +| `imageRenderer.extraVolumes` | Additional image-renderer volumes | `[]` | +| `imageRenderer.serviceAccountName` | image-renderer deployment serviceAccountName | `""` | +| `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` | +| `imageRenderer.podAnnotations` | image-renderer image-renderer pod annotation | `{}` | +| `imageRenderer.hostAliases` | image-renderer deployment Host Aliases | `[]` | +| `imageRenderer.priorityClassName` | image-renderer deployment priority class | `''` | +| `imageRenderer.service.enabled` | Enable the image-renderer service | `true` | +| `imageRenderer.service.portName` | image-renderer service port name | `http` | +| `imageRenderer.service.port` | image-renderer port used by deployment | `8081` | +| `imageRenderer.service.targetPort` | image-renderer service port used by service | `8081` | +| `imageRenderer.appProtocol` | Adds the appProtocol field to the service | `` | +| `imageRenderer.grafanaSubPath` | Grafana sub path to use for image renderer callback url | `''` | +| `imageRenderer.serverURL` | Remote image renderer url | `''` | +| `imageRenderer.renderingCallbackURL` | Callback url for the Grafana image renderer | `''` | +| `imageRenderer.podPortName` | name of the image-renderer port on the pod | `http` | +| `imageRenderer.revisionHistoryLimit` | number of image-renderer replica sets to keep | `10` | +| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` | +| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` | +| `imageRenderer.resources` | Set resource limits for image-renderer pods | `{}` | +| `imageRenderer.nodeSelector` | Node labels for pod assignment | `{}` | +| `imageRenderer.tolerations` | Toleration labels for pod assignment | `[]` | +| `imageRenderer.affinity` | Affinity settings for pod assignment | `{}` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources. | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed | `{}` | +| `networkPolicy.ingress` | Enable the creation of an ingress network policy | `true` | +| `networkPolicy.egress.enabled` | Enable the creation of an egress network policy | `false` | +| `networkPolicy.egress.ports` | An array of ports to allow for the egress | `[]` | +| `enableKubeBackwardCompatibility` | Enable backward compatibility of kubernetes where pod's defintion version below 1.13 doesn't have the enableServiceLinks option | `false` | + +### Example ingress with path + +With grafana 6.3 and above + +```yaml +grafana.ini: + server: + domain: monitoring.example.com + root_url: "%(protocol)s://%(domain)s/grafana" + serve_from_sub_path: true +ingress: + enabled: true + hosts: + - "monitoring.example.com" + path: "/grafana" +``` + +### Example of extraVolumeMounts and extraVolumes + +Configure additional volumes with `extraVolumes` and volume mounts with `extraVolumeMounts`. + +Example for `extraVolumeMounts` and corresponding `extraVolumes`: + +```yaml +extraVolumeMounts: + - name: plugins + mountPath: /var/lib/grafana/plugins + subPath: configs/grafana/plugins + readOnly: false + - name: dashboards + mountPath: /var/lib/grafana/dashboards + hostPath: /usr/shared/grafana/dashboards + readOnly: false + +extraVolumes: + - name: plugins + existingClaim: existing-grafana-claim + - name: dashboards + hostPath: /usr/shared/grafana/dashboards +``` + +Volumes default to `emptyDir`. Set to `persistentVolumeClaim`, +`hostPath`, `csi`, or `configMap` for other types. For a +`persistentVolumeClaim`, specify an existing claim name with +`existingClaim`. + +## Import dashboards + +There are a few methods to import dashboards to Grafana. Below are some examples and explanations as to how to use each method: + +```yaml +dashboards: + default: + some-dashboard: + json: | + { + "annotations": + + ... + # Complete json file here + ... + + "title": "Some Dashboard", + "uid": "abcd1234", + "version": 1 + } + custom-dashboard: + # This is a path to a file inside the dashboards directory inside the chart directory + file: dashboards/custom-dashboard.json + prometheus-stats: + # Ref: https://grafana.com/dashboards/2 + gnetId: 2 + revision: 2 + datasource: Prometheus + loki-dashboard-quick-search: + gnetId: 12019 + revision: 2 + datasource: + - name: DS_PROMETHEUS + value: Prometheus + - name: DS_LOKI + value: Loki + local-dashboard: + url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json +``` + +## BASE64 dashboards + +Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit) +A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk. +If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk. + +### Gerrit use case + +Gerrit API for download files has the following schema: where {project-name} and +{file-id} usually has '/' in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard +the url value is + +## Sidecar for dashboards + +If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana +pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with +a label as defined in `sidecar.dashboards.label`. The files defined in those configmaps are written +to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported +dashboards are deleted/updated. + +A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside +one configmap is currently not properly mirrored in grafana. + +Example dashboard config: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-grafana-dashboard + labels: + grafana_dashboard: "1" +data: + k8s-dashboard.json: |- + [...] +``` + +## Sidecar for datasources + +If the parameter `sidecar.datasources.enabled` is set, an init container is deployed in the grafana +pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and +filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in +those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, +the data sources in grafana can be imported. + +Should you aim for reloading datasources in Grafana each time the config is changed, set `sidecar.datasources.skipReload: false` and adjust `sidecar.datasources.reloadURL` to `http://..svc.cluster.local/api/admin/provisioning/datasources/reload`. + +Secrets are recommended over configmaps for this usecase because datasources usually contain private +data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those. + +Example values to add a postgres datasource as a kubernetes secret: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: grafana-datasources + labels: + grafana_datasource: 'true' # default value for: sidecar.datasources.label +stringData: + pg-db.yaml: |- + apiVersion: 1 + datasources: + - name: My pg db datasource + type: postgres + url: my-postgresql-db:5432 + user: db-readonly-user + secureJsonData: + password: 'SUperSEcretPa$$word' + jsonData: + database: my_datase + sslmode: 'disable' # disable/require/verify-ca/verify-full + maxOpenConns: 0 # Grafana v5.4+ + maxIdleConns: 2 # Grafana v5.4+ + connMaxLifetime: 14400 # Grafana v5.4+ + postgresVersion: 1000 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10 + timescaledb: false + # allow users to edit datasources from the UI. + editable: false +``` + +Example values to add a datasource adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file): + +```yaml +datasources: + datasources.yaml: + apiVersion: 1 + datasources: + # name of the datasource. Required + - name: Graphite + # datasource type. Required + type: graphite + # access mode. proxy or direct (Server or Browser in the UI). Required + access: proxy + # org id. will default to orgId 1 if not specified + orgId: 1 + # url + url: http://localhost:8080 + # database password, if used + password: + # database user, if used + user: + # database name, if used + database: + # enable/disable basic auth + basicAuth: + # basic auth username + basicAuthUser: + # basic auth password + basicAuthPassword: + # enable/disable with credentials headers + withCredentials: + # mark as default datasource. Max one per org + isDefault: + # fields that will be converted to json and stored in json_data + jsonData: + graphiteVersion: "1.1" + tlsAuth: true + tlsAuthWithCACert: true + # json object of data that will be encrypted. + secureJsonData: + tlsCACert: "..." + tlsClientCert: "..." + tlsClientKey: "..." + version: 1 + # allow users to edit datasources from the UI. + editable: false +``` + +## Sidecar for notifiers + +If the parameter `sidecar.notifiers.enabled` is set, an init container is deployed in the grafana +pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and +filters out the ones with a label as defined in `sidecar.notifiers.label`. The files defined in +those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, +the notification channels in grafana can be imported. The secrets must be created before +`helm install` so that the notifiers init container can list the secrets. + +Secrets are recommended over configmaps for this usecase because alert notification channels usually contain +private data like SMTP usernames and passwords. Secrets are the more appropriate cluster resource to manage those. + +Example datasource config adapted from [Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/#alert-notification-channels): + +```yaml +notifiers: + - name: notification-channel-1 + type: slack + uid: notifier1 + # either + org_id: 2 + # or + org_name: Main Org. + is_default: true + send_reminder: true + frequency: 1h + disable_resolve_message: false + # See `Supported Settings` section for settings supporter for each + # alert notification type. + settings: + recipient: 'XXX' + token: 'xoxb' + uploadImage: true + url: https://slack.com + +delete_notifiers: + - name: notification-channel-1 + uid: notifier1 + org_id: 2 + - name: notification-channel-2 + # default org_id: 1 +``` + +## Sidecar for alerting resources + +If the parameter `sidecar.alerts.enabled` is set, a sidecar container is deployed in the grafana +pod. This container watches all configmaps (or secrets) in the cluster (namespace defined by `sidecar.alerts.searchNamespace`) and filters out the ones with +a label as defined in `sidecar.alerts.label` (default is `grafana_alert`). The files defined in those configmaps are written +to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported alerting resources are updated, however, deletions are a little more complicated (see below). + +This sidecar can be used to provision alert rules, contact points, notification policies, notification templates and mute timings as shown in [Grafana Documentation](https://grafana.com/docs/grafana/next/alerting/set-up/provision-alerting-resources/file-provisioning/). + +To fetch the alert config which will be provisioned, use the alert provisioning API ([Grafana Documentation](https://grafana.com/docs/grafana/next/developers/http_api/alerting_provisioning/)). +You can use either JSON or YAML format. + +Example config for an alert rule: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-grafana-alert + labels: + grafana_alert: "1" +data: + k8s-alert.yml: |- + apiVersion: 1 + groups: + - orgId: 1 + name: k8s-alert + [...] +``` + +To delete provisioned alert rules is a two step process, you need to delete the configmap which defined the alert rule +and then create a configuration which deletes the alert rule. + +Example deletion configuration: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: delete-sample-grafana-alert + namespace: monitoring + labels: + grafana_alert: "1" +data: + delete-k8s-alert.yml: |- + apiVersion: 1 + deleteRules: + - orgId: 1 + uid: 16624780-6564-45dc-825c-8bded4ad92d3 +``` + +## Statically provision alerting resources + +If you don't need to change alerting resources (alert rules, contact points, notification policies and notification templates) regularly you could use the `alerting` config option instead of the sidecar option above. +This will grab the alerting config and apply it statically at build time for the helm file. + +There are two methods to statically provision alerting configuration in Grafana. Below are some examples and explanations as to how to use each method: + +```yaml +alerting: + team1-alert-rules.yaml: + file: alerting/team1/rules.yaml + team2-alert-rules.yaml: + file: alerting/team2/rules.yaml + team3-alert-rules.yaml: + file: alerting/team3/rules.yaml + notification-policies.yaml: + file: alerting/shared/notification-policies.yaml + notification-templates.yaml: + file: alerting/shared/notification-templates.yaml + contactpoints.yaml: + apiVersion: 1 + contactPoints: + - orgId: 1 + name: Slack channel + receivers: + - uid: default-receiver + type: slack + settings: + # Webhook URL to be filled in + url: "" + # We need to escape double curly braces for the tpl function. + text: '{{ `{{ template "default.message" . }}` }}' + title: '{{ `{{ template "default.title" . }}` }}' +``` + +The two possibilities for static alerting resource provisioning are: + +* Inlining the file contents as shown for contact points in the above example. +* Importing a file using a relative path starting from the chart root directory as shown for the alert rules in the above example. + +### Important notes on file provisioning + +* The format of the files is defined in the [Grafana documentation](https://grafana.com/docs/grafana/next/alerting/set-up/provision-alerting-resources/file-provisioning/) on file provisioning. +* The chart supports importing YAML and JSON files. +* The filename must be unique, otherwise one volume mount will overwrite the other. +* In case of inlining, double curly braces that arise from the Grafana configuration format and are not intended as templates for the chart must be escaped. +* The number of total files under `alerting:` is not limited. Each file will end up as a volume mount in the corresponding provisioning folder of the deployed Grafana instance. +* The file size for each import is limited by what the function `.Files.Get` can handle, which suffices for most cases. + +## How to serve Grafana with a path prefix (/grafana) + +In order to serve Grafana with a prefix (e.g., ), add the following to your values.yaml. + +```yaml +ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/rewrite-target: /$1 + nginx.ingress.kubernetes.io/use-regex: "true" + + path: /grafana/?(.*) + hosts: + - k8s.example.dev + +grafana.ini: + server: + root_url: http://localhost:3000/grafana # this host can be localhost +``` + +## How to securely reference secrets in grafana.ini + +This example uses Grafana [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets. + +In grafana.ini: + +```yaml +grafana.ini: + [auth.generic_oauth] + enabled = true + client_id = $__file{/etc/secrets/auth_generic_oauth/client_id} + client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret} +``` + +Existing secret, or created along with helm: + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: auth-generic-oauth-secret +type: Opaque +stringData: + client_id: + client_secret: +``` + +Include in the `extraSecretMounts` configuration flag: + +```yaml +extraSecretMounts: + - name: auth-generic-oauth-secret-mount + secretName: auth-generic-oauth-secret + defaultMode: 0440 + mountPath: /etc/secrets/auth_generic_oauth + readOnly: true +``` + +### extraSecretMounts using a Container Storage Interface (CSI) provider + +This example uses a CSI driver e.g. retrieving secrets using [Azure Key Vault Provider](https://github.com/Azure/secrets-store-csi-driver-provider-azure) + +```yaml +extraSecretMounts: + - name: secrets-store-inline + mountPath: /run/secrets + readOnly: true + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: "my-provider" + nodePublishSecretRef: + name: akv-creds +``` + +## Image Renderer Plug-In + +This chart supports enabling [remote image rendering](https://github.com/grafana/grafana-image-renderer/blob/master/README.md#run-in-docker) + +```yaml +imageRenderer: + enabled: true +``` + +### Image Renderer NetworkPolicy + +By default the image-renderer pods will have a network policy which only allows ingress traffic from the created grafana instance + +### High Availability for unified alerting + +If you want to run Grafana in a high availability cluster you need to enable +the headless service by setting `headlessService: true` in your `values.yaml` +file. + +As next step you have to setup the `grafana.ini` in your `values.yaml` in a way +that it will make use of the headless service to obtain all the IPs of the +cluster. You should replace ``{{ Name }}`` with the name of your helm deployment. + +```yaml +grafana.ini: + ... + unified_alerting: + enabled: true + ha_peers: {{ Name }}-headless:9094 + ha_listen_address: ${POD_IP}:9094 + ha_advertise_address: ${POD_IP}:9094 + + alerting: + enabled: false +``` diff --git a/utils/assets/charts/grafana/ci/default-values.yaml b/utils/assets/charts/grafana/ci/default-values.yaml new file mode 100644 index 0000000..fc2ba60 --- /dev/null +++ b/utils/assets/charts/grafana/ci/default-values.yaml @@ -0,0 +1 @@ +# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. diff --git a/utils/assets/charts/grafana/ci/with-affinity-values.yaml b/utils/assets/charts/grafana/ci/with-affinity-values.yaml new file mode 100644 index 0000000..f5b9b53 --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-affinity-values.yaml @@ -0,0 +1,16 @@ +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/instance: grafana-test + app.kubernetes.io/name: grafana + topologyKey: failure-domain.beta.kubernetes.io/zone + weight: 100 + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/instance: grafana-test + app.kubernetes.io/name: grafana + topologyKey: kubernetes.io/hostname diff --git a/utils/assets/charts/grafana/ci/with-dashboard-json-values.yaml b/utils/assets/charts/grafana/ci/with-dashboard-json-values.yaml new file mode 100644 index 0000000..e0c4e41 --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-dashboard-json-values.yaml @@ -0,0 +1,53 @@ +dashboards: + my-provider: + my-awesome-dashboard: + # An empty but valid dashboard + json: | + { + "__inputs": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.3.5" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [], + "schemaVersion": 19, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": ["5s"] + }, + "timezone": "", + "title": "Dummy Dashboard", + "uid": "IdcYQooWk", + "version": 1 + } + datasource: Prometheus diff --git a/utils/assets/charts/grafana/ci/with-dashboard-values.yaml b/utils/assets/charts/grafana/ci/with-dashboard-values.yaml new file mode 100644 index 0000000..7b662c5 --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-dashboard-values.yaml @@ -0,0 +1,19 @@ +dashboards: + my-provider: + my-awesome-dashboard: + gnetId: 10000 + revision: 1 + datasource: Prometheus +dashboardProviders: + dashboardproviders.yaml: + apiVersion: 1 + providers: + - name: 'my-provider' + orgId: 1 + folder: '' + type: file + updateIntervalSeconds: 10 + disableDeletion: true + editable: true + options: + path: /var/lib/grafana/dashboards/my-provider diff --git a/utils/assets/charts/grafana/ci/with-extraconfigmapmounts-values.yaml b/utils/assets/charts/grafana/ci/with-extraconfigmapmounts-values.yaml new file mode 100644 index 0000000..5cc44a0 --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-extraconfigmapmounts-values.yaml @@ -0,0 +1,7 @@ +extraConfigmapMounts: + - name: '{{ include "grafana.fullname" . }}' + configMap: '{{ include "grafana.fullname" . }}' + mountPath: /var/lib/grafana/dashboards/test-dashboard.json + # This is not a realistic test, but for this we only care about extraConfigmapMounts not being empty and pointing to an existing ConfigMap + subPath: grafana.ini + readOnly: true diff --git a/utils/assets/charts/grafana/ci/with-image-renderer-values.yaml b/utils/assets/charts/grafana/ci/with-image-renderer-values.yaml new file mode 100644 index 0000000..06c0bda --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-image-renderer-values.yaml @@ -0,0 +1,107 @@ +podLabels: + customLableA: Aaaaa +imageRenderer: + enabled: true + env: + RENDERING_ARGS: --disable-gpu,--window-size=1280x758 + RENDERING_MODE: clustered + podLabels: + customLableB: Bbbbb + networkPolicy: + limitIngress: true + limitEgress: true + resources: + limits: + cpu: 1000m + memory: 1000Mi + requests: + cpu: 500m + memory: 50Mi + extraVolumes: + - name: empty-renderer-volume + emtpyDir: {} + extraVolumeMounts: + - mountPath: /tmp/renderer + name: empty-renderer-volume + extraConfigmapMounts: + - name: renderer-config + mountPath: /usr/src/app/config.json + subPath: renderer-config.json + configMap: image-renderer-config + extraSecretMounts: + - name: renderer-certificate + mountPath: /usr/src/app/certs/ + secretName: image-renderer-certificate + readOnly: true + +extraObjects: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: image-renderer-config + data: + renderer-config.json: | + { + "service": { + "host": null, + "port": 8081, + "protocol": "http", + "certFile": "", + "certKey": "", + + "metrics": { + "enabled": true, + "collectDefaultMetrics": true, + "requestDurationBuckets": [1, 5, 7, 9, 11, 13, 15, 20, 30] + }, + + "logging": { + "level": "info", + "console": { + "json": true, + "colorize": false + } + }, + + "security": { + "authToken": "-" + } + }, + "rendering": { + "chromeBin": null, + "args": ["--no-sandbox", "--disable-gpu"], + "ignoresHttpsErrors": false, + + "timezone": null, + "acceptLanguage": null, + "width": 1000, + "height": 500, + "deviceScaleFactor": 1, + "maxWidth": 3080, + "maxHeight": 3000, + "maxDeviceScaleFactor": 4, + "pageZoomLevel": 1, + "headed": false, + + "mode": "default", + "emulateNetworkConditions": false, + "clustering": { + "monitor": false, + "mode": "browser", + "maxConcurrency": 5, + "timeout": 30 + }, + + "verboseLogging": false, + "dumpio": false, + "timingMetrics": false + } + } + - apiVersion: v1 + kind: Secret + metadata: + name: image-renderer-certificate + type: Opaque + data: + # Decodes to 'PLACEHOLDER CERTIFICATE' + not-a-real-certificate: UExBQ0VIT0xERVIgQ0VSVElGSUNBVEU= diff --git a/utils/assets/charts/grafana/ci/with-nondefault-values.yaml b/utils/assets/charts/grafana/ci/with-nondefault-values.yaml new file mode 100644 index 0000000..4848489 --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-nondefault-values.yaml @@ -0,0 +1,32 @@ +global: + environment: prod +ingress: + enabled: true + hosts: + - monitoring-{{ .Values.global.environment }}.example.com + +route: + main: + enabled: true + labels: + app: monitoring-prometheus + hostnames: + - "*.example.com" + - "{{ .Values.global.environment }}.example.com" + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: my-header-name + value: my-new-header-value + additionalRules: + - filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: my-header-name + value: my-new-header-value + matches: + - path: + type: PathPrefix + value: /foo/ diff --git a/utils/assets/charts/grafana/ci/with-persistence.yaml b/utils/assets/charts/grafana/ci/with-persistence.yaml new file mode 100644 index 0000000..b92ca02 --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-persistence.yaml @@ -0,0 +1,3 @@ +persistence: + type: pvc + enabled: true diff --git a/utils/assets/charts/grafana/ci/with-sidecars-envvaluefrom-values.yaml b/utils/assets/charts/grafana/ci/with-sidecars-envvaluefrom-values.yaml new file mode 100644 index 0000000..a6935e5 --- /dev/null +++ b/utils/assets/charts/grafana/ci/with-sidecars-envvaluefrom-values.yaml @@ -0,0 +1,38 @@ +extraObjects: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ include "grafana.fullname" . }}-test' + data: + var1: "value1" + - apiVersion: v1 + kind: Secret + metadata: + name: '{{ include "grafana.fullname" . }}-test' + type: Opaque + data: + var2: "dmFsdWUy" + +sidecar: + dashboards: + enabled: true + envValueFrom: + VAR1: + configMapKeyRef: + name: '{{ include "grafana.fullname" . }}-test' + key: var1 + VAR2: + secretKeyRef: + name: '{{ include "grafana.fullname" . }}-test' + key: var2 + datasources: + enabled: true + envValueFrom: + VAR1: + configMapKeyRef: + name: '{{ include "grafana.fullname" . }}-test' + key: var1 + VAR2: + secretKeyRef: + name: '{{ include "grafana.fullname" . }}-test' + key: var2 diff --git a/utils/assets/charts/grafana/dashboards/custom-dashboard.json b/utils/assets/charts/grafana/dashboards/custom-dashboard.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/utils/assets/charts/grafana/dashboards/custom-dashboard.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/utils/assets/charts/grafana/templates/NOTES.txt b/utils/assets/charts/grafana/templates/NOTES.txt new file mode 100644 index 0000000..a40f666 --- /dev/null +++ b/utils/assets/charts/grafana/templates/NOTES.txt @@ -0,0 +1,55 @@ +1. Get your '{{ .Values.adminUser }}' user password by running: + + kubectl get secret --namespace {{ include "grafana.namespace" . }} {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} -o jsonpath="{.data.{{ .Values.admin.passwordKey | default "admin-password" }}}" | base64 --decode ; echo + + +2. The Grafana server can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: + + {{ include "grafana.fullname" . }}.{{ include "grafana.namespace" . }}.svc.cluster.local +{{ if .Values.ingress.enabled }} + If you bind grafana to 80, please update values in values.yaml and reinstall: + ``` + securityContext: + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + + command: + - "setcap" + - "'cap_net_bind_service=+ep'" + - "/usr/sbin/grafana-server &&" + - "sh" + - "/run.sh" + ``` + Details refer to https://grafana.com/docs/installation/configuration/#http-port. + Or grafana would always crash. + + From outside the cluster, the server URL(s) are: + {{- range .Values.ingress.hosts }} + http://{{ . }} + {{- end }} +{{- else }} + Get the Grafana URL to visit by running these commands in the same shell: + {{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ include "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "grafana.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ include "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT + {{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ include "grafana.namespace" . }} -w {{ include "grafana.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ include "grafana.namespace" . }} {{ include "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + http://$SERVICE_IP:{{ .Values.service.port -}} + {{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ include "grafana.namespace" . }} -l "app.kubernetes.io/name={{ include "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ include "grafana.namespace" . }} port-forward $POD_NAME 3000 + {{- end }} +{{- end }} + +3. Login with the password from step 1 and the username: {{ .Values.adminUser }} + +{{- if and (not .Values.persistence.enabled) (not .Values.persistence.disableWarning) }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the Grafana pod is terminated. ##### +################################################################################# +{{- end }} diff --git a/utils/assets/charts/grafana/templates/_config.tpl b/utils/assets/charts/grafana/templates/_config.tpl new file mode 100644 index 0000000..8897620 --- /dev/null +++ b/utils/assets/charts/grafana/templates/_config.tpl @@ -0,0 +1,176 @@ +{{/* + Generate config map data + */}} +{{- define "grafana.configData" -}} +{{ include "grafana.assertNoLeakedSecrets" . }} +{{- $files := .Files }} +{{- $root := . -}} +{{- with .Values.plugins }} +plugins: {{ join "," . }} +{{- end }} +grafana.ini: | +{{- range $elem, $elemVal := index .Values "grafana.ini" }} + {{- if not (kindIs "map" $elemVal) }} + {{- if kindIs "invalid" $elemVal }} + {{ $elem }} = + {{- else if kindIs "slice" $elemVal }} + {{ $elem }} = {{ toJson $elemVal }} + {{- else if kindIs "string" $elemVal }} + {{ $elem }} = {{ tpl $elemVal $ }} + {{- else }} + {{ $elem }} = {{ $elemVal }} + {{- end }} + {{- end }} +{{- end }} +{{- range $key, $value := index .Values "grafana.ini" }} + {{- if kindIs "map" $value }} + [{{ $key }}] + {{- range $elem, $elemVal := $value }} + {{- if kindIs "invalid" $elemVal }} + {{ $elem }} = + {{- else if kindIs "slice" $elemVal }} + {{ $elem }} = {{ toJson $elemVal }} + {{- else if kindIs "string" $elemVal }} + {{ $elem }} = {{ tpl $elemVal $ }} + {{- else }} + {{ $elem }} = {{ $elemVal }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} + +{{- range $key, $value := .Values.datasources }} +{{- if not (hasKey $value "secret") }} +{{ $key }}: | + {{- tpl (toYaml $value | nindent 2) $root }} +{{- end }} +{{- end }} + +{{- range $key, $value := .Values.notifiers }} +{{- if not (hasKey $value "secret") }} +{{ $key }}: | + {{- toYaml $value | nindent 2 }} +{{- end }} +{{- end }} + +{{- range $key, $value := .Values.alerting }} +{{- if (hasKey $value "file") }} +{{ $key }}: +{{- toYaml ( $files.Get $value.file ) | nindent 2 }} +{{- else if (or (hasKey $value "secret") (hasKey $value "secretFile"))}} +{{/* will be stored inside secret generated by "configSecret.yaml"*/}} +{{- else }} +{{ $key }}: | + {{- tpl (toYaml $value | nindent 2) $root }} +{{- end }} +{{- end }} + +{{- range $key, $value := .Values.dashboardProviders }} +{{ $key }}: | + {{- toYaml $value | nindent 2 }} +{{- end }} + +{{- if .Values.dashboards }} +download_dashboards.sh: | + #!/usr/bin/env sh + set -euf + {{- if .Values.dashboardProviders }} + {{- range $key, $value := .Values.dashboardProviders }} + {{- range $value.providers }} + mkdir -p {{ .options.path }} + {{- end }} + {{- end }} + {{- end }} +{{ $dashboardProviders := .Values.dashboardProviders }} +{{- range $provider, $dashboards := .Values.dashboards }} + {{- range $key, $value := $dashboards }} + {{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }} + curl -skf \ + --connect-timeout 60 \ + --max-time 60 \ + {{- if not $value.b64content }} + {{- if not $value.acceptHeader }} + -H "Accept: application/json" \ + {{- else }} + -H "Accept: {{ $value.acceptHeader }}" \ + {{- end }} + {{- if $value.token }} + -H "Authorization: token {{ $value.token }}" \ + {{- end }} + {{- if $value.bearerToken }} + -H "Authorization: Bearer {{ $value.bearerToken }}" \ + {{- end }} + {{- if $value.basic }} + -H "Authorization: Basic {{ $value.basic }}" \ + {{- end }} + {{- if $value.gitlabToken }} + -H "PRIVATE-TOKEN: {{ $value.gitlabToken }}" \ + {{- end }} + -H "Content-Type: application/json;charset=UTF-8" \ + {{- end }} + {{- $dpPath := "" -}} + {{- range $kd := (index $dashboardProviders "dashboardproviders.yaml").providers }} + {{- if eq $kd.name $provider }} + {{- $dpPath = $kd.options.path }} + {{- end }} + {{- end }} + {{- if $value.url }} + "{{ $value.url }}" \ + {{- else }} + "https://grafana.com/api/dashboards/{{ $value.gnetId }}/revisions/{{- if $value.revision -}}{{ $value.revision }}{{- else -}}1{{- end -}}/download" \ + {{- end }} + {{- if $value.datasource }} + {{- if kindIs "string" $value.datasource }} + | sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g' \ + {{- end }} + {{- if kindIs "slice" $value.datasource }} + {{- range $value.datasource }} + | sed '/-- .* --/! s/${{"{"}}{{ .name }}}/{{ .value }}/g' \ + {{- end }} + {{- end }} + {{- end }} + {{- if $value.b64content }} + | base64 -d \ + {{- end }} + > "{{- if $dpPath -}}{{ $dpPath }}{{- else -}}/var/lib/grafana/dashboards/{{ $provider }}{{- end -}}/{{ $key }}.json" + {{ end }} + {{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* + Generate dashboard json config map data + */}} +{{- define "grafana.configDashboardProviderData" -}} +provider.yaml: |- + apiVersion: 1 + providers: + - name: '{{ .Values.sidecar.dashboards.provider.name }}' + orgId: {{ .Values.sidecar.dashboards.provider.orgid }} + {{- if not .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + folder: '{{ .Values.sidecar.dashboards.provider.folder }}' + folderUid: '{{ .Values.sidecar.dashboards.provider.folderUid }}' + {{- end }} + type: {{ .Values.sidecar.dashboards.provider.type }} + disableDeletion: {{ .Values.sidecar.dashboards.provider.disableDelete }} + allowUiUpdates: {{ .Values.sidecar.dashboards.provider.allowUiUpdates }} + updateIntervalSeconds: {{ .Values.sidecar.dashboards.provider.updateIntervalSeconds | default 30 }} + options: + foldersFromFilesStructure: {{ .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + path: {{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }} +{{- end -}} + +{{- define "grafana.secretsData" -}} +{{- if and (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) }} +admin-user: {{ .Values.adminUser | b64enc | quote }} +{{- if .Values.adminPassword }} +admin-password: {{ .Values.adminPassword | b64enc | quote }} +{{- else }} +admin-password: {{ include "grafana.password" . }} +{{- end }} +{{- end }} +{{- if not .Values.ldap.existingSecret }} +ldap-toml: {{ tpl .Values.ldap.config $ | b64enc | quote }} +{{- end }} +{{- end -}} diff --git a/utils/assets/charts/grafana/templates/_helpers.tpl b/utils/assets/charts/grafana/templates/_helpers.tpl new file mode 100644 index 0000000..be9c1c5 --- /dev/null +++ b/utils/assets/charts/grafana/templates/_helpers.tpl @@ -0,0 +1,274 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "grafana.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "grafana.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "grafana.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create the name of the service account +*/}} +{{- define "grafana.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "grafana.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "grafana.serviceAccountNameTest" -}} +{{- if .Values.serviceAccount.create }} +{{- default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }} +{{- else }} +{{- default "default" .Values.serviceAccount.nameTest }} +{{- end }} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "grafana.namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "grafana.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | trunc 63 | trimSuffix "-" | quote }} +{{- end }} +{{- with .Values.extraLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "grafana.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "grafana.imageRenderer.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.imageRenderer.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | trunc 63 | trimSuffix "-" | quote }} +{{- end }} +{{- end }} + +{{/* +Selector labels ImageRenderer +*/}} +{{- define "grafana.imageRenderer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Looks if there's an existing secret and reuse its password. If not it generates +new password and use it. +*/}} +{{- define "grafana.password" -}} +{{- $secret := (lookup "v1" "Secret" (include "grafana.namespace" .) (include "grafana.fullname" .) ) }} +{{- if $secret }} +{{- index $secret "data" "admin-password" }} +{{- else }} +{{- (randAlphaNum 40) | b64enc | quote }} +{{- end }} +{{- end }} + +{{/* +Return the appropriate apiVersion for rbac. +*/}} +{{- define "grafana.rbac.apiVersion" -}} +{{- if $.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }} +{{- print "rbac.authorization.k8s.io/v1" }} +{{- else }} +{{- print "rbac.authorization.k8s.io/v1beta1" }} +{{- end }} +{{- end }} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "grafana.ingress.apiVersion" -}} +{{- if and ($.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) }} +{{- print "networking.k8s.io/v1" }} +{{- else if $.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +{{- print "networking.k8s.io/v1beta1" }} +{{- else }} +{{- print "extensions/v1beta1" }} +{{- end }} +{{- end }} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "grafana.hpa.apiVersion" -}} +{{- if .Capabilities.APIVersions.Has "autoscaling/v2" }} +{{- print "autoscaling/v2" }} +{{- else }} +{{- print "autoscaling/v2beta2" }} +{{- end }} +{{- end }} + +{{/* +Return the appropriate apiVersion for podDisruptionBudget. +*/}} +{{- define "grafana.podDisruptionBudget.apiVersion" -}} +{{- if $.Values.podDisruptionBudget.apiVersion }} +{{- print $.Values.podDisruptionBudget.apiVersion }} +{{- else if $.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +{{- print "policy/v1" }} +{{- else }} +{{- print "policy/v1beta1" }} +{{- end }} +{{- end }} + +{{/* +Return if ingress is stable. +*/}} +{{- define "grafana.ingress.isStable" -}} +{{- eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1" }} +{{- end }} + +{{/* +Return if ingress supports ingressClassName. +*/}} +{{- define "grafana.ingress.supportsIngressClassName" -}} +{{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) }} +{{- end }} + +{{/* +Return if ingress supports pathType. +*/}} +{{- define "grafana.ingress.supportsPathType" -}} +{{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) }} +{{- end }} + +{{/* +Formats imagePullSecrets. Input is (dict "root" . "imagePullSecrets" .{specific imagePullSecrets}) +*/}} +{{- define "grafana.imagePullSecrets" -}} +{{- $root := .root }} +{{- range (concat .root.Values.global.imagePullSecrets .imagePullSecrets) }} +{{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml (dict "name" (tpl .name $root)) | trim }} +{{- else }} +- name: {{ tpl . $root }} +{{- end }} +{{- end }} +{{- end }} + + +{{/* + Checks whether or not the configSecret secret has to be created + */}} +{{- define "grafana.shouldCreateConfigSecret" -}} +{{- $secretFound := false -}} +{{- range $key, $value := .Values.datasources }} + {{- if hasKey $value "secret" }} + {{- $secretFound = true}} + {{- end }} +{{- end }} +{{- range $key, $value := .Values.notifiers }} + {{- if hasKey $value "secret" }} + {{- $secretFound = true}} + {{- end }} +{{- end }} +{{- range $key, $value := .Values.alerting }} + {{- if (or (hasKey $value "secret") (hasKey $value "secretFile")) }} + {{- $secretFound = true}} + {{- end }} +{{- end }} +{{- $secretFound}} +{{- end -}} + +{{/* + Checks whether the user is attempting to store secrets in plaintext + in the grafana.ini configmap +*/}} +{{/* grafana.assertNoLeakedSecrets checks for sensitive keys in values */}} +{{- define "grafana.assertNoLeakedSecrets" -}} + {{- $sensitiveKeysYaml := ` +sensitiveKeys: +- path: ["database", "password"] +- path: ["smtp", "password"] +- path: ["security", "secret_key"] +- path: ["security", "admin_password"] +- path: ["auth.basic", "password"] +- path: ["auth.ldap", "bind_password"] +- path: ["auth.google", "client_secret"] +- path: ["auth.github", "client_secret"] +- path: ["auth.gitlab", "client_secret"] +- path: ["auth.generic_oauth", "client_secret"] +- path: ["auth.okta", "client_secret"] +- path: ["auth.azuread", "client_secret"] +- path: ["auth.grafana_com", "client_secret"] +- path: ["auth.grafananet", "client_secret"] +- path: ["azure", "user_identity_client_secret"] +- path: ["unified_alerting", "ha_redis_password"] +- path: ["metrics", "basic_auth_password"] +- path: ["external_image_storage.s3", "secret_key"] +- path: ["external_image_storage.webdav", "password"] +- path: ["external_image_storage.azure_blob", "account_key"] +` | fromYaml -}} + {{- if $.Values.assertNoLeakedSecrets -}} + {{- $grafanaIni := index .Values "grafana.ini" -}} + {{- range $_, $secret := $sensitiveKeysYaml.sensitiveKeys -}} + {{- $currentMap := $grafanaIni -}} + {{- $shouldContinue := true -}} + {{- range $index, $elem := $secret.path -}} + {{- if and $shouldContinue (hasKey $currentMap $elem) -}} + {{- if eq (len $secret.path) (add1 $index) -}} + {{- if not (regexMatch "\\$(?:__(?:env|file|vault))?{[^}]+}" (index $currentMap $elem)) -}} + {{- fail (printf "Sensitive key '%s' should not be defined explicitly in values. Use variable expansion instead. You can disable this client-side validation by changing the value of assertNoLeakedSecrets." (join "." $secret.path)) -}} + {{- end -}} + {{- else -}} + {{- $currentMap = index $currentMap $elem -}} + {{- end -}} + {{- else -}} + {{- $shouldContinue = false -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/grafana/templates/_pod.tpl b/utils/assets/charts/grafana/templates/_pod.tpl new file mode 100644 index 0000000..bf55e43 --- /dev/null +++ b/utils/assets/charts/grafana/templates/_pod.tpl @@ -0,0 +1,1389 @@ +{{- define "grafana.pod" -}} +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} +{{- $root := . -}} +{{- with .Values.schedulerName }} +schedulerName: "{{ . }}" +{{- end }} +serviceAccountName: {{ include "grafana.serviceAccountName" . }} +automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} +{{- with .Values.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.hostAliases }} +hostAliases: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- if .Values.dnsPolicy }} +dnsPolicy: {{ .Values.dnsPolicy }} +{{- end }} +{{- with .Values.dnsConfig }} +dnsConfig: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.priorityClassName }} +priorityClassName: {{ . }} +{{- end }} +{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.extraInitContainers (and .Values.sidecar.alerts.enabled .Values.sidecar.alerts.initAlerts) (and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources) (and .Values.sidecar.notifiers.enabled .Values.sidecar.notifiers.initNotifiers)) }} +initContainers: +{{- end }} +{{- if ( and .Values.persistence.enabled .Values.initChownData.enabled ) }} + - name: init-chown-data + {{- $registry := .Values.global.imageRegistry | default .Values.initChownData.image.registry -}} + {{- if .Values.initChownData.image.sha }} + image: "{{ $registry }}/{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} + {{- with .Values.initChownData.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + command: + - chown + - -R + - {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} + - /var/lib/grafana + {{- with .Values.initChownData.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: storage + mountPath: "/var/lib/grafana" + {{- with .Values.persistence.subPath }} + subPath: {{ tpl . $root }} + {{- end }} +{{- end }} +{{- if .Values.dashboards }} + - name: download-dashboards + {{- $registry := .Values.global.imageRegistry | default .Values.downloadDashboardsImage.registry -}} + {{- if .Values.downloadDashboardsImage.sha }} + image: "{{ $registry }}/{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} + command: ["/bin/sh"] + args: [ "-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh -x /etc/grafana/download_dashboards.sh" ] + {{- with .Values.downloadDashboards.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + env: + {{- range $key, $value := .Values.downloadDashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.downloadDashboards.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- with .Values.downloadDashboards.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.downloadDashboards.envFromSecret }} + envFrom: + - secretRef: + name: {{ tpl . $root }} + {{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/download_dashboards.sh" + subPath: download_dashboards.sh + - name: storage + mountPath: "/var/lib/grafana" + {{- with .Values.persistence.subPath }} + subPath: {{ tpl . $root }} + {{- end }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} +{{- end }} +{{- if and .Values.sidecar.alerts.enabled .Values.sidecar.alerts.initAlerts }} + - name: {{ include "grafana.name" . }}-init-sc-alerts + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.alerts.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.alerts.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: "LIST" + - name: LABEL + value: "{{ .Values.sidecar.alerts.label }}" + {{- with .Values.sidecar.alerts.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/alerting" + - name: RESOURCE + value: {{ quote .Values.sidecar.alerts.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.alerts.searchNamespace }} + - name: NAMESPACE + value: {{ . | join "," | quote }} + {{- end }} + {{- with .Values.sidecar.alerts.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: {{ quote . }} + {{- end }} + {{- with .Values.sidecar.alerts.script }} + - name: SCRIPT + value: {{ quote . }} + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-alerts-volume + mountPath: "/etc/grafana/provisioning/alerting" + {{- with .Values.sidecar.alerts.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} +{{- end }} +{{- if and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources }} + - name: {{ include "grafana.name" . }}-init-sc-datasources + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.sidecar.datasources.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: "LIST" + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- with .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- if .Values.sidecar.datasources.searchNamespace }} + - name: NAMESPACE + value: "{{ tpl (.Values.sidecar.datasources.searchNamespace | join ",") . }}" + {{- end }} + {{- with .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end }} +{{- if and .Values.sidecar.notifiers.enabled .Values.sidecar.notifiers.initNotifiers }} + - name: {{ include "grafana.name" . }}-init-sc-notifiers + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.notifiers.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.notifiers.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: LIST + - name: LABEL + value: "{{ .Values.sidecar.notifiers.label }}" + {{- with .Values.sidecar.notifiers.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/notifiers" + - name: RESOURCE + value: {{ quote .Values.sidecar.notifiers.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.notifiers.searchNamespace }} + - name: NAMESPACE + value: "{{ tpl (. | join ",") $root }}" + {{- end }} + {{- with .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} +{{- with .Values.extraInitContainers }} + {{- tpl (toYaml .) $root | nindent 2 }} +{{- end }} +{{- if or .Values.image.pullSecrets .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- include "grafana.imagePullSecrets" (dict "root" $root "imagePullSecrets" .Values.image.pullSecrets) | nindent 2 }} +{{- end }} +{{- if not .Values.enableKubeBackwardCompatibility }} +enableServiceLinks: {{ .Values.enableServiceLinks }} +{{- end }} +containers: +{{- if and .Values.sidecar.alerts.enabled (not .Values.sidecar.alerts.initAlerts) }} + - name: {{ include "grafana.name" . }}-sc-alerts + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.alerts.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.alerts.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.alerts.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.alerts.label }}" + {{- with .Values.sidecar.alerts.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/alerting" + - name: RESOURCE + value: {{ quote .Values.sidecar.alerts.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.alerts.searchNamespace }} + - name: NAMESPACE + value: {{ . | join "," | quote }} + {{- end }} + {{- with .Values.sidecar.alerts.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: {{ quote . }} + {{- end }} + {{- with .Values.sidecar.alerts.script }} + - name: SCRIPT + value: {{ quote . }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.alerts.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.alerts.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.alerts.watchServerTimeout }} + {{- if ne .Values.sidecar.alerts.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.alerts.watchServerTimeout with .Values.sidecar.alerts.watchMethod %s" .Values.sidecar.alerts.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.alerts.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.alerts.watchClientTimeout }} + {{- if ne .Values.sidecar.alerts.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.alerts.watchClientTimeout with .Values.sidecar.alerts.watchMethod %s" .Values.sidecar.alerts.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.alerts.watchClientTimeout }}" + {{- end }} + {{- if .Values.sidecar.alerts.maxTotalRetries }} + - name: REQ_RETRY_TOTAL + value: "{{ .Values.sidecar.alerts.maxTotalRetries }}" + {{- end }} + {{- if .Values.sidecar.alerts.maxConnectRetries }} + - name: REQ_RETRY_CONNECT + value: "{{ .Values.sidecar.alerts.maxConnectRetries }}" + {{- end }} + {{- if .Values.sidecar.alerts.maxReadRetries }} + - name: REQ_RETRY_READ + value: "{{ .Values.sidecar.alerts.maxReadRetries }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-alerts-volume + mountPath: "/etc/grafana/provisioning/alerting" + {{- with .Values.sidecar.alerts.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} +{{- end}} +{{- if .Values.sidecar.dashboards.enabled }} + - name: {{ include "grafana.name" . }}-sc-dashboard + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.dashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.sidecar.dashboards.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- if .Values.sidecar.dashboards.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.dashboards.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.dashboards.label }}" + {{- with .Values.sidecar.dashboards.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} + {{- end }} + - name: FOLDER + value: "{{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }}" + - name: RESOURCE + value: {{ quote .Values.sidecar.dashboards.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.dashboards.searchNamespace }} + - name: NAMESPACE + value: "{{ tpl (. | join ",") $root }}" + {{- end }} + {{- with .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.dashboards.folderAnnotation }} + - name: FOLDER_ANNOTATION + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.dashboards.script }} + - name: SCRIPT + value: "{{ . }}" + {{- end }} + {{- if not .Values.sidecar.dashboards.skipReload }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + - name: REQ_URL + value: {{ .Values.sidecar.dashboards.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.dashboards.watchServerTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchServerTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.dashboards.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.dashboards.watchClientTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchClientTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: {{ .Values.sidecar.dashboards.watchClientTimeout | quote }} + {{- end }} + {{- if .Values.sidecar.dashboards.maxTotalRetries }} + - name: REQ_RETRY_TOTAL + value: "{{ .Values.sidecar.dashboards.maxTotalRetries }}" + {{- end }} + {{- if .Values.sidecar.dashboards.maxConnectRetries }} + - name: REQ_RETRY_CONNECT + value: "{{ .Values.sidecar.dashboards.maxConnectRetries }}" + {{- end }} + {{- if .Values.sidecar.dashboards.maxReadRetries }} + - name: REQ_RETRY_READ + value: "{{ .Values.sidecar.dashboards.maxReadRetries }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} + {{- with .Values.sidecar.dashboards.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} +{{- end}} +{{- if and .Values.sidecar.datasources.enabled (not .Values.sidecar.datasources.initDatasources) }} + - name: {{ include "grafana.name" . }}-sc-datasources + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.sidecar.datasources.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.datasources.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- with .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.datasources.searchNamespace }} + - name: NAMESPACE + value: "{{ tpl (. | join ",") $root }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.datasources.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.datasources.script }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.datasources.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.datasources.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.datasources.watchServerTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchServerTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.datasources.watchClientTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchClientTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchClientTimeout }}" + {{- end }} + {{- if .Values.sidecar.datasources.maxTotalRetries }} + - name: REQ_RETRY_TOTAL + value: "{{ .Values.sidecar.datasources.maxTotalRetries }}" + {{- end }} + {{- if .Values.sidecar.datasources.maxConnectRetries }} + - name: REQ_RETRY_CONNECT + value: "{{ .Values.sidecar.datasources.maxConnectRetries }}" + {{- end }} + {{- if .Values.sidecar.datasources.maxReadRetries }} + - name: REQ_RETRY_READ + value: "{{ .Values.sidecar.datasources.maxReadRetries }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" + {{- with .Values.sidecar.datasources.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} +{{- end}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: {{ include "grafana.name" . }}-sc-notifiers + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.notifiers.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.notifiers.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.notifiers.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.notifiers.label }}" + {{- with .Values.sidecar.notifiers.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/notifiers" + - name: RESOURCE + value: {{ quote .Values.sidecar.notifiers.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- with .Values.sidecar.notifiers.searchNamespace }} + - name: NAMESPACE + value: "{{ tpl (. | join ",") $root }}" + {{- end }} + {{- with .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ . }}" + {{- end }} + {{- if .Values.sidecar.notifiers.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.notifiers.script }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.notifiers.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.notifiers.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.notifiers.watchServerTimeout }} + {{- if ne .Values.sidecar.notifiers.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.notifiers.watchServerTimeout with .Values.sidecar.notifiers.watchMethod %s" .Values.sidecar.notifiers.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.notifiers.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.notifiers.watchClientTimeout }} + {{- if ne .Values.sidecar.notifiers.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.notifiers.watchClientTimeout with .Values.sidecar.notifiers.watchMethod %s" .Values.sidecar.notifiers.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.notifiers.watchClientTimeout }}" + {{- end }} + {{- if .Values.sidecar.notifiers.maxTotalRetries }} + - name: REQ_RETRY_TOTAL + value: "{{ .Values.sidecar.notifiers.maxTotalRetries }}" + {{- end }} + {{- if .Values.sidecar.notifiers.maxConnectRetries }} + - name: REQ_RETRY_CONNECT + value: "{{ .Values.sidecar.notifiers.maxConnectRetries }}" + {{- end }} + {{- if .Values.sidecar.notifiers.maxReadRetries }} + - name: REQ_RETRY_READ + value: "{{ .Values.sidecar.notifiers.maxReadRetries }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" + {{- with .Values.sidecar.notifiers.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} +{{- end}} +{{- if .Values.sidecar.plugins.enabled }} + - name: {{ include "grafana.name" . }}-sc-plugins + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.plugins.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.plugins.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.plugins.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.plugins.label }}" + {{- if .Values.sidecar.plugins.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.plugins.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/plugins" + - name: RESOURCE + value: {{ quote .Values.sidecar.plugins.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.plugins.searchNamespace }} + - name: NAMESPACE + value: "{{ tpl (. | join ",") $root }}" + {{- end }} + {{- with .Values.sidecar.plugins.script }} + - name: SCRIPT + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ . }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.plugins.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.plugins.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.plugins.watchServerTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchServerTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.plugins.watchClientTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchClientTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchClientTimeout }}" + {{- end }} + {{- if .Values.sidecar.plugins.maxTotalRetries }} + - name: REQ_RETRY_TOTAL + value: "{{ .Values.sidecar.plugins.maxTotalRetries }}" + {{- end }} + {{- if .Values.sidecar.plugins.maxConnectRetries }} + - name: REQ_RETRY_CONNECT + value: "{{ .Values.sidecar.plugins.maxConnectRetries }}" + {{- end }} + {{- if .Values.sidecar.plugins.maxReadRetries }} + - name: REQ_RETRY_READ + value: "{{ .Values.sidecar.plugins.maxReadRetries }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" + {{- with .Values.sidecar.plugins.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} +{{- end}} + - name: {{ .Chart.Name }} + {{- $registry := .Values.global.imageRegistry | default .Values.image.registry -}} + {{- if .Values.image.sha }} + image: "{{ $registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}@sha256:{{ .Values.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.command }} + command: + {{- range .Values.command }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- if .Values.args }} + args: + {{- range .Values.args }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/grafana.ini" + subPath: grafana.ini + {{- if .Values.ldap.enabled }} + - name: ldap + mountPath: "/etc/grafana/ldap.toml" + subPath: ldap.toml + {{- end }} + {{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + mountPath: {{ tpl .mountPath $root }} + subPath: {{ tpl (.subPath | default "") $root }} + readOnly: {{ .readOnly }} + {{- end }} + - name: storage + mountPath: "/var/lib/grafana" + {{- with .Values.persistence.subPath }} + subPath: {{ tpl . $root }} + {{- end }} + {{- with .Values.dashboards }} + {{- range $provider, $dashboards := . }} + {{- range $key, $value := $dashboards }} + {{- if (or (hasKey $value "json") (hasKey $value "file")) }} + - name: dashboards-{{ $provider }} + mountPath: "/var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json" + subPath: "{{ $key }}.json" + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.dashboardsConfigMaps }} + {{- range (keys . | sortAlpha) }} + - name: dashboards-{{ . }} + mountPath: "/var/lib/grafana/dashboards/{{ . }}" + {{- end }} + {{- end }} + {{- with .Values.datasources }} + {{- $datasources := . }} + {{- range (keys . | sortAlpha) }} + {{- if (or (hasKey (index $datasources .) "secret")) }} {{/*check if current datasource should be handeled as secret */}} + - name: config-secret + mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" + subPath: {{ . | quote }} + {{- else }} + - name: config + mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" + subPath: {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.notifiers }} + {{- $notifiers := . }} + {{- range (keys . | sortAlpha) }} + {{- if (or (hasKey (index $notifiers .) "secret")) }} {{/*check if current notifier should be handeled as secret */}} + - name: config-secret + mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" + subPath: {{ . | quote }} + {{- else }} + - name: config + mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" + subPath: {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.alerting }} + {{- $alertingmap := .}} + {{- range (keys . | sortAlpha) }} + {{- if (or (hasKey (index $.Values.alerting .) "secret") (hasKey (index $.Values.alerting .) "secretFile")) }} {{/*check if current alerting entry should be handeled as secret */}} + - name: config-secret + mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" + subPath: {{ . | quote }} + {{- else }} + - name: config + mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" + subPath: {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.dashboardProviders }} + {{- range (keys . | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/dashboards/{{ . }}" + subPath: {{ . | quote }} + {{- end }} + {{- end }} + {{- with .Values.sidecar.alerts.enabled }} + - name: sc-alerts-volume + mountPath: "/etc/grafana/provisioning/alerting" + {{- end}} + {{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} + {{- if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" + subPath: provider.yaml + {{- end}} + {{- end}} + {{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" + {{- end}} + {{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" + {{- end}} + {{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" + {{- end}} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + subPath: {{ .subPath | default "" }} + {{- end }} + {{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + ports: + - name: {{ .Values.podPortName }} + containerPort: {{ .Values.service.targetPort }} + protocol: TCP + - name: {{ .Values.gossipPortName }}-tcp + containerPort: 9094 + protocol: TCP + - name: {{ .Values.gossipPortName }}-udp + containerPort: 9094 + protocol: UDP + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if .Values.plugins }} + - name: GF_INSTALL_PLUGINS + valueFrom: + configMapKeyRef: + name: {{ include "grafana.fullname" . }} + key: plugins + {{- end }} + {{- if .Values.smtp.existingSecret }} + - name: GF_SMTP_USER + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.userKey | default "user" }} + - name: GF_SMTP_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.passwordKey | default "password" }} + {{- end }} + {{- if .Values.imageRenderer.enabled }} + - name: GF_RENDERING_SERVER_URL + {{- if .Values.imageRenderer.serverURL }} + value: {{ .Values.imageRenderer.serverURL | quote }} + {{- else }} + value: http://{{ include "grafana.fullname" . }}-image-renderer.{{ include "grafana.namespace" . }}:{{ .Values.imageRenderer.service.port }}/render + {{- end }} + - name: GF_RENDERING_CALLBACK_URL + {{- if .Values.imageRenderer.renderingCallbackURL }} + value: {{ .Values.imageRenderer.renderingCallbackURL | quote }} + {{- else }} + value: {{ .Values.imageRenderer.grafanaProtocol }}://{{ include "grafana.fullname" . }}.{{ include "grafana.namespace" . }}:{{ .Values.service.port }}/{{ .Values.imageRenderer.grafanaSubPath }} + {{- end }} + {{- end }} + - name: GF_PATHS_DATA + value: {{ (get .Values "grafana.ini").paths.data }} + - name: GF_PATHS_LOGS + value: {{ (get .Values "grafana.ini").paths.logs }} + - name: GF_PATHS_PLUGINS + value: {{ (get .Values "grafana.ini").paths.plugins }} + - name: GF_PATHS_PROVISIONING + value: {{ (get .Values "grafana.ini").paths.provisioning }} + {{- range $key, $value := .Values.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- range $key, $value := .Values.env }} + - name: "{{ tpl $key $ }}" + value: "{{ tpl (print $value) $ }}" + {{- end }} + {{- if or .Values.envFromSecret (or .Values.envRenderSecret .Values.envFromSecrets) .Values.envFromConfigMaps }} + envFrom: + {{- if .Values.envFromSecret }} + - secretRef: + name: {{ tpl .Values.envFromSecret . }} + {{- end }} + {{- if .Values.envRenderSecret }} + - secretRef: + name: {{ include "grafana.fullname" . }}-env + {{- end }} + {{- range .Values.envFromSecrets }} + - secretRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- if .prefix }} + prefix: {{ tpl .prefix $ }} + {{- end }} + {{- end }} + {{- range .Values.envFromConfigMaps }} + - configMapRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- if .prefix }} + prefix: {{ tpl .prefix $ }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.lifecycleHooks }} + lifecycle: + {{- tpl (toYaml .) $root | nindent 6 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- with .Values.extraContainers }} + {{- tpl . $ | nindent 2 }} +{{- end }} +{{- with .Values.nodeSelector }} +nodeSelector: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.affinity }} +affinity: + {{- tpl (toYaml .) $root | nindent 2 }} +{{- end }} +{{- with .Values.topologySpreadConstraints }} +topologySpreadConstraints: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.tolerations }} +tolerations: + {{- toYaml . | nindent 2 }} +{{- end }} +volumes: + - name: config + configMap: + name: {{ include "grafana.fullname" . }} + {{- $createConfigSecret := eq (include "grafana.shouldCreateConfigSecret" .) "true" -}} + {{- if and .Values.createConfigmap $createConfigSecret }} + - name: config-secret + secret: + secretName: {{ include "grafana.fullname" . }}-config-secret + {{- end }} + {{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + configMap: + name: {{ tpl .configMap $root }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- with .items }} + items: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.dashboards }} + {{- range (keys .Values.dashboards | sortAlpha) }} + - name: dashboards-{{ . }} + configMap: + name: {{ include "grafana.fullname" $ }}-dashboards-{{ . }} + {{- end }} + {{- end }} + {{- if .Values.dashboardsConfigMaps }} + {{- range $provider, $name := .Values.dashboardsConfigMaps }} + - name: dashboards-{{ $provider }} + configMap: + name: {{ tpl $name $root }} + {{- end }} + {{- end }} + {{- if .Values.ldap.enabled }} + - name: ldap + secret: + {{- if .Values.ldap.existingSecret }} + secretName: {{ .Values.ldap.existingSecret }} + {{- else }} + secretName: {{ include "grafana.fullname" . }} + {{- end }} + items: + - key: ldap-toml + path: ldap.toml + {{- end }} + {{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} + - name: storage + persistentVolumeClaim: + claimName: {{ tpl (.Values.persistence.existingClaim | default (include "grafana.fullname" .)) . }} + {{- else if and .Values.persistence.enabled (has .Values.persistence.type $sts) }} + {{/* nothing */}} + {{- else }} + - name: storage + {{- if .Values.persistence.inMemory.enabled }} + emptyDir: + medium: Memory + {{- with .Values.persistence.inMemory.sizeLimit }} + sizeLimit: {{ . }} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + {{- if .Values.sidecar.alerts.enabled }} + - name: sc-alerts-volume + emptyDir: + {{- with .Values.sidecar.alerts.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume + emptyDir: + {{- with .Values.sidecar.dashboards.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + configMap: + name: {{ include "grafana.fullname" . }}-config-dashboards + {{- end }} + {{- end }} + {{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume + emptyDir: + {{- with .Values.sidecar.datasources.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume + emptyDir: + {{- with .Values.sidecar.plugins.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume + emptyDir: + {{- with .Values.sidecar.notifiers.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- range .Values.extraSecretMounts }} + {{- if .secretName }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + defaultMode: {{ .defaultMode }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- with .items }} + items: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- else if .projected }} + - name: {{ .name }} + projected: + {{- toYaml .projected | nindent 6 }} + {{- else if .csi }} + - name: {{ .name }} + csi: + {{- toYaml .csi | nindent 6 }} + {{- end }} + {{- end }} + {{- range .Values.extraVolumes }} + - name: {{ .name }} + {{- if .existingClaim }} + persistentVolumeClaim: + claimName: {{ .existingClaim }} + {{- else if .hostPath }} + hostPath: + {{ toYaml .hostPath | nindent 6 }} + {{- else if .csi }} + csi: + {{- toYaml .csi | nindent 6 }} + {{- else if .configMap }} + configMap: + {{- toYaml .configMap | nindent 6 }} + {{- else if .emptyDir }} + emptyDir: + {{- toYaml .emptyDir | nindent 6 }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} + {{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + emptyDir: {} + {{- end }} + {{- with .Values.extraContainerVolumes }} + {{- tpl (toYaml .) $root | nindent 2 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/clusterrole.yaml b/utils/assets/charts/grafana/templates/clusterrole.yaml new file mode 100644 index 0000000..3af4b62 --- /dev/null +++ b/utils/assets/charts/grafana/templates/clusterrole.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) (not .Values.rbac.useExistingClusterRole) }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "grafana.fullname" . }}-clusterrole +{{- if or .Values.sidecar.dashboards.enabled .Values.rbac.extraClusterRoleRules .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled .Values.sidecar.alerts.enabled }} +rules: + {{- if or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled .Values.sidecar.alerts.enabled }} + - apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] + {{- end}} + {{- with .Values.rbac.extraClusterRoleRules }} + {{- toYaml . | nindent 2 }} + {{- end}} +{{- else }} +rules: [] +{{- end}} +{{- end}} diff --git a/utils/assets/charts/grafana/templates/clusterrolebinding.yaml b/utils/assets/charts/grafana/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..bda9431 --- /dev/null +++ b/utils/assets/charts/grafana/templates/clusterrolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "grafana.fullname" . }}-clusterrolebinding + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + name: {{ include "grafana.serviceAccountName" . }} + namespace: {{ include "grafana.namespace" . }} +roleRef: + kind: ClusterRole + {{- if .Values.rbac.useExistingClusterRole }} + name: {{ .Values.rbac.useExistingClusterRole }} + {{- else }} + name: {{ include "grafana.fullname" . }}-clusterrole + {{- end }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/utils/assets/charts/grafana/templates/configSecret.yaml b/utils/assets/charts/grafana/templates/configSecret.yaml new file mode 100644 index 0000000..55574b9 --- /dev/null +++ b/utils/assets/charts/grafana/templates/configSecret.yaml @@ -0,0 +1,43 @@ +{{- $createConfigSecret := eq (include "grafana.shouldCreateConfigSecret" .) "true" -}} +{{- if and .Values.createConfigmap $createConfigSecret }} +{{- $files := .Files }} +{{- $root := . -}} +apiVersion: v1 +kind: Secret +metadata: + name: "{{ include "grafana.fullname" . }}-config-secret" + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: +{{- range $key, $value := .Values.alerting }} + {{- if (hasKey $value "secretFile") }} + {{- $key | nindent 2 }}: + {{- toYaml ( $files.Get $value.secretFile ) | b64enc | nindent 4}} + {{/* as of https://helm.sh/docs/chart_template_guide/accessing_files/ this will only work if you fork this chart and add files to it*/}} + {{- end }} +{{- end }} +stringData: +{{- range $key, $value := .Values.datasources }} +{{- if (hasKey $value "secret") }} +{{- $key | nindent 2 }}: | + {{- tpl (toYaml $value.secret | nindent 4) $root }} +{{- end }} +{{- end }} +{{- range $key, $value := .Values.notifiers }} +{{- if (hasKey $value "secret") }} +{{- $key | nindent 2 }}: | + {{- tpl (toYaml $value.secret | nindent 4) $root }} +{{- end }} +{{- end }} +{{- range $key, $value := .Values.alerting }} +{{ if (hasKey $value "secret") }} + {{- $key | nindent 2 }}: | + {{- tpl (toYaml $value.secret | nindent 4) $root }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/configmap-dashboard-provider.yaml b/utils/assets/charts/grafana/templates/configmap-dashboard-provider.yaml new file mode 100644 index 0000000..b412c4d --- /dev/null +++ b/utils/assets/charts/grafana/templates/configmap-dashboard-provider.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.sidecar.dashboards.enabled .Values.sidecar.dashboards.SCProvider }} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "grafana.fullname" . }}-config-dashboards + namespace: {{ include "grafana.namespace" . }} +data: + {{- include "grafana.configDashboardProviderData" . | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/configmap.yaml b/utils/assets/charts/grafana/templates/configmap.yaml new file mode 100644 index 0000000..0a2edf4 --- /dev/null +++ b/utils/assets/charts/grafana/templates/configmap.yaml @@ -0,0 +1,20 @@ +{{- if .Values.createConfigmap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- if or .Values.configMapAnnotations .Values.annotations }} + annotations: + {{- with .Values.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.configMapAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +data: + {{- include "grafana.configData" . | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/dashboards-json-configmap.yaml b/utils/assets/charts/grafana/templates/dashboards-json-configmap.yaml new file mode 100644 index 0000000..df0ed0d --- /dev/null +++ b/utils/assets/charts/grafana/templates/dashboards-json-configmap.yaml @@ -0,0 +1,35 @@ +{{- if .Values.dashboards }} +{{ $files := .Files }} +{{- range $provider, $dashboards := .Values.dashboards }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "grafana.fullname" $ }}-dashboards-{{ $provider }} + namespace: {{ include "grafana.namespace" $ }} + labels: + {{- include "grafana.labels" $ | nindent 4 }} + dashboard-provider: {{ $provider }} +{{- if $dashboards }} +data: +{{- $dashboardFound := false }} +{{- range $key, $value := $dashboards }} +{{- if (or (hasKey $value "json") (hasKey $value "file")) }} +{{- $dashboardFound = true }} + {{- print $key | nindent 2 }}.json: + {{- if hasKey $value "json" }} + |- + {{- $value.json | nindent 6 }} + {{- end }} + {{- if hasKey $value "file" }} + {{- toYaml ( $files.Get $value.file ) | nindent 4}} + {{- end }} +{{- end }} +{{- end }} +{{- if not $dashboardFound }} + {} +{{- end }} +{{- end }} +--- +{{- end }} + +{{- end }} diff --git a/utils/assets/charts/grafana/templates/deployment.yaml b/utils/assets/charts/grafana/templates/deployment.yaml new file mode 100644 index 0000000..7bf7521 --- /dev/null +++ b/utils/assets/charts/grafana/templates/deployment.yaml @@ -0,0 +1,53 @@ +{{- if (and (not .Values.useStatefulSet) (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc"))) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if (not .Values.autoscaling.enabled) }} + replicas: {{ .Values.replicas }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + {{- with .Values.deploymentStrategy }} + strategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + labels: + {{- include "grafana.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + checksum/config: {{ include "grafana.configData" . | sha256sum }} + {{- if .Values.dashboards }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + {{- end }} + checksum/sc-dashboard-provider-config: {{ include "grafana.configDashboardProviderData" . | sha256sum }} + {{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include "grafana.secretsData" . | sha256sum }} + {{- end }} + {{- if .Values.envRenderSecret }} + checksum/secret-env: {{ tpl (toYaml .Values.envRenderSecret) . | sha256sum }} + {{- end }} + kubectl.kubernetes.io/default-container: {{ .Chart.Name }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include "grafana.pod" . | nindent 6 }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/extra-manifests.yaml b/utils/assets/charts/grafana/templates/extra-manifests.yaml new file mode 100644 index 0000000..a9bb3b6 --- /dev/null +++ b/utils/assets/charts/grafana/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraObjects }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/utils/assets/charts/grafana/templates/headless-service.yaml b/utils/assets/charts/grafana/templates/headless-service.yaml new file mode 100644 index 0000000..3028589 --- /dev/null +++ b/utils/assets/charts/grafana/templates/headless-service.yaml @@ -0,0 +1,22 @@ +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} +{{- if or .Values.headlessService (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (has .Values.persistence.type $sts)) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "grafana.fullname" . }}-headless + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + clusterIP: None + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} + type: ClusterIP + ports: + - name: {{ .Values.gossipPortName }}-tcp + port: 9094 +{{- end }} diff --git a/utils/assets/charts/grafana/templates/hpa.yaml b/utils/assets/charts/grafana/templates/hpa.yaml new file mode 100644 index 0000000..d9624b2 --- /dev/null +++ b/utils/assets/charts/grafana/templates/hpa.yaml @@ -0,0 +1,51 @@ +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} +{{- if .Values.autoscaling.enabled }} +apiVersion: {{ include "grafana.hpa.apiVersion" . }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + app.kubernetes.io/name: {{ include "grafana.name" . }} + helm.sh/chart: {{ include "grafana.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + {{- if has .Values.persistence.type $sts }} + kind: StatefulSet + {{- else }} + kind: Deployment + {{- end }} + name: {{ include "grafana.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ .Values.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemory }} + {{- end }} + {{- end }} + {{- if .Values.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ .Values.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPU }} + {{- end }} + {{- end }} + {{- if .Values.autoscaling.behavior }} + behavior: {{ toYaml .Values.autoscaling.behavior | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/image-renderer-deployment.yaml b/utils/assets/charts/grafana/templates/image-renderer-deployment.yaml new file mode 100644 index 0000000..4828aa3 --- /dev/null +++ b/utils/assets/charts/grafana/templates/image-renderer-deployment.yaml @@ -0,0 +1,199 @@ +{{ if .Values.imageRenderer.enabled }} +{{- $root := . -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "grafana.fullname" . }}-image-renderer + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} + {{- with .Values.imageRenderer.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.imageRenderer.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and (not .Values.imageRenderer.autoscaling.enabled) (.Values.imageRenderer.replicas) }} + replicas: {{ .Values.imageRenderer.replicas }} + {{- end }} + revisionHistoryLimit: {{ .Values.imageRenderer.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + + {{- with .Values.imageRenderer.deploymentStrategy }} + strategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + template: + metadata: + labels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} + {{- with .Values.imageRenderer.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- with .Values.imageRenderer.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imageRenderer.schedulerName }} + schedulerName: "{{ . }}" + {{- end }} + {{- with .Values.imageRenderer.serviceAccountName }} + serviceAccountName: "{{ . }}" + {{- end }} + {{- with .Values.imageRenderer.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imageRenderer.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imageRenderer.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.imageRenderer.image.pullSecrets }} + imagePullSecrets: + {{- range . }} + - name: {{ tpl . $root }} + {{- end}} + {{- end }} + containers: + - name: {{ .Chart.Name }}-image-renderer + {{- $registry := .Values.global.imageRegistry | default .Values.imageRenderer.image.registry -}} + {{- if .Values.imageRenderer.image.sha }} + image: "{{ $registry }}/{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} + {{- if .Values.imageRenderer.command }} + command: + {{- range .Values.imageRenderer.command }} + - {{ . }} + {{- end }} + {{- end}} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + containerPort: {{ .Values.imageRenderer.service.targetPort }} + protocol: TCP + livenessProbe: + httpGet: + path: / + port: {{ .Values.imageRenderer.service.portName }} + env: + - name: HTTP_PORT + value: {{ .Values.imageRenderer.service.targetPort | quote }} + {{- if .Values.imageRenderer.serviceMonitor.enabled }} + - name: ENABLE_METRICS + value: "true" + {{- end }} + {{- range $key, $value := .Values.imageRenderer.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 16 }} + {{- end }} + {{- range $key, $value := .Values.imageRenderer.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + {{- with .Values.imageRenderer.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - mountPath: /tmp + name: image-renderer-tmpfs + {{- range .Values.imageRenderer.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + mountPath: {{ tpl .mountPath $root }} + subPath: {{ tpl (.subPath | default "") $root }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.imageRenderer.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + subPath: {{ .subPath | default "" }} + {{- end }} + {{- range .Values.imageRenderer.extraVolumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + {{- with .Values.imageRenderer.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.imageRenderer.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.imageRenderer.affinity }} + affinity: + {{- tpl (toYaml .) $root | nindent 8 }} + {{- end }} + {{- with .Values.imageRenderer.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: image-renderer-tmpfs + emptyDir: {} + {{- range .Values.imageRenderer.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + configMap: + name: {{ tpl .configMap $root }} + {{- with .items }} + items: + {{- toYaml . | nindent 14 }} + {{- end }} + {{- end }} + {{- range .Values.imageRenderer.extraSecretMounts }} + {{- if .secretName }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + defaultMode: {{ .defaultMode }} + {{- with .items }} + items: + {{- toYaml . | nindent 14 }} + {{- end }} + {{- else if .projected }} + - name: {{ .name }} + projected: + {{- toYaml .projected | nindent 12 }} + {{- else if .csi }} + - name: {{ .name }} + csi: + {{- toYaml .csi | nindent 12 }} + {{- end }} + {{- end }} + {{- range .Values.imageRenderer.extraVolumes }} + - name: {{ .name }} + {{- if .existingClaim }} + persistentVolumeClaim: + claimName: {{ .existingClaim }} + {{- else if .hostPath }} + hostPath: + {{ toYaml .hostPath | nindent 12 }} + {{- else if .csi }} + csi: + {{- toYaml .csi | nindent 12 }} + {{- else if .configMap }} + configMap: + {{- toYaml .configMap | nindent 12 }} + {{- else if .emptyDir }} + emptyDir: + {{- toYaml .emptyDir | nindent 12 }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/image-renderer-hpa.yaml b/utils/assets/charts/grafana/templates/image-renderer-hpa.yaml new file mode 100644 index 0000000..d992f62 --- /dev/null +++ b/utils/assets/charts/grafana/templates/image-renderer-hpa.yaml @@ -0,0 +1,46 @@ +{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.autoscaling.enabled }} +apiVersion: {{ include "grafana.hpa.apiVersion" . }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "grafana.fullname" . }}-image-renderer + namespace: {{ include "grafana.namespace" . }} + labels: + app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer + helm.sh/chart: {{ include "grafana.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "grafana.fullname" . }}-image-renderer + minReplicas: {{ .Values.imageRenderer.autoscaling.minReplicas }} + maxReplicas: {{ .Values.imageRenderer.autoscaling.maxReplicas }} + metrics: + {{- if .Values.imageRenderer.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ .Values.imageRenderer.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.imageRenderer.autoscaling.targetMemory }} + {{- end }} + {{- end }} + {{- if .Values.imageRenderer.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ .Values.imageRenderer.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.imageRenderer.autoscaling.targetCPU }} + {{- end }} + {{- end }} + {{- if .Values.imageRenderer.autoscaling.behavior }} + behavior: {{ toYaml .Values.imageRenderer.autoscaling.behavior | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/image-renderer-network-policy.yaml b/utils/assets/charts/grafana/templates/image-renderer-network-policy.yaml new file mode 100644 index 0000000..bcbd249 --- /dev/null +++ b/utils/assets/charts/grafana/templates/image-renderer-network-policy.yaml @@ -0,0 +1,79 @@ +{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.networkPolicy.limitIngress }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "grafana.fullname" . }}-image-renderer-ingress + namespace: {{ include "grafana.namespace" . }} + annotations: + comment: Limit image-renderer ingress traffic from grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- with .Values.imageRenderer.podLabels }} + {{- toYaml . | nindent 6 }} + {{- end }} + + policyTypes: + - Ingress + ingress: + - ports: + - port: {{ .Values.imageRenderer.service.targetPort }} + protocol: TCP + from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ include "grafana.namespace" . }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 14 }} + {{- end }} + {{- with .Values.imageRenderer.networkPolicy.extraIngressSelectors -}} + {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} + +{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.networkPolicy.limitEgress }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "grafana.fullname" . }}-image-renderer-egress + namespace: {{ include "grafana.namespace" . }} + annotations: + comment: Limit image-renderer egress traffic to grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- with .Values.imageRenderer.podLabels }} + {{- toYaml . | nindent 6 }} + {{- end }} + + policyTypes: + - Egress + egress: + # allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # talk only to grafana + - ports: + - port: {{ .Values.service.targetPort }} + protocol: TCP + to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ include "grafana.namespace" . }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 14 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/image-renderer-service.yaml b/utils/assets/charts/grafana/templates/image-renderer-service.yaml new file mode 100644 index 0000000..f8da127 --- /dev/null +++ b/utils/assets/charts/grafana/templates/image-renderer-service.yaml @@ -0,0 +1,31 @@ +{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "grafana.fullname" . }}-image-renderer + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} + {{- with .Values.imageRenderer.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.imageRenderer.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + {{- with .Values.imageRenderer.service.clusterIP }} + clusterIP: {{ . }} + {{- end }} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + port: {{ .Values.imageRenderer.service.port }} + protocol: TCP + targetPort: {{ .Values.imageRenderer.service.targetPort }} + {{- with .Values.imageRenderer.appProtocol }} + appProtocol: {{ . }} + {{- end }} + selector: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/image-renderer-servicemonitor.yaml b/utils/assets/charts/grafana/templates/image-renderer-servicemonitor.yaml new file mode 100644 index 0000000..5d9f09d --- /dev/null +++ b/utils/assets/charts/grafana/templates/image-renderer-servicemonitor.yaml @@ -0,0 +1,48 @@ +{{- if .Values.imageRenderer.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "grafana.fullname" . }}-image-renderer + {{- if .Values.imageRenderer.serviceMonitor.namespace }} + namespace: {{ tpl .Values.imageRenderer.serviceMonitor.namespace . }} + {{- else }} + namespace: {{ include "grafana.namespace" . }} + {{- end }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} + {{- with .Values.imageRenderer.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.imageRenderer.service.portName }} + {{- with .Values.imageRenderer.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.imageRenderer.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + honorLabels: true + path: {{ .Values.imageRenderer.serviceMonitor.path }} + scheme: {{ .Values.imageRenderer.serviceMonitor.scheme }} + {{- with .Values.imageRenderer.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.imageRenderer.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + jobLabel: "{{ .Release.Name }}-image-renderer" + selector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ include "grafana.namespace" . }} + {{- with .Values.imageRenderer.serviceMonitor.targetLabels }} + targetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/ingress.yaml b/utils/assets/charts/grafana/templates/ingress.yaml new file mode 100644 index 0000000..b2ffd81 --- /dev/null +++ b/utils/assets/charts/grafana/templates/ingress.yaml @@ -0,0 +1,78 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "grafana.ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "grafana.ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "grafana.ingress.supportsPathType" .) "true" -}} +{{- $fullName := include "grafana.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +{{- $ingressPathType := .Values.ingress.pathType -}} +{{- $extraPaths := .Values.ingress.extraPaths -}} +apiVersion: {{ include "grafana.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingress.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} + ingressClassName: {{ .Values.ingress.ingressClassName }} + {{- end -}} + {{- with .Values.ingress.tls }} + tls: + {{- tpl (toYaml .) $ | nindent 4 }} + {{- end }} + rules: + {{- if .Values.ingress.hosts }} + {{- range .Values.ingress.hosts }} + - host: {{ tpl . $ | quote }} + http: + paths: + {{- with $extraPaths }} + {{- toYaml . | nindent 10 }} + {{- end }} + - path: {{ $ingressPath }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} + {{- else }} + - http: + paths: + - backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- with $ingressPath }} + path: {{ . }} + {{- end }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + {{- end -}} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/networkpolicy.yaml b/utils/assets/charts/grafana/templates/networkpolicy.yaml new file mode 100644 index 0000000..4cd3ed6 --- /dev/null +++ b/utils/assets/charts/grafana/templates/networkpolicy.yaml @@ -0,0 +1,61 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + policyTypes: + {{- if .Values.networkPolicy.ingress }} + - Ingress + {{- end }} + {{- if .Values.networkPolicy.egress.enabled }} + - Egress + {{- end }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + + {{- if .Values.networkPolicy.egress.enabled }} + egress: + {{- if not .Values.networkPolicy.egress.blockDNSResolution }} + - ports: + - port: 53 + protocol: UDP + {{- end }} + - ports: + {{ .Values.networkPolicy.egress.ports | toJson }} + {{- with .Values.networkPolicy.egress.to }} + to: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.ingress }} + ingress: + - ports: + - port: {{ .Values.service.targetPort }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ include "grafana.fullname" . }}-client: "true" + {{- with .Values.networkPolicy.explicitNamespacesSelector }} + - namespaceSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + - podSelector: + matchLabels: + {{- include "grafana.labels" . | nindent 14 }} + role: read + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/poddisruptionbudget.yaml b/utils/assets/charts/grafana/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..0525121 --- /dev/null +++ b/utils/assets/charts/grafana/templates/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if .Values.podDisruptionBudget }} +apiVersion: {{ include "grafana.podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ . }} + {{- end }} + {{- with .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/podsecuritypolicy.yaml b/utils/assets/charts/grafana/templates/podsecuritypolicy.yaml new file mode 100644 index 0000000..eed7af9 --- /dev/null +++ b/utils/assets/charts/grafana/templates/podsecuritypolicy.yaml @@ -0,0 +1,49 @@ +{{- if and .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "grafana.fullname" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.rbac.pspUseAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + # Default set from Docker, with DAC_OVERRIDE and CHOWN + - ALL + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'csi' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/utils/assets/charts/grafana/templates/pvc.yaml b/utils/assets/charts/grafana/templates/pvc.yaml new file mode 100644 index 0000000..d1c4b2d --- /dev/null +++ b/utils/assets/charts/grafana/templates/pvc.yaml @@ -0,0 +1,39 @@ +{{- if and (not .Values.useStatefulSet) .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "pvc")}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.persistence.extraPvcLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.persistence.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.persistence.finalizers }} + finalizers: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if and (.Values.persistence.lookupVolumeName) (lookup "v1" "PersistentVolumeClaim" (include "grafana.namespace" .) (include "grafana.fullname" .)) }} + volumeName: {{ (lookup "v1" "PersistentVolumeClaim" (include "grafana.namespace" .) (include "grafana.fullname" .)).spec.volumeName }} + {{- end }} + {{- with .Values.persistence.storageClassName }} + storageClassName: {{ . }} + {{- end }} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/role.yaml b/utils/assets/charts/grafana/templates/role.yaml new file mode 100644 index 0000000..4b5edd9 --- /dev/null +++ b/utils/assets/charts/grafana/templates/role.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if or .Values.rbac.pspEnabled (and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled .Values.rbac.extraRoleRules)) }} +rules: + {{- if and .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} + - apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ include "grafana.fullname" . }}] + {{- end }} + {{- if and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled) }} + - apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- with .Values.rbac.extraRoleRules }} + {{- toYaml . | nindent 2 }} + {{- end}} +{{- else }} +rules: [] +{{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/rolebinding.yaml b/utils/assets/charts/grafana/templates/rolebinding.yaml new file mode 100644 index 0000000..58f77c6 --- /dev/null +++ b/utils/assets/charts/grafana/templates/rolebinding.yaml @@ -0,0 +1,25 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + {{- if .Values.rbac.useExistingRole }} + name: {{ .Values.rbac.useExistingRole }} + {{- else }} + name: {{ include "grafana.fullname" . }} + {{- end }} +subjects: +- kind: ServiceAccount + name: {{ include "grafana.serviceAccountName" . }} + namespace: {{ include "grafana.namespace" . }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/route.yaml b/utils/assets/charts/grafana/templates/route.yaml new file mode 100644 index 0000000..e8c98b3 --- /dev/null +++ b/utils/assets/charts/grafana/templates/route.yaml @@ -0,0 +1,44 @@ +{{- range $name, $route := .Values.route }} + {{- if $route.enabled -}} +--- +apiVersion: {{ $route.apiVersion | default "gateway.networking.k8s.io/v1" }} +kind: {{ $route.kind | default "HTTPRoute" }} +metadata: + {{- with $route.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ template "grafana.fullname" $ }}{{ if ne $name "main" }}-{{ $name }}{{ end }} + namespace: {{ template "grafana.namespace" $ }} + labels: + app: {{ template "grafana.name" $ }}-prometheus + {{- include "grafana.labels" $ | nindent 4 }} + {{- with $route.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with $route.parentRefs }} + parentRefs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $route.hostnames }} + hostnames: + {{- tpl (toYaml .) $ | nindent 4 }} + {{- end }} + rules: + {{- if $route.additionalRules }} + {{- tpl (toYaml $route.additionalRules) $ | nindent 4 }} + {{- end }} + - backendRefs: + - name: {{ include "grafana.fullname" $ }} + port: {{ $.Values.service.port }} + {{- with $route.filters }} + filters: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $route.matches }} + matches: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/grafana/templates/secret-env.yaml b/utils/assets/charts/grafana/templates/secret-env.yaml new file mode 100644 index 0000000..eb14aac --- /dev/null +++ b/utils/assets/charts/grafana/templates/secret-env.yaml @@ -0,0 +1,14 @@ +{{- if .Values.envRenderSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "grafana.fullname" . }}-env + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +type: Opaque +data: +{{- range $key, $val := .Values.envRenderSecret }} + {{ $key }}: {{ tpl ($val | toString) $ | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/secret.yaml b/utils/assets/charts/grafana/templates/secret.yaml new file mode 100644 index 0000000..fd2ca50 --- /dev/null +++ b/utils/assets/charts/grafana/templates/secret.yaml @@ -0,0 +1,16 @@ +{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- include "grafana.secretsData" . | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/service.yaml b/utils/assets/charts/grafana/templates/service.yaml new file mode 100644 index 0000000..022328c --- /dev/null +++ b/utils/assets/charts/grafana/templates/service.yaml @@ -0,0 +1,67 @@ +{{- if .Values.service.enabled }} +{{- $root := . }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.annotations }} + annotations: + {{- tpl (toYaml . | nindent 4) $root }} + {{- end }} +spec: + {{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} + type: ClusterIP + {{- with .Values.service.clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- else if eq .Values.service.type "LoadBalancer" }} + type: LoadBalancer + {{- with .Values.service.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- with .Values.service.loadBalancerClass }} + loadBalancerClass: {{ . }} + {{- end }} + {{- with .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- else }} + type: {{ .Values.service.type }} + {{- end }} + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + {{- with .Values.service.externalIPs }} + externalIPs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- end }} + ports: + - name: {{ .Values.service.portName }} + port: {{ .Values.service.port }} + protocol: TCP + targetPort: {{ .Values.service.targetPort }} + {{- with .Values.service.appProtocol }} + appProtocol: {{ . }} + {{- end }} + {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- with .Values.extraExposePorts }} + {{- tpl (toYaml . | nindent 4) $root }} + {{- end }} + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/serviceaccount.yaml b/utils/assets/charts/grafana/templates/serviceaccount.yaml new file mode 100644 index 0000000..ffca071 --- /dev/null +++ b/utils/assets/charts/grafana/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.serviceAccount.autoMount | default .Values.serviceAccount.automountServiceAccountToken }} +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} + name: {{ include "grafana.serviceAccountName" . }} + namespace: {{ include "grafana.namespace" . }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/servicemonitor.yaml b/utils/assets/charts/grafana/templates/servicemonitor.yaml new file mode 100644 index 0000000..0359013 --- /dev/null +++ b/utils/assets/charts/grafana/templates/servicemonitor.yaml @@ -0,0 +1,52 @@ +{{- if .Values.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "grafana.fullname" . }} + {{- if .Values.serviceMonitor.namespace }} + namespace: {{ tpl .Values.serviceMonitor.namespace . }} + {{- else }} + namespace: {{ include "grafana.namespace" . }} + {{- end }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.serviceMonitor.labels }} + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.service.portName }} + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + honorLabels: true + path: {{ .Values.serviceMonitor.path }} + scheme: {{ .Values.serviceMonitor.scheme }} + {{- with .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + jobLabel: "{{ .Release.Name }}" + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ include "grafana.namespace" . }} + {{- with .Values.serviceMonitor.targetLabels }} + targetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/statefulset.yaml b/utils/assets/charts/grafana/templates/statefulset.yaml new file mode 100644 index 0000000..896f810 --- /dev/null +++ b/utils/assets/charts/grafana/templates/statefulset.yaml @@ -0,0 +1,58 @@ +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} +{{- if (or (.Values.useStatefulSet) (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (has .Values.persistence.type $sts)))}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + serviceName: {{ include "grafana.fullname" . }}-headless + template: + metadata: + labels: + {{- include "grafana.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} + {{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- end }} + kubectl.kubernetes.io/default-container: {{ .Chart.Name }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- include "grafana.pod" . | nindent 6 }} + {{- if .Values.persistence.enabled}} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: storage + spec: + accessModes: {{ .Values.persistence.accessModes }} + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/tests/test-configmap.yaml b/utils/assets/charts/grafana/templates/tests/test-configmap.yaml new file mode 100644 index 0000000..5695df3 --- /dev/null +++ b/utils/assets/charts/grafana/templates/tests/test-configmap.yaml @@ -0,0 +1,20 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "grafana.fullname" . }}-test + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": {{ .Values.testFramework.hookType | default "test" }} + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + labels: + {{- include "grafana.labels" . | nindent 4 }} +data: + run.sh: |- + @test "Test Health" { + url="http://{{ include "grafana.fullname" . }}/api/health" + + code=$(wget --server-response --spider --timeout 90 --tries 10 ${url} 2>&1 | awk '/^ HTTP/{print $2}') + [ "$code" == "200" ] + } +{{- end }} diff --git a/utils/assets/charts/grafana/templates/tests/test-podsecuritypolicy.yaml b/utils/assets/charts/grafana/templates/tests/test-podsecuritypolicy.yaml new file mode 100644 index 0000000..549400a --- /dev/null +++ b/utils/assets/charts/grafana/templates/tests/test-podsecuritypolicy.yaml @@ -0,0 +1,32 @@ +{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "grafana.fullname" . }}-test + annotations: + "helm.sh/hook": {{ .Values.testFramework.hookType | default "test" }} + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + labels: + {{- include "grafana.labels" . | nindent 4 }} +spec: + allowPrivilegeEscalation: true + privileged: false + hostNetwork: false + hostIPC: false + hostPID: false + fsGroup: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + runAsUser: + rule: RunAsAny + volumes: + - configMap + - downwardAPI + - emptyDir + - projected + - csi + - secret +{{- end }} diff --git a/utils/assets/charts/grafana/templates/tests/test-role.yaml b/utils/assets/charts/grafana/templates/tests/test-role.yaml new file mode 100644 index 0000000..0f04c56 --- /dev/null +++ b/utils/assets/charts/grafana/templates/tests/test-role.yaml @@ -0,0 +1,17 @@ +{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "grafana.fullname" . }}-test + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": {{ .Values.testFramework.hookType | default "test" }} + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + labels: + {{- include "grafana.labels" . | nindent 4 }} +rules: + - apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ include "grafana.fullname" . }}-test] +{{- end }} diff --git a/utils/assets/charts/grafana/templates/tests/test-rolebinding.yaml b/utils/assets/charts/grafana/templates/tests/test-rolebinding.yaml new file mode 100644 index 0000000..811adb0 --- /dev/null +++ b/utils/assets/charts/grafana/templates/tests/test-rolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "grafana.fullname" . }}-test + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": {{ .Values.testFramework.hookType | default "test" }} + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + labels: + {{- include "grafana.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "grafana.fullname" . }}-test +subjects: + - kind: ServiceAccount + name: {{ include "grafana.serviceAccountNameTest" . }} + namespace: {{ include "grafana.namespace" . }} +{{- end }} diff --git a/utils/assets/charts/grafana/templates/tests/test-serviceaccount.yaml b/utils/assets/charts/grafana/templates/tests/test-serviceaccount.yaml new file mode 100644 index 0000000..2e5f322 --- /dev/null +++ b/utils/assets/charts/grafana/templates/tests/test-serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.testFramework.enabled .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} + name: {{ include "grafana.serviceAccountNameTest" . }} + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": {{ .Values.testFramework.hookType | default "test" }} + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" +{{- end }} diff --git a/utils/assets/charts/grafana/templates/tests/test.yaml b/utils/assets/charts/grafana/templates/tests/test.yaml new file mode 100644 index 0000000..3aac160 --- /dev/null +++ b/utils/assets/charts/grafana/templates/tests/test.yaml @@ -0,0 +1,53 @@ +{{- if .Values.testFramework.enabled }} +{{- $root := . }} +apiVersion: v1 +kind: Pod +metadata: + name: {{ include "grafana.fullname" . }}-test + labels: + {{- include "grafana.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": {{ .Values.testFramework.hookType | default "test" }} + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + namespace: {{ include "grafana.namespace" . }} +spec: + serviceAccountName: {{ include "grafana.serviceAccountNameTest" . }} + {{- with .Values.testFramework.securityContext }} + securityContext: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if or .Values.image.pullSecrets .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- include "grafana.imagePullSecrets" (dict "root" $root "imagePullSecrets" .Values.image.pullSecrets) | nindent 4 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- tpl (toYaml .) $root | nindent 4 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 4 }} + {{- end }} + containers: + - name: {{ .Release.Name }}-test + image: "{{ .Values.global.imageRegistry | default .Values.testFramework.image.registry }}/{{ .Values.testFramework.image.repository }}:{{ .Values.testFramework.image.tag }}" + imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}" + command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"] + volumeMounts: + - mountPath: /tests + name: tests + readOnly: true + {{- with .Values.testFramework.resources }} + resources: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: tests + configMap: + name: {{ include "grafana.fullname" . }}-test + restartPolicy: Never +{{- end }} diff --git a/utils/assets/charts/grafana/values.yaml b/utils/assets/charts/grafana/values.yaml new file mode 100644 index 0000000..95696c1 --- /dev/null +++ b/utils/assets/charts/grafana/values.yaml @@ -0,0 +1,1545 @@ +global: + # -- Overrides the Docker registry globally for all images + imageRegistry: null + + # To help compatibility with other charts which use global.imagePullSecrets. + # Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). + # Can be templated. + # global: + # imagePullSecrets: + # - name: pullSecret1 + # - name: pullSecret2 + # or + # global: + # imagePullSecrets: + # - pullSecret1 + # - pullSecret2 + imagePullSecrets: [] + +rbac: + create: true + ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) + # useExistingRole: name-of-some-role + # useExistingClusterRole: name-of-some-clusterRole + pspEnabled: false + pspUseAppArmor: false + namespaced: false + extraRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] + extraClusterRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] +serviceAccount: + create: true + name: + nameTest: + ## ServiceAccount labels. + labels: {} + ## Service account annotations. Can be templated. + # annotations: + # eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here + + ## autoMount is deprecated in favor of automountServiceAccountToken + # autoMount: false + automountServiceAccountToken: false + +replicas: 1 + +## Create a headless service for the deployment +headlessService: false + +## Should the service account be auto mounted on the pod +automountServiceAccountToken: true + +## Create HorizontalPodAutoscaler object for deployment type +# +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPU: "60" + targetMemory: "" + behavior: {} + +## See `kubectl explain poddisruptionbudget.spec` for more +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} +# apiVersion: "" +# minAvailable: 1 +# maxUnavailable: 1 + +## See `kubectl explain deployment.spec.strategy` for more +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +deploymentStrategy: + type: RollingUpdate + +readinessProbe: + httpGet: + path: /api/health + port: 3000 + +livenessProbe: + httpGet: + path: /api/health + port: 3000 + initialDelaySeconds: 60 + timeoutSeconds: 30 + failureThreshold: 10 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: "default-scheduler" + +image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: grafana/grafana + # Overrides the Grafana image tag whose default is the chart appVersion + tag: "" + sha: "" + pullPolicy: IfNotPresent + + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Can be templated. + ## + pullSecrets: [] + # - myRegistrKeySecretName + +testFramework: + enabled: true + ## The type of Helm hook used to run this test. Defaults to test. + ## ref: https://helm.sh/docs/topics/charts_hooks/#the-available-hooks + ## + # hookType: test + image: + # -- The Docker registry + registry: docker.io + repository: bats/bats + tag: "v1.4.1" + imagePullPolicy: IfNotPresent + securityContext: {} + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +# dns configuration for pod +dnsPolicy: ~ +dnsConfig: {} + # nameservers: + # - 8.8.8.8 + # options: + # - name: ndots + # value: "2" + # - name: edns0 + +securityContext: + runAsNonRoot: true + runAsUser: 472 + runAsGroup: 472 + fsGroup: 472 + +containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + +# Enable creating the grafana configmap +createConfigmap: true + +# Extra configmaps to mount in grafana pods +# Values are templated. +extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /etc/grafana/ssl/ + # subPath: certificates.crt # (optional) + # configMap: certs-configmap + # readOnly: true + # optional: false + + +extraEmptyDirMounts: [] + # - name: provisioning-notifiers + # mountPath: /etc/grafana/provisioning/notifiers + + +# Apply extra labels to common labels. +extraLabels: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: + +downloadDashboardsImage: + # -- The Docker registry + registry: docker.io + repository: curlimages/curl + tag: 7.85.0 + sha: "" + pullPolicy: IfNotPresent + +downloadDashboards: + env: {} + envFromSecret: "" + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + +## Pod Annotations +# podAnnotations: {} + +## ConfigMap Annotations +# configMapAnnotations: {} + # argocd.argoproj.io/sync-options: Replace=true + +## Pod Labels +# podLabels: {} + +podPortName: grafana +gossipPortName: gossip +## Deployment annotations +# annotations: {} + +## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). +## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. +## ref: http://kubernetes.io/docs/user-guide/services/ +## +service: + enabled: true + type: ClusterIP + # Set the ip family policy to configure dual-stack see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services) + ipFamilyPolicy: "" + # Sets the families that should be supported and the order in which they should be applied to ClusterIP as well. Can be IPv4 and/or IPv6. + ipFamilies: [] + loadBalancerIP: "" + loadBalancerClass: "" + loadBalancerSourceRanges: [] + port: 80 + targetPort: 3000 + # targetPort: 4181 To be used with a proxy extraContainer + ## Service annotations. Can be templated. + annotations: {} + labels: {} + portName: service + # Adds the appProtocol field to the service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + +serviceMonitor: + ## If true, a ServiceMonitor CR is created for a prometheus operator + ## https://github.com/coreos/prometheus-operator + ## + enabled: false + path: /metrics + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + labels: {} + interval: 30s + scheme: http + tlsConfig: {} + scrapeTimeout: 30s + relabelings: [] + metricRelabelings: [] + targetLabels: [] + +extraExposePorts: [] + # - name: keycloak + # port: 8080 + # targetPort: 8080 + +# overrides pod.spec.hostAliases in the grafana deployment's pods +hostAliases: [] + # - ip: "1.2.3.4" + # hostnames: + # - "my.host.com" + +ingress: + enabled: false + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + # Values can be templated + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: / + + # pathType is only for k8s >= 1.1= + pathType: Prefix + + hosts: + - chart-example.local + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + ## Or for k8s > 1.19 + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + + + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +# -- BETA: Configure the gateway routes for the chart here. +# More routes can be added by adding a dictionary key like the 'main' route. +# Be aware that this is an early beta of this feature, +# kube-prometheus-stack does not guarantee this works and is subject to change. +# Being BETA this can/will change in the future without notice, do not use unless you want to take that risk +# [[ref]](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1alpha2) +route: + main: + # -- Enables or disables the route + enabled: false + + # -- Set the route apiVersion, e.g. gateway.networking.k8s.io/v1 or gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 + # -- Set the route kind + # Valid options are GRPCRoute, HTTPRoute, TCPRoute, TLSRoute, UDPRoute + kind: HTTPRoute + + annotations: {} + labels: {} + + hostnames: [] + # - my-filter.example.com + parentRefs: [] + # - name: acme-gw + + matches: + - path: + type: PathPrefix + value: / + + ## Filters define the filters that are applied to requests that match this rule. + filters: [] + + ## Additional custom rules that can be added to the route + additionalRules: [] + +resources: {} +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi + +## Node labels for pod assignment +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +# +nodeSelector: {} + +## Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Affinity for pod assignment (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Topology Spread Constraints +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## +topologySpreadConstraints: [] + +## Additional init containers (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +## +extraInitContainers: [] + +## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod +extraContainers: "" +# extraContainers: | +# - name: proxy +# image: quay.io/gambol99/keycloak-proxy:latest +# args: +# - -provider=github +# - -client-id= +# - -client-secret= +# - -github-org= +# - -email-domain=* +# - -cookie-secret= +# - -http-address=http://0.0.0.0:4181 +# - -upstream-url=http://127.0.0.1:3000 +# ports: +# - name: proxy-web +# containerPort: 4181 + +## Volumes that can be used in init containers that will not be mounted to deployment pods +extraContainerVolumes: [] +# - name: volume-from-secret +# secret: +# secretName: secret-to-mount +# - name: empty-dir-volume +# emptyDir: {} + +## Enable persistence using Persistent Volume Claims +## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + type: pvc + enabled: false + # storageClassName: default + accessModes: + - ReadWriteOnce + size: 10Gi + # annotations: {} + finalizers: + - kubernetes.io/pvc-protection + # selectorLabels: {} + ## Sub-directory of the PV to mount. Can be templated. + # subPath: "" + ## Name of an existing PVC. Can be templated. + # existingClaim: + ## Extra labels to apply to a PVC. + extraPvcLabels: {} + disableWarning: false + + ## If persistence is not enabled, this allows to mount the + ## local storage in-memory to improve performance + ## + inMemory: + enabled: false + ## The maximum usage on memory medium EmptyDir would be + ## the minimum value between the SizeLimit specified + ## here and the sum of memory limits of all containers in a pod + ## + # sizeLimit: 300Mi + + ## If 'lookupVolumeName' is set to true, Helm will attempt to retrieve + ## the current value of 'spec.volumeName' and incorporate it into the template. + lookupVolumeName: true + +initChownData: + ## If false, data ownership will not be reset at startup + ## This allows the grafana-server to be run with an arbitrary user + ## + enabled: true + + ## initChownData container image + ## + image: + # -- The Docker registry + registry: docker.io + repository: library/busybox + tag: "1.31.1" + sha: "" + pullPolicy: IfNotPresent + + ## initChownData resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + securityContext: + runAsNonRoot: false + runAsUser: 0 + seccompProfile: + type: RuntimeDefault + capabilities: + add: + - CHOWN + +# Administrator credentials when not using an existing secret (see below) +adminUser: admin +# adminPassword: strongpassword + +# Use an existing secret for the admin user. +admin: + ## Name of the secret. Can be templated. + existingSecret: "" + userKey: admin-user + passwordKey: admin-password + +## Define command to be executed at startup by grafana container +## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) +## Default is "run.sh" as defined in grafana's Dockerfile +# command: +# - "sh" +# - "/run.sh" + +## Optionally define args if command is used +## Needed if using `hashicorp/envconsul` to manage secrets +## By default no arguments are set +# args: +# - "-secret" +# - "secret/grafana" +# - "./grafana" + +## Extra environment variables that will be pass onto deployment pods +## +## to provide grafana with access to CloudWatch on AWS EKS: +## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) +## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the +## same oidc eks provider as noted before (same as the existing line) +## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name +## +## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", +## +## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess +## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) +## +## env: +## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here +## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token +## AWS_REGION: us-east-1 +## +## 5. uncomment the EKS section in extraSecretMounts: below +## 6. uncomment the annotation section in the serviceAccount: above +## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn + +env: {} + +## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core +## Renders in container spec as: +## env: +## ... +## - name: +## valueFrom: +## +envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + +## The name of a secret in the same kubernetes namespace which contain values to be added to the environment +## This can be useful for auth tokens, etc. Value is templated. +envFromSecret: "" + +## Sensible environment variables that will be rendered as new secret object +## This can be useful for auth tokens, etc. +## If the secret values contains "{{", they'll need to be properly escaped so that they are not interpreted by Helm +## ref: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function +envRenderSecret: {} + +## The names of secrets in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the secret must be defined with an optional key. +## Name is templated. +envFromSecrets: [] +## - name: secret-name +## prefix: prefix +## optional: true + +## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the configmap must be defined with an optional key. +## Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core +envFromConfigMaps: [] +## - name: configmap-name +## prefix: prefix +## optional: true + +# Inject Kubernetes services as environment variables. +# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables +enableServiceLinks: true + +## Additional grafana server secret mounts +# Defines additional mounts with secrets. Secrets must be manually created in the namespace. +extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # secretName: grafana-secret-files + # readOnly: true + # optional: false + # subPath: "" + # + # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) + # - name: aws-iam-token + # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount + # readOnly: true + # projected: + # defaultMode: 420 + # sources: + # - serviceAccountToken: + # audience: sts.amazonaws.com + # expirationSeconds: 86400 + # path: token + # + # for CSI e.g. Azure Key Vault use the following + # - name: secrets-store-inline + # mountPath: /run/secrets + # readOnly: true + # csi: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "akv-grafana-spc" + # nodePublishSecretRef: # Only required when using service principal mode + # name: grafana-akv-creds # Only required when using service principal mode + +## Additional grafana server volume mounts +# Defines additional volume mounts. +extraVolumeMounts: [] + # - name: extra-volume-0 + # mountPath: /mnt/volume0 + # readOnly: true + # - name: extra-volume-1 + # mountPath: /mnt/volume1 + # readOnly: true + # - name: grafana-secrets + # mountPath: /mnt/volume2 + +## Additional Grafana server volumes +extraVolumes: [] + # - name: extra-volume-0 + # existingClaim: volume-claim + # - name: extra-volume-1 + # hostPath: + # path: /usr/shared/ + # type: "" + # - name: grafana-secrets + # csi: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "grafana-env-spc" + +## Container Lifecycle Hooks. Execute a specific bash command or make an HTTP request +lifecycleHooks: {} + # postStart: + # exec: + # command: [] + +## Pass the plugins you want installed as a list. +## +plugins: [] + # - digrich-bubblechart-panel + # - grafana-clock-panel + ## You can also use other plugin download URL, as long as they are valid zip files, + ## and specify the name of the plugin after the semicolon. Like this: + # - https://grafana.com/api/plugins/marcusolsson-json-datasource/versions/1.3.2/download;marcusolsson-json-datasource + +## Configure grafana datasources +## ref: http://docs.grafana.org/administration/provisioning/#datasources +## +datasources: {} +# datasources.yaml: +# apiVersion: 1 +# datasources: +# - name: Prometheus +# type: prometheus +# url: http://prometheus-prometheus-server +# access: proxy +# isDefault: true +# - name: CloudWatch +# type: cloudwatch +# access: proxy +# uid: cloudwatch +# editable: false +# jsonData: +# authType: default +# defaultRegion: us-east-1 +# deleteDatasources: [] +# - name: Prometheus + +## Configure grafana alerting (can be templated) +## ref: https://docs.grafana.com/alerting/set-up/provision-alerting-resources/file-provisioning/ +## +alerting: {} + # policies.yaml: + # apiVersion: 1 + # policies: + # - orgId: 1 + # receiver: first_uid + # + # rules.yaml: + # apiVersion: 1 + # groups: + # - orgId: 1 + # name: '{{ .Chart.Name }}_my_rule_group' + # folder: my_first_folder + # interval: 60s + # rules: + # - uid: my_id_1 + # title: my_first_rule + # condition: A + # data: + # - refId: A + # datasourceUid: '-100' + # model: + # conditions: + # - evaluator: + # params: + # - 3 + # type: gt + # operator: + # type: and + # query: + # params: + # - A + # reducer: + # type: last + # type: query + # datasource: + # type: __expr__ + # uid: '-100' + # expression: 1==0 + # intervalMs: 1000 + # maxDataPoints: 43200 + # refId: A + # type: math + # dashboardUid: my_dashboard + # panelId: 123 + # noDataState: Alerting + # for: 60s + # annotations: + # some_key: some_value + # labels: + # team: sre_team_1 + # + # contactpoints.yaml: + # secret: + # apiVersion: 1 + # contactPoints: + # - orgId: 1 + # name: cp_1 + # receivers: + # - uid: first_uid + # type: pagerduty + # settings: + # integrationKey: XXX + # severity: critical + # class: ping failure + # component: Grafana + # group: app-stack + # summary: | + # {{ `{{ include "default.message" . }}` }} + # + # templates.yaml: + # apiVersion: 1 + # templates: + # - orgId: 1 + # name: my_first_template + # template: | + # {{ ` + # {{ define "my_first_template" }} + # Custom notification message + # {{ end }} + # ` }} + # + # mutetimes.yaml + # apiVersion: 1 + # muteTimes: + # - orgId: 1 + # name: mti_1 + # # refer to https://prometheus.io/docs/alerting/latest/configuration/#time_interval-0 + # time_intervals: {} + +## Configure notifiers +## ref: http://docs.grafana.org/administration/provisioning/#alert-notification-channels +## +notifiers: {} +# notifiers.yaml: +# notifiers: +# - name: email-notifier +# type: email +# uid: email1 +# # either: +# org_id: 1 +# # or +# org_name: Main Org. +# is_default: true +# settings: +# addresses: an_email_address@example.com +# delete_notifiers: + +## Configure grafana dashboard providers +## ref: http://docs.grafana.org/administration/provisioning/#dashboards +## +## `path` must be /var/lib/grafana/dashboards/ +## +dashboardProviders: {} +# dashboardproviders.yaml: +# apiVersion: 1 +# providers: +# - name: 'default' +# orgId: 1 +# folder: '' +# type: file +# disableDeletion: false +# editable: true +# options: +# path: /var/lib/grafana/dashboards/default + +## Configure grafana dashboard to import +## NOTE: To use dashboards you must also enable/configure dashboardProviders +## ref: https://grafana.com/dashboards +## +## dashboards per provider, use provider name as key. +## +dashboards: {} + # default: + # some-dashboard: + # json: | + # $RAW_JSON + # custom-dashboard: + # file: dashboards/custom-dashboard.json + # prometheus-stats: + # gnetId: 2 + # revision: 2 + # datasource: Prometheus + # local-dashboard: + # url: https://example.com/repository/test.json + # token: '' + # local-dashboard-base64: + # url: https://example.com/repository/test-b64.json + # token: '' + # b64content: true + # local-dashboard-gitlab: + # url: https://example.com/repository/test-gitlab.json + # gitlabToken: '' + # local-dashboard-bitbucket: + # url: https://example.com/repository/test-bitbucket.json + # bearerToken: '' + # local-dashboard-azure: + # url: https://example.com/repository/test-azure.json + # basic: '' + # acceptHeader: '*/*' + +## Reference to external ConfigMap per provider. Use provider name as key and ConfigMap name as value. +## A provider dashboards must be defined either by external ConfigMaps or in values.yaml, not in both. +## ConfigMap data example: +## +## data: +## example-dashboard.json: | +## RAW_JSON +## +dashboardsConfigMaps: {} +# default: "" + +## Grafana's primary configuration +## NOTE: values in map will be converted to ini format +## ref: http://docs.grafana.org/installation/configuration/ +## +grafana.ini: + paths: + data: /var/lib/grafana/ + logs: /var/log/grafana + plugins: /var/lib/grafana/plugins + provisioning: /etc/grafana/provisioning + analytics: + check_for_updates: true + log: + mode: console + grafana_net: + url: https://grafana.net + server: + domain: "{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ tpl (.Values.ingress.hosts | first) . }}{{ else }}''{{ end }}" +## grafana Authentication can be enabled with the following values on grafana.ini + # server: + # The full public facing url you use in browser, used for redirects and emails + # root_url: + # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana + # auth.github: + # enabled: false + # allow_sign_up: false + # scopes: user:email,read:org + # auth_url: https://github.com/login/oauth/authorize + # token_url: https://github.com/login/oauth/access_token + # api_url: https://api.github.com/user + # team_ids: + # allowed_organizations: + # client_id: + # client_secret: +## LDAP Authentication can be enabled with the following values on grafana.ini +## NOTE: Grafana will fail to start if the value for ldap.toml is invalid + # auth.ldap: + # enabled: true + # allow_sign_up: true + # config_file: /etc/grafana/ldap.toml + +## Grafana's LDAP configuration +## Templated by the template in _helpers.tpl +## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled +## ref: http://docs.grafana.org/installation/configuration/#auth-ldap +## ref: http://docs.grafana.org/installation/ldap/#configuration +ldap: + enabled: false + # `existingSecret` is a reference to an existing secret containing the ldap configuration + # for Grafana in a key `ldap-toml`. + existingSecret: "" + # `config` is the content of `ldap.toml` that will be stored in the created secret + config: "" + # config: |- + # verbose_logging = true + + # [[servers]] + # host = "my-ldap-server" + # port = 636 + # use_ssl = true + # start_tls = false + # ssl_skip_verify = false + # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" + +## Grafana's SMTP configuration +## NOTE: To enable, grafana.ini must be configured with smtp.enabled +## ref: http://docs.grafana.org/installation/configuration/#smtp +smtp: + # `existingSecret` is a reference to an existing secret containing the smtp configuration + # for Grafana. + existingSecret: "" + userKey: "user" + passwordKey: "password" + +## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders +## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards +sidecar: + image: + # -- The Docker registry + registry: quay.io + repository: kiwigrid/k8s-sidecar + tag: 1.28.0 + sha: "" + imagePullPolicy: IfNotPresent + resources: {} +# limits: +# cpu: 100m +# memory: 100Mi +# requests: +# cpu: 50m +# memory: 50Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + # skipTlsVerify Set to true to skip tls verification for kube api calls + # skipTlsVerify: true + enableUniqueFilenames: false + readinessProbe: {} + livenessProbe: {} + # Log level default for all sidecars. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. Defaults to INFO + # logLevel: INFO + alerts: + enabled: false + # Additional environment variables for the alerts sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with alert are marked with + label: grafana_alert + # value of label that the configmaps with alert are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # If specified, the sidecar will search for alert config-maps inside this namespace. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # maxTotalRetries: Total number of retries to allow for any http request. + # Takes precedence over other counts. Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry. + # maxTotalRetries: 5 + # + # maxConnectRetries: How many connection-related errors to retry on for any http request. + # These are errors raised before the request is sent to the remote server, which we assume has not triggered the server to process the request. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxConnectRetries: 10 + # + # maxReadRetries: How many times to retry on read errors for any http request + # These errors are raised after the request was sent to the server, so the request may have side-effects. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxReadRetries: 5 + # + # Endpoint to send request to reload alerts + reloadURL: "http://localhost:3000/api/admin/provisioning/alerting/reload" + # Absolute path to shell script to execute after a alert got reloaded + script: null + skipReload: false + # This is needed if skipReload is true, to load any alerts defined at startup time. + # Deploy the alert sidecar as an initContainer. + initAlerts: false + # Additional alerts sidecar volume mounts + extraMounts: [] + # Sets the size limit of the alert sidecar emptyDir volume + sizeLimit: {} + dashboards: + enabled: false + # Additional environment variables for the dashboards sidecar + env: {} + ## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. + ## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core + ## Renders in container spec as: + ## env: + ## ... + ## - name: + ## valueFrom: + ## + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + SCProvider: true + # label that the configmaps with dashboards are marked with + label: grafana_dashboard + # value of label that the configmaps with dashboards are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # folder in the pod that should hold the collected dashboards (unless `defaultFolderName` is set) + folder: /tmp/dashboards + # The default folder name, it will create a subfolder under the `folder` and put dashboards in there instead + defaultFolderName: null + # Namespaces list. If specified, the sidecar will search for config-maps/secrets inside these namespaces. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces. + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # If specified, the sidecar will look for annotation with this name to create folder and put graph here. + # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. + folderAnnotation: null + # + # maxTotalRetries: Total number of retries to allow for any http request. + # Takes precedence over other counts. Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry. + # maxTotalRetries: 5 + # + # maxConnectRetries: How many connection-related errors to retry on for any http request. + # These are errors raised before the request is sent to the remote server, which we assume has not triggered the server to process the request. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxConnectRetries: 10 + # + # maxReadRetries: How many times to retry on read errors for any http request + # These errors are raised after the request was sent to the server, so the request may have side-effects. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxReadRetries: 5 + # + # Endpoint to send request to reload alerts + reloadURL: "http://localhost:3000/api/admin/provisioning/dashboards/reload" + # Absolute path to shell script to execute after a configmap got reloaded + script: null + skipReload: false + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # provider configuration that lets grafana manage the dashboards + provider: + # name of the provider, should be unique + name: sidecarProvider + # orgid as configured in grafana + orgid: 1 + # folder in which the dashboards should be imported in grafana + folder: '' + # folder UID. will be automatically generated if not specified + folderUid: '' + # type of the provider + type: file + # disableDelete to activate a import-only behaviour + disableDelete: false + # allow updating provisioned dashboards from the UI + allowUiUpdates: false + # allow Grafana to replicate dashboard structure from filesystem + foldersFromFilesStructure: false + # Additional dashboards sidecar volume mounts + extraMounts: [] + # Sets the size limit of the dashboard sidecar emptyDir volume + sizeLimit: {} + datasources: + enabled: false + # Additional environment variables for the datasourcessidecar + env: {} + ## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. + ## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core + ## Renders in container spec as: + ## env: + ## ... + ## - name: + ## valueFrom: + ## + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with datasources are marked with + label: grafana_datasource + # value of label that the configmaps with datasources are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # If specified, the sidecar will search for datasource config-maps inside this namespace. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # maxTotalRetries: Total number of retries to allow for any http request. + # Takes precedence over other counts. Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry. + # maxTotalRetries: 5 + # + # maxConnectRetries: How many connection-related errors to retry on for any http request. + # These are errors raised before the request is sent to the remote server, which we assume has not triggered the server to process the request. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxConnectRetries: 10 + # + # maxReadRetries: How many times to retry on read errors for any http request + # These errors are raised after the request was sent to the server, so the request may have side-effects. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxReadRetries: 5 + # + # Endpoint to send request to reload datasources + reloadURL: "http://localhost:3000/api/admin/provisioning/datasources/reload" + # Absolute path to shell script to execute after a datasource got reloaded + script: null + skipReload: false + # This is needed if skipReload is true, to load any datasources defined at startup time. + # Deploy the datasources sidecar as an initContainer. + initDatasources: false + # Additional datasources sidecar volume mounts + extraMounts: [] + # Sets the size limit of the datasource sidecar emptyDir volume + sizeLimit: {} + plugins: + enabled: false + # Additional environment variables for the plugins sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with plugins are marked with + label: grafana_plugin + # value of label that the configmaps with plugins are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # If specified, the sidecar will search for plugin config-maps inside this namespace. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # maxTotalRetries: Total number of retries to allow for any http request. + # Takes precedence over other counts. Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry. + # maxTotalRetries: 5 + # + # maxConnectRetries: How many connection-related errors to retry on for any http request. + # These are errors raised before the request is sent to the remote server, which we assume has not triggered the server to process the request. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxConnectRetries: 10 + # + # maxReadRetries: How many times to retry on read errors for any http request + # These errors are raised after the request was sent to the server, so the request may have side-effects. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxReadRetries: 5 + # + # Endpoint to send request to reload plugins + reloadURL: "http://localhost:3000/api/admin/provisioning/plugins/reload" + # Absolute path to shell script to execute after a plugin got reloaded + script: null + skipReload: false + # Deploy the datasource sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any plugins defined at startup time. + initPlugins: false + # Additional plugins sidecar volume mounts + extraMounts: [] + # Sets the size limit of the plugin sidecar emptyDir volume + sizeLimit: {} + notifiers: + enabled: false + # Additional environment variables for the notifierssidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with notifiers are marked with + label: grafana_notifier + # value of label that the configmaps with notifiers are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # If specified, the sidecar will search for notifier config-maps inside this namespace. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # maxTotalRetries: Total number of retries to allow for any http request. + # Takes precedence over other counts. Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry. + # maxTotalRetries: 5 + # + # maxConnectRetries: How many connection-related errors to retry on for any http request. + # These are errors raised before the request is sent to the remote server, which we assume has not triggered the server to process the request. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxConnectRetries: 10 + # + # maxReadRetries: How many times to retry on read errors for any http request + # These errors are raised after the request was sent to the server, so the request may have side-effects. + # Applies to all requests to reloadURL and k8s api requests. + # Set to 0 to fail on the first retry of this type. + # maxReadRetries: 5 + # + # Endpoint to send request to reload notifiers + reloadURL: "http://localhost:3000/api/admin/provisioning/notifications/reload" + # Absolute path to shell script to execute after a notifier got reloaded + script: null + skipReload: false + # Deploy the notifier sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any notifiers defined at startup time. + initNotifiers: false + # Additional notifiers sidecar volume mounts + extraMounts: [] + # Sets the size limit of the notifier sidecar emptyDir volume + sizeLimit: {} + +## Override the deployment namespace +## +namespaceOverride: "" + +## Number of old ReplicaSets to retain +## +revisionHistoryLimit: 10 + +## Add a seperate remote image renderer deployment/service +imageRenderer: + deploymentStrategy: {} + # Enable the image-renderer deployment & service + enabled: false + replicas: 1 + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPU: "60" + targetMemory: "" + behavior: {} + # The url of remote image renderer if it is not in the same namespace with the grafana instance + serverURL: "" + # The callback url of grafana instances if it is not in the same namespace with the remote image renderer + renderingCallbackURL: "" + image: + # -- The Docker registry + registry: docker.io + # image-renderer Image repository + repository: grafana/grafana-image-renderer + # image-renderer Image tag + tag: latest + # image-renderer Image sha (optional) + sha: "" + # image-renderer ImagePullPolicy + pullPolicy: Always + # extra environment variables + env: + HTTP_HOST: "0.0.0.0" + # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 + # RENDERING_MODE: clustered + # IGNORE_HTTPS_ERRORS: true + + ## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. + ## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core + ## Renders in container spec as: + ## env: + ## ... + ## - name: + ## valueFrom: + ## + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + + # image-renderer deployment serviceAccount + serviceAccountName: "" + # image-renderer deployment securityContext + securityContext: {} + # image-renderer deployment container securityContext + containerSecurityContext: + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ['ALL'] + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + ## image-renderer pod annotation + podAnnotations: {} + # image-renderer deployment Host Aliases + hostAliases: [] + # image-renderer deployment priority class + priorityClassName: '' + service: + # Enable the image-renderer service + enabled: true + # image-renderer service port name + portName: 'http' + # image-renderer service port used by both service and deployment + port: 8081 + targetPort: 8081 + # Adds the appProtocol field to the image-renderer service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + serviceMonitor: + ## If true, a ServiceMonitor CRD is created for a prometheus operator + ## https://github.com/coreos/prometheus-operator + ## + enabled: false + path: /metrics + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + labels: {} + interval: 1m + scheme: http + tlsConfig: {} + scrapeTimeout: 30s + relabelings: [] + # See: https://doc.crds.dev/github.com/prometheus-operator/kube-prometheus/monitoring.coreos.com/ServiceMonitor/v1@v0.11.0#spec-targetLabels + targetLabels: [] + # - targetLabel1 + # - targetLabel2 + # If https is enabled in Grafana, this needs to be set as 'https' to correctly configure the callback used in Grafana + grafanaProtocol: http + # In case a sub_path is used this needs to be added to the image renderer callback + grafanaSubPath: "" + # name of the image-renderer port on the pod + podPortName: http + # number of image-renderer replica sets to keep + revisionHistoryLimit: 10 + networkPolicy: + # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods + limitIngress: true + # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods + limitEgress: false + # Allow additional services to access image-renderer (eg. Prometheus operator when ServiceMonitor is enabled) + extraIngressSelectors: [] + resources: {} +# limits: +# cpu: 100m +# memory: 100Mi +# requests: +# cpu: 50m +# memory: 50Mi + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + + ## Affinity for pod assignment (evaluated as template) + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## + affinity: {} + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: "default-scheduler" + + # Extra configmaps to mount in image-renderer pods + extraConfigmapMounts: [] + + # Extra secrets to mount in image-renderer pods + extraSecretMounts: [] + + # Extra volumes to mount in image-renderer pods + extraVolumeMounts: [] + + # Extra volumes for image-renderer pods + extraVolumes: [] + +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to grafana port defined. + ## When true, grafana will accept connections from any source + ## (with the correct destination port). + ## + ingress: true + ## @param networkPolicy.ingress When true enables the creation + ## an ingress network policy + ## + allowExternal: true + ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed + ## If explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace + ## and that match other criteria, the ones that have the good label, can reach the grafana. + ## But sometimes, we want the grafana to be accessible to clients from other namespaces, in this case, we can use this + ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. + ## + ## Example: + ## explicitNamespacesSelector: + ## matchLabels: + ## role: frontend + ## matchExpressions: + ## - {key: role, operator: In, values: [frontend]} + ## + explicitNamespacesSelector: {} + ## + ## + ## + ## + ## + ## + egress: + ## @param networkPolicy.egress.enabled When enabled, an egress network policy will be + ## created allowing grafana to connect to external data sources from kubernetes cluster. + enabled: false + ## + ## @param networkPolicy.egress.blockDNSResolution When enabled, DNS resolution will be blocked + ## for all pods in the grafana namespace. + blockDNSResolution: false + ## + ## @param networkPolicy.egress.ports Add individual ports to be allowed by the egress + ports: [] + ## Add ports to the egress by specifying - port: + ## E.X. + ## - port: 80 + ## - port: 443 + ## + ## @param networkPolicy.egress.to Allow egress traffic to specific destinations + to: [] + ## Add destinations to the egress by specifying - ipBlock: + ## E.X. + ## to: + ## - namespaceSelector: + ## matchExpressions: + ## - {key: role, operator: In, values: [grafana]} + ## + ## + ## + ## + ## + +# Enable backward compatibility of kubernetes where version below 1.13 doesn't have the enableServiceLinks option +enableKubeBackwardCompatibility: false +useStatefulSet: false +# Create a dynamic manifests via values: +extraObjects: [] + # - apiVersion: "kubernetes-client.io/v1" + # kind: ExternalSecret + # metadata: + # name: grafana-secrets + # spec: + # backendType: gcpSecretsManager + # data: + # - key: grafana-admin-password + # name: adminPassword + +# assertNoLeakedSecrets is a helper function defined in _helpers.tpl that checks if secret +# values are not exposed in the rendered grafana.ini configmap. It is enabled by default. +# +# To pass values into grafana.ini without exposing them in a configmap, use variable expansion: +# https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#variable-expansion +# +# Alternatively, if you wish to allow secret values to be exposed in the rendered grafana.ini configmap, +# you can disable this check by setting assertNoLeakedSecrets to false. +assertNoLeakedSecrets: true diff --git a/utils/assets/charts/hydra/.helmignore b/utils/assets/charts/hydra/.helmignore new file mode 100644 index 0000000..b066297 --- /dev/null +++ b/utils/assets/charts/hydra/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +*.txt \ No newline at end of file diff --git a/utils/assets/charts/hydra/Chart.lock b/utils/assets/charts/hydra/Chart.lock new file mode 100644 index 0000000..6f43409 --- /dev/null +++ b/utils/assets/charts/hydra/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: ory-commons + repository: file://../ory-commons + version: 0.1.0 +- name: hydra-maester + repository: file://../hydra-maester + version: 0.50.6 +digest: sha256:0799d168b3e83ce9b85a48ef5d3abb9a99f6cb2f8436be51d91f3612e6b2b2da +generated: "2024-12-16T15:04:47.361658969Z" diff --git a/utils/assets/charts/hydra/Chart.yaml b/utils/assets/charts/hydra/Chart.yaml new file mode 100644 index 0000000..a390367 --- /dev/null +++ b/utils/assets/charts/hydra/Chart.yaml @@ -0,0 +1,33 @@ +apiVersion: v2 +appVersion: v2.2.0 +dependencies: +- alias: ory + name: ory-commons + repository: file://../ory-commons + version: 0.1.0 +- alias: hydra-maester + condition: maester.enabled + name: hydra-maester + repository: file://../hydra-maester + version: 0.50.6 +description: A Helm chart for deploying ORY Hydra in Kubernetes +home: https://www.ory.sh/ +icon: https://raw.githubusercontent.com/ory/docs/master/docs/static/img/logo-hydra.svg +keywords: +- oauth2 +- openid-connect +- openid +- oidc +- op +- api-security +- security +maintainers: +- email: hi@ory.sh + name: ORY Team + url: https://www.ory.sh/ +name: hydra +sources: +- https://github.com/ory/hydra +- https://github.com/ory/k8s +type: application +version: 0.50.6 diff --git a/utils/assets/charts/hydra/README.md b/utils/assets/charts/hydra/README.md new file mode 100644 index 0000000..185340f --- /dev/null +++ b/utils/assets/charts/hydra/README.md @@ -0,0 +1,206 @@ +# hydra + +![Version: 0.50.5](https://img.shields.io/badge/Version-0.50.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v2.2.0](https://img.shields.io/badge/AppVersion-v2.2.0-informational?style=flat-square) + +A Helm chart for deploying ORY Hydra in Kubernetes + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| ORY Team | | | + +## Source Code + +* +* + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../hydra-maester | hydra-maester(hydra-maester) | 0.50.5 | +| file://../ory-commons | ory(ory-commons) | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| configmap.hashSumEnabled | bool | `true` | switch to false to prevent checksum annotations being maintained and propogated to the pods | +| cronjob.janitor.affinity | object | `{}` | Configure node affinity | +| cronjob.janitor.annotations | object | `{}` | Set custom cron job level annotations | +| cronjob.janitor.automountServiceAccountToken | bool | `true` | Set automounting of the SA token | +| cronjob.janitor.customArgs | list | `[]` | Configure the arguments of the entrypoint, overriding the default value | +| cronjob.janitor.customCommand | list | `[]` | Configure a custom entrypoint, overriding the default value | +| cronjob.janitor.extraContainers | string | `""` | If you want to add extra sidecar containers. | +| cronjob.janitor.extraEnv | list | `[]` | Array of extra envs to be passed to the cronjob. This takes precedence over deployment variables. Kubernetes format is expected. Value is processed with Helm `tpl` - name: FOO value: BAR | +| cronjob.janitor.extraInitContainers | string | `""` | If you want to add extra init containers. These are processed before the migration init container. | +| cronjob.janitor.extraVolumeMounts | list | `[]` | | +| cronjob.janitor.extraVolumes | list | `[]` | If you want to mount external volume | +| cronjob.janitor.labels | object | `{}` | Set custom cron job level labels | +| cronjob.janitor.nodeSelector | object | `{}` | Configure node labels for pod assignment | +| cronjob.janitor.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects | +| cronjob.janitor.podMetadata.annotations | object | `{}` | Extra pod level annotations | +| cronjob.janitor.podMetadata.labels | object | `{}` | Extra pod level labels | +| cronjob.janitor.podSecurityContext | object | `{}` | | +| cronjob.janitor.resources | object | `{"limits":{},"requests":{}}` | We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi | +| cronjob.janitor.schedule | string | `"0 */1 * * *"` | Configure how often the cron job is ran | +| cronjob.janitor.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":100}` | Configure the containers' SecurityContext for the janitor cronjob | +| cronjob.janitor.serviceAccount | object | `{"annotations":{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0"},"create":true,"name":""}` | Specify the serviceAccountName value. In some situations it is needed to provides specific permissions to Hydra deployments Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. | +| cronjob.janitor.serviceAccount.annotations | object | `{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0"}` | Annotations to add to the service account | +| cronjob.janitor.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| cronjob.janitor.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| cronjob.janitor.tolerations | list | `[]` | Configure node tolerations | +| deployment.annotations | object | `{}` | Set custom deployment level annotations | +| deployment.automigration | object | `{"extraEnv":[]}` | Parameters for the automigration initContainer | +| deployment.automigration.extraEnv | list | `[]` | Array of extra envs to be passed to the initContainer. Kubernetes format is expected. Value is processed with Helm `tpl` - name: FOO value: BAR | +| deployment.automountServiceAccountToken | bool | `false` | | +| deployment.autoscaling | object | `{"behavior":{},"enabled":false,"maxReplicas":3,"minReplicas":1,"targetCPU":{},"targetMemory":{}}` | Configure HPA | +| deployment.autoscaling.behavior | object | `{}` | Set custom behavior https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior | +| deployment.customLivenessProbe | object | `{}` | Configure a custom livenessProbe. This overwrites the default object | +| deployment.customReadinessProbe | object | `{}` | Configure a custom readinessProbe. This overwrites the default object | +| deployment.customStartupProbe | object | `{}` | Configure a custom startupProbe. This overwrites the default object | +| deployment.dnsConfig | object | `{}` | Configure pod dnsConfig. | +| deployment.extraContainers | string | `""` | If you want to add extra sidecar containers. | +| deployment.extraEnv | list | `[]` | Array of extra envs to be passed to the deployment. Kubernetes format is expected. Value is processed with Helm `tpl` - name: FOO value: BAR | +| deployment.extraInitContainers | string | `""` | If you want to add extra init containers. These are processed before the migration init container. | +| deployment.extraVolumeMounts | list | `[]` | | +| deployment.extraVolumes | list | `[]` | If you want to mount external volume | +| deployment.initContainerSecurityContext | object | `{}` | | +| deployment.labels | object | `{}` | Set custom deployment level labels | +| deployment.lifecycle | object | `{}` | | +| deployment.nodeSelector | object | `{}` | Node labels for pod assignment. | +| deployment.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects | +| deployment.podMetadata.annotations | object | `{}` | Extra pod level annotations | +| deployment.podMetadata.labels | object | `{}` | Extra pod level labels | +| deployment.podSecurityContext.fsGroup | int | `65534` | | +| deployment.podSecurityContext.fsGroupChangePolicy | string | `"OnRootMismatch"` | | +| deployment.podSecurityContext.runAsGroup | int | `65534` | | +| deployment.podSecurityContext.runAsNonRoot | bool | `true` | | +| deployment.podSecurityContext.runAsUser | int | `65534` | | +| deployment.podSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| deployment.readinessProbe | object | `{"failureThreshold":5,"initialDelaySeconds":5,"periodSeconds":10}` | Default probe timers | +| deployment.resources | object | `{}` | We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi | +| deployment.revisionHistoryLimit | int | `5` | Number of revisions kept in history | +| deployment.securityContext.allowPrivilegeEscalation | bool | `false` | | +| deployment.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| deployment.securityContext.privileged | bool | `false` | | +| deployment.securityContext.readOnlyRootFilesystem | bool | `true` | | +| deployment.securityContext.runAsGroup | int | `65534` | | +| deployment.securityContext.runAsNonRoot | bool | `true` | | +| deployment.securityContext.runAsUser | int | `65534` | | +| deployment.securityContext.seLinuxOptions.level | string | `"s0:c123,c456"` | | +| deployment.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| deployment.serviceAccount | object | `{"annotations":{},"create":true,"name":""}` | Specify the serviceAccountName value. In some situations it is needed to provides specific permissions to Hydra deployments Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. | +| deployment.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| deployment.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| deployment.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| deployment.startupProbe | object | `{"failureThreshold":5,"initialDelaySeconds":1,"periodSeconds":1,"successThreshold":1,"timeoutSeconds":2}` | Default probe timers | +| deployment.strategy.rollingUpdate.maxSurge | string | `"25%"` | | +| deployment.strategy.rollingUpdate.maxUnavailable | string | `"25%"` | | +| deployment.strategy.type | string | `"RollingUpdate"` | | +| deployment.terminationGracePeriodSeconds | int | `60` | | +| deployment.tolerations | list | `[]` | Configure node tolerations. | +| deployment.topologySpreadConstraints | list | `[]` | Configure pod topologySpreadConstraints. | +| fullnameOverride | string | `""` | Full chart name override | +| hydra-maester.adminService.name | string | `""` | The service name value may need to be set if you use `fullnameOverride` for the parent chart | +| hydra.automigration.customArgs | list | `[]` | Ability to override arguments of the entrypoint. Can be used in-depended of customCommand eg: - sleep 5; - kratos | +| hydra.automigration.customCommand | list | `[]` | Ability to override the entrypoint of the automigration container (e.g. to source dynamic secrets or export environment dynamic variables) | +| hydra.automigration.enabled | bool | `false` | | +| hydra.automigration.resources | object | `{}` | resource requests and limits for the automigration initcontainer | +| hydra.automigration.type | string | `"job"` | Configure the way to execute database migration. Possible values: job, initContainer When set to job, the migration will be executed as a job on release or upgrade. When set to initContainer, the migration will be executed when kratos pod is created Defaults to job | +| hydra.command | list | `["hydra"]` | Ability to override the entrypoint of hydra container (e.g. to source dynamic secrets or export environment dynamic variables) | +| hydra.config | object | `{"secrets":{},"serve":{"admin":{"port":4445},"public":{"port":4444},"tls":{"allow_termination_from":["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}},"urls":{"self":{}}}` | The ORY Hydra configuration. For a full list of available settings, check: https://www.ory.sh/docs/hydra/reference/configuration | +| hydra.config.secrets | object | `{}` | The secrets have to be provided as a string slice, example: system: - "OG5XbmxXa3dYeGplQXpQanYxeEFuRUFa" - "foo bar 123 456 lorem" - "foo bar 123 456 lorem 1" - "foo bar 123 456 lorem 2" - "foo bar 123 456 lorem 3" | +| hydra.config.urls | object | `{"self":{}}` | Configure the urls used by hydra itself, such as the issuer. Note: some values are required for hydra to start, please refer to https://www.ory.sh/docs/hydra/self-hosted/kubernetes-helm-chart self: issuer: "https://public.hydra.localhost:4444/" | +| hydra.customArgs | list | `[]` | Ability to override arguments of the entrypoint. Can be used in-depended of customCommand | +| hydra.dev | bool | `false` | Enable dev mode, not secure in production environments | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| image.repository | string | `"oryd/hydra"` | ORY Hydra image | +| image.tag | string | `"v2.2.0"` | ORY Hydra version | +| imagePullSecrets | list | `[]` | Image pull secrets | +| ingress.admin.annotations | object | `{}` | | +| ingress.admin.className | string | `""` | | +| ingress.admin.enabled | bool | `false` | En-/Disable the api ingress. | +| ingress.admin.hosts[0].host | string | `"admin.hydra.localhost"` | | +| ingress.admin.hosts[0].paths[0].path | string | `"/"` | | +| ingress.admin.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | +| ingress.public | object | `{"annotations":{},"className":"","enabled":false,"hosts":[{"host":"public.hydra.localhost","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}]}` | Configure ingress for the proxy port. | +| ingress.public.enabled | bool | `false` | En-/Disable the proxy ingress. | +| janitor.batchSize | int | `100` | Configure how many records are deleted with each iteration | +| janitor.cleanupGrants | bool | `false` | Configure if the trust relationships must be cleaned up | +| janitor.cleanupRequests | bool | `false` | Configure if the consent and authentication requests must be cleaned up | +| janitor.cleanupTokens | bool | `false` | Configure if the access and refresh tokens must be cleaned up | +| janitor.enabled | bool | `false` | Enable cleanup of stale database rows by periodically running the janitor command | +| janitor.limit | int | `10000` | Configure how many records are retrieved from database for deletion | +| job.annotations | object | `{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"1"}` | If you do want to specify annotations, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'annotations:'. | +| job.automountServiceAccountToken | bool | `true` | Set automounting of the SA token | +| job.extraContainers | string | `""` | If you want to add extra sidecar containers. | +| job.extraEnv | list | `[]` | Array of extra envs to be passed to the job. This takes precedence over deployment variables. Kubernetes format is expected. Value is processed with Helm `tpl` - name: FOO value: BAR | +| job.extraInitContainers | string | `""` | If you want to add extra init containers. extraInitContainers: | - name: ... image: ... | +| job.labels | object | `{}` | Set custom deployment level labels | +| job.lifecycle | string | `""` | If you want to add lifecycle hooks. | +| job.nodeSelector | object | `{}` | Node labels for pod assignment. | +| job.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects | +| job.podMetadata.annotations | object | `{}` | Extra pod level annotations | +| job.podMetadata.labels | object | `{}` | Extra pod level labels | +| job.resources | object | `{}` | resource requests and limits for the automigration job | +| job.serviceAccount | object | `{"annotations":{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0"},"create":true,"name":""}` | Specify the serviceAccountName value. In some situations it is needed to provides specific permissions to Hydra deployments Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. | +| job.serviceAccount.annotations | object | `{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0"}` | Annotations to add to the service account | +| job.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| job.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| job.shareProcessNamespace | bool | `false` | Set sharing process namespace | +| job.spec.backoffLimit | int | `10` | Set job back off limit | +| job.tolerations | list | `[]` | Configure node tolerations. | +| maester.enabled | bool | `true` | | +| nameOverride | string | `""` | | +| pdb.enabled | bool | `false` | | +| pdb.spec.maxUnavailable | string | `""` | | +| pdb.spec.minAvailable | string | `""` | | +| priorityClassName | string | `""` | Pod priority https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ | +| replicaCount | int | `1` | Number of ORY Hydra members | +| secret.enabled | bool | `true` | switch to false to prevent creating the secret | +| secret.hashSumEnabled | bool | `true` | switch to false to prevent checksum annotations being maintained and propogated to the pods | +| secret.nameOverride | string | `""` | Provide custom name of existing secret, or custom name of secret to be created | +| secret.secretAnnotations | object | `{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0","helm.sh/resource-policy":"keep"}` | Annotations to be added to secret. Annotations are added only when secret is being created. Existing secret will not be modified. | +| service.admin | object | `{"annotations":{},"enabled":true,"labels":{},"loadBalancerIP":"","metricsPath":"/admin/metrics/prometheus","name":"http","port":4445,"type":"ClusterIP"}` | Configures the Kubernetes service for the api port. | +| service.admin.annotations | object | `{}` | If you do want to specify annotations, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'annotations:'. | +| service.admin.enabled | bool | `true` | En-/disable the service | +| service.admin.loadBalancerIP | string | `""` | The load balancer IP | +| service.admin.metricsPath | string | `"/admin/metrics/prometheus"` | Path to the metrics endpoint | +| service.admin.name | string | `"http"` | The service port name. Useful to set a custom service port name if it must follow a scheme (e.g. Istio) | +| service.admin.port | int | `4445` | The service port | +| service.admin.type | string | `"ClusterIP"` | The service type | +| service.public | object | `{"annotations":{},"enabled":true,"labels":{},"loadBalancerIP":"","name":"http","port":4444,"type":"ClusterIP"}` | Configures the Kubernetes service for the proxy port. | +| service.public.annotations | object | `{}` | If you do want to specify annotations, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'annotations:'. | +| service.public.enabled | bool | `true` | En-/disable the service | +| service.public.loadBalancerIP | string | `""` | The load balancer IP | +| service.public.name | string | `"http"` | The service port name. Useful to set a custom service port name if it must follow a scheme (e.g. Istio) | +| service.public.port | int | `4444` | The service port | +| service.public.type | string | `"ClusterIP"` | The service type | +| serviceMonitor.enabled | bool | `false` | switch to true to enable creating the ServiceMonitor | +| serviceMonitor.labels | object | `{}` | Provide additionnal labels to the ServiceMonitor ressource metadata | +| serviceMonitor.scheme | string | `"http"` | HTTP scheme to use for scraping. | +| serviceMonitor.scrapeInterval | string | `"60s"` | Interval at which metrics should be scraped | +| serviceMonitor.scrapeTimeout | string | `"30s"` | Timeout after which the scrape is ended | +| serviceMonitor.tlsConfig | object | `{}` | TLS configuration to use when scraping the endpoint | +| test.busybox | object | `{"repository":"busybox","tag":1}` | use a busybox image from another repository | +| test.labels | object | `{}` | Provide additional labels to the test pod | +| watcher.automountServiceAccountToken | bool | `true` | | +| watcher.enabled | bool | `false` | | +| watcher.image | string | `"oryd/k8s-toolbox:v0.0.7"` | | +| watcher.mountFile | string | `""` | Path to mounted file, which wil be monitored for changes. eg: /etc/secrets/my-secret/foo | +| watcher.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects | +| watcher.podMetadata.annotations | object | `{}` | Extra pod level annotations | +| watcher.podMetadata.labels | object | `{}` | Extra pod level labels | +| watcher.podSecurityContext | object | `{}` | pod securityContext for watcher deployment | +| watcher.resources | object | `{}` | | +| watcher.revisionHistoryLimit | int | `5` | Number of revisions kept in history | +| watcher.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":100,"seccompProfile":{"type":"RuntimeDefault"}}` | container securityContext for watcher deployment | +| watcher.watchLabelKey | string | `"ory.sh/watcher"` | Label key used for managing applications | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/utils/assets/charts/hydra/charts/hydra-maester/.helmignore b/utils/assets/charts/hydra/charts/hydra-maester/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/utils/assets/charts/hydra/charts/hydra-maester/Chart.yaml b/utils/assets/charts/hydra/charts/hydra-maester/Chart.yaml new file mode 100644 index 0000000..15b8787 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +appVersion: v0.0.36 +description: A Helm chart for Kubernetes +icon: https://raw.githubusercontent.com/ory/docs/master/docs/static/img/logo-hydra.svg +name: hydra-maester +type: application +version: 0.50.6 diff --git a/utils/assets/charts/hydra/charts/hydra-maester/README.md b/utils/assets/charts/hydra/charts/hydra-maester/README.md new file mode 100644 index 0000000..38b05b6 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/README.md @@ -0,0 +1,67 @@ +# hydra-maester + +![Version: 0.50.5](https://img.shields.io/badge/Version-0.50.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.0.36](https://img.shields.io/badge/AppVersion-v0.0.36-informational?style=flat-square) + +A Helm chart for Kubernetes + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| adminService.endpoint | string | `"/admin/clients"` | Set the clients endpoint, should be `/clients` for Hydra 1.x and `/admin/clients` for Hydra 2.x | +| adminService.insecureSkipVerify | bool | `false` | Skip http client insecure verification | +| adminService.name | string | `nil` | Service name | +| adminService.port | int | `4445` | Service port | +| adminService.scheme | string | `"http"` | Scheme used by Hydra client endpoint. May be "http" or "https" | +| adminService.tlsTrustStorePath | string | `""` | TLS ca-cert path for hydra client | +| affinity | object | `{}` | Configure node affinity | +| deployment.args | object | `{"syncPeriod":""}` | Arguments to be passed to the program | +| deployment.args.syncPeriod | string | `""` | The minimum frequency at which watched resources are reconciled | +| deployment.automountServiceAccountToken | bool | `true` | This applications connects to the k8s API and requires the permissions | +| deployment.dnsConfig | object | `{}` | Configure pod dnsConfig. | +| deployment.extraAnnotations | object | `{}` | Deployment level extra annotations | +| deployment.extraEnv | list | `[]` | To set extra env vars for the container. | +| deployment.extraLabels | object | `{}` | Deployment level extra labels | +| deployment.extraVolumeMounts | list | `[]` | | +| deployment.extraVolumes | list | `[]` | If you want to mount external volume | +| deployment.nodeSelector | object | `{}` | Node labels for pod assignment. | +| deployment.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects | +| deployment.podMetadata.annotations | object | `{}` | Extra pod level annotations | +| deployment.podMetadata.labels | object | `{}` | Extra pod level labels | +| deployment.podSecurityContext.fsGroup | int | `65534` | | +| deployment.podSecurityContext.fsGroupChangePolicy | string | `"OnRootMismatch"` | | +| deployment.podSecurityContext.runAsGroup | int | `65534` | | +| deployment.podSecurityContext.runAsNonRoot | bool | `true` | | +| deployment.podSecurityContext.runAsUser | int | `65534` | | +| deployment.podSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| deployment.resources | object | `{}` | | +| deployment.securityContext.allowPrivilegeEscalation | bool | `false` | | +| deployment.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| deployment.securityContext.privileged | bool | `false` | | +| deployment.securityContext.readOnlyRootFilesystem | bool | `true` | | +| deployment.securityContext.runAsGroup | int | `65534` | | +| deployment.securityContext.runAsNonRoot | bool | `true` | | +| deployment.securityContext.runAsUser | int | `65534` | | +| deployment.securityContext.seLinuxOptions.level | string | `"s0:c123,c456"` | | +| deployment.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| deployment.serviceAccount | object | `{"annotations":{}}` | Configure service account | +| deployment.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| deployment.terminationGracePeriodSeconds | int | `60` | | +| deployment.tolerations | list | `[]` | Configure node tolerations. | +| deployment.topologySpreadConstraints | list | `[]` | Configure pod topologySpreadConstraints. | +| enabledNamespaces | list | `[]` | The Controller have CREATE and READ access to all Secrets in the namespaces listed below. | +| forwardedProto | string | `nil` | | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| image.repository | string | `"oryd/hydra-maester"` | Ory Hydra-maester image | +| image.tag | string | `"v0.0.36"` | Ory Hydra-maester version | +| imagePullSecrets | list | `[]` | Image pull secrets | +| pdb.enabled | bool | `false` | | +| pdb.spec.maxUnavailable | string | `""` | | +| pdb.spec.minAvailable | string | `""` | | +| priorityClassName | string | `""` | Pod priority # https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ | +| replicaCount | int | `1` | Number of replicas in deployment | +| revisionHistoryLimit | int | `5` | Number of revisions kept in history | +| singleNamespaceMode | bool | `false` | Single namespace mode. If enabled the controller will watch for resources only from namespace it is deployed in, ignoring others | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/utils/assets/charts/hydra/charts/hydra-maester/crds/crd-oauth2clients.yaml b/utils/assets/charts/hydra/charts/hydra-maester/crds/crd-oauth2clients.yaml new file mode 100644 index 0000000..ac3ad46 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/crds/crd-oauth2clients.yaml @@ -0,0 +1,364 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: oauth2clients.hydra.ory.sh +spec: + group: hydra.ory.sh + names: + kind: OAuth2Client + listKind: OAuth2ClientList + plural: oauth2clients + singular: oauth2client + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: OAuth2Client is the Schema for the oauth2clients API + properties: + apiVersion: + description: + "APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the + latest internal value, and may reject unrecognized values. More + info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" + type: string + kind: + description: + "Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the + client submits requests to. Cannot be updated. In CamelCase. + More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" + type: string + metadata: + type: object + spec: + description: + OAuth2ClientSpec defines the desired state of OAuth2Client + properties: + allowedCorsOrigins: + description: + AllowedCorsOrigins is an array of allowed CORS origins + items: + description: + RedirectURI represents a redirect URI for the client + pattern: \w+:/?/?[^\s]+ + type: string + type: array + audience: + description: + Audience is a whitelist defining the audiences this client + is allowed to request tokens for + items: + type: string + type: array + backChannelLogoutSessionRequired: + default: false + description: + BackChannelLogoutSessionRequired Boolean value specifying + whether the RP requires that a sid (session ID) Claim be + included in the Logout Token to identify the RP session with + the OP when the backchannel_logout_uri is used. If omitted, + the default value is false. + type: boolean + backChannelLogoutURI: + description: + BackChannelLogoutURI RP URL that will cause the RP to log + itself out when sent a Logout Token by the OP + pattern: (^$|^https?://.*) + type: string + clientName: + description: + ClientName is the human-readable string name of the client + to be presented to the end-user during authorization. + type: string + deletionPolicy: + description: + Indicates if a deleted OAuth2Client custom resource should + delete the database row or not. Value 1 means deletion of + the OAuth2 client, value 2 means keep an orphan oauth2 + client. + type: integer + frontChannelLogoutSessionRequired: + default: false + description: + FrontChannelLogoutSessionRequired Boolean value specifying + whether the RP requires that iss (issuer) and sid (session + ID) query parameters be included to identify the RP session + with the OP when the frontchannel_logout_uri is used + type: boolean + frontChannelLogoutURI: + description: + FrontChannelLogoutURI RP URL that will cause the RP to log + itself out when rendered in an iframe by the OP. An iss + (issuer) query parameter and a sid (session ID) query + parameter MAY be included by the OP to enable the RP to + validate the request and to determine which of the + potentially multiple sessions is to be logged out; if either + is included, both MUST be + pattern: (^$|^https?://.*) + type: string + grantTypes: + description: + GrantTypes is an array of grant types the client is allowed + to use. + items: + description: GrantType represents an OAuth 2.0 grant type + enum: + - client_credentials + - authorization_code + - implicit + - refresh_token + type: string + maxItems: 4 + minItems: 1 + type: array + hydraAdmin: + description: + HydraAdmin is the optional configuration to use for managing + this client + properties: + endpoint: + description: + Endpoint is the endpoint for the hydra instance on which + to set up the client. This value will override the value + provided to `--endpoint` (defaults to `"/clients"` in + the application) + pattern: (^$|^/.*) + type: string + forwardedProto: + description: + ForwardedProto overrides the `--forwarded-proto` flag. + The value "off" will force this to be off even if + `--forwarded-proto` is specified + pattern: (^$|https?|off) + type: string + port: + description: + Port is the port for the hydra instance on which to set + up the client. This value will override the value + provided to `--hydra-port` + maximum: 65535 + type: integer + url: + description: + URL is the URL for the hydra instance on which to set up + the client. This value will override the value provided + to `--hydra-url` + maxLength: 64 + pattern: (^$|^https?://.*) + type: string + type: object + jwksUri: + description: + JwksUri Define the URL where the JSON Web Key Set should be + fetched from when performing the private_key_jwt client + authentication method. + pattern: (^$|^https?://.*) + type: string + metadata: + description: Metadata is arbitrary data + nullable: true + type: object + x-kubernetes-preserve-unknown-fields: true + postLogoutRedirectUris: + description: + PostLogoutRedirectURIs is an array of the post logout + redirect URIs allowed for the application + items: + description: + RedirectURI represents a redirect URI for the client + pattern: \w+:/?/?[^\s]+ + type: string + type: array + redirectUris: + description: + RedirectURIs is an array of the redirect URIs allowed for + the application + items: + description: + RedirectURI represents a redirect URI for the client + pattern: \w+:/?/?[^\s]+ + type: string + type: array + responseTypes: + description: + ResponseTypes is an array of the OAuth 2.0 response type + strings that the client can use at the authorization + endpoint. + items: + description: + ResponseType represents an OAuth 2.0 response type strings + enum: + - id_token + - code + - token + - code token + - code id_token + - id_token token + - code id_token token + type: string + maxItems: 3 + minItems: 1 + type: array + scope: + description: + Scope is a string containing a space-separated list of scope + values (as described in Section 3.3 of OAuth 2.0 [RFC6749]) + that the client can use when requesting access tokens. + pattern: ([a-zA-Z0-9\.\*]+\s?)+ + type: string + secretName: + description: + SecretName points to the K8s secret that contains this + client's ID and password + maxLength: 253 + minLength: 1 + pattern: '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*' + type: string + skipConsent: + default: false + description: + SkipConsent skips the consent screen for this client. + type: boolean + tokenEndpointAuthMethod: + allOf: + - enum: + - client_secret_basic + - client_secret_post + - private_key_jwt + - none + - enum: + - client_secret_basic + - client_secret_post + - private_key_jwt + - none + description: + Indication which authentication method shoud be used for the + token endpoint + type: string + tokenLifespans: + description: Configuration about token lifespans. + properties: + authorization_code_grant_access_token_lifespan: + description: + The lifespan of the access token issued during + authorization_code grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + authorization_code_grant_id_token_lifespan: + description: + The lifespan of the id token issued during + authorization_code grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + authorization_code_grant_refresh_token_lifespan: + description: + The lifespan of the refresh token issued during + authorization_code grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + client_credentials_grant_access_token_lifespan: + description: + The lifespan of the access token issued during + client_credentials grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + implicit_grant_access_token_lifespan: + description: + The lifespan of the access token issued during implicit + grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + implicit_grant_id_token_lifespan: + description: + The lifespan of the id token issued during implicit + grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + jwt_bearer_grant_access_token_lifespan: + description: + The lifespan of the access token issued during + jwt_bearer grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + refresh_token_grant_access_token_lifespan: + description: + The lifespan of the access token issued during + refresh_token grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + refresh_token_grant_id_token_lifespan: + description: + The lifespan of the id token issued during refresh_token + grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + refresh_token_grant_refresh_token_lifespan: + description: + The lifespan of the refresh token issued during + refresh_token grant type. + pattern: "[0-9]+(ns|us|ms|s|m|h)" + type: string + type: object + required: + - grantTypes + - scope + - secretName + type: object + status: + description: + OAuth2ClientStatus defines the observed state of OAuth2Client + properties: + conditions: + items: + description: + OAuth2ClientCondition contains condition information for + an OAuth2Client + properties: + status: + enum: + - "True" + - "False" + - Unknown + type: string + type: + type: string + required: + - status + - type + type: object + type: array + observedGeneration: + description: + ObservedGeneration represents the most recent generation + observed by the daemon set controller. + format: int64 + type: integer + reconciliationError: + description: + ReconciliationError represents an error that occurred during + the reconciliation process + properties: + description: + description: + Description is the description of the reconciliation + error + type: string + statusCode: + description: + Code is the status code of the reconciliation error + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/utils/assets/charts/hydra/charts/hydra-maester/templates/_helpers.tpl b/utils/assets/charts/hydra/charts/hydra-maester/templates/_helpers.tpl new file mode 100644 index 0000000..b607c67 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/templates/_helpers.tpl @@ -0,0 +1,59 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "hydra-maester.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "hydra-maester.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "hydra-maester.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "hydra-maester.labels" -}} +app.kubernetes.io/name: {{ include "hydra-maester.name" . }} +helm.sh/chart: {{ include "hydra-maester.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + + +{{/* +Get Hydra admin service name +*/}} +{{- define "hydra-maester.adminService" -}} +{{- if .Values.hydraFullnameOverride -}} +{{- printf "%s-admin" .Values.hydraFullnameOverride -}} +{{- else if contains "hydra" .Release.Name -}} +{{- printf "%s-admin" .Release.Name -}} +{{- else -}} +{{- printf "%s-%s-admin" .Release.Name "hydra" -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/hydra/charts/hydra-maester/templates/deployment.yaml b/utils/assets/charts/hydra/charts/hydra-maester/templates/deployment.yaml new file mode 100644 index 0000000..290f4a3 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/templates/deployment.yaml @@ -0,0 +1,123 @@ +{{- if and (ne .Values.adminService.scheme "http") (ne .Values.adminService.scheme "https") -}} +{{ fail "invalid scheme: must be http or https" }} +{{- end -}} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "hydra-maester.fullname" . }} + labels: + {{- include "hydra-maester.labels" . | nindent 4 }} + {{- with .Values.deployment.extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + control-plane: controller-manager + app.kubernetes.io/name: {{ include "hydra-maester.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: {{ include "hydra-maester.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.deployment.extraLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.podMetadata.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- with .Values.deployment.extraAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.podMetadata.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.deployment.extraVolumes }} + {{- toYaml .Values.deployment.extraVolumes | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /manager + args: + - --metrics-addr=127.0.0.1:8080 + - --hydra-url={{ required "scheme is required" .Values.adminService.scheme }}://{{ .Values.adminService.name | default ( include "hydra-maester.adminService" . ) }} + - --hydra-port={{ required "port must be set and non-empty" .Values.adminService.port }} + {{- with .Values.adminService.endpoint }} + - --endpoint={{ . }} + {{- end }} + {{- if .Values.forwardedProto }} + - --forwarded-proto={{ .Values.forwardedProto }} + {{- end }} + {{- if .Values.singleNamespaceMode }} + - --namespace={{ .Release.Namespace }} + {{- end }} + {{- if .Values.deployment.args.syncPeriod }} + - --sync-period={{ .Values.deployment.args.syncPeriod }} + {{- end }} + {{- if .Values.adminService.insecureSkipVerify }} + - --insecure-skip-verify={{ .Values.adminService.insecureSkipVerify }} + {{- end}} + {{- if .Values.adminService.tlsTrustStorePath }} + - --tls-trust-store={{ .Values.adminService.tlsTrustStorePath }} + {{- end }} + volumeMounts: + {{- if .Values.deployment.extraVolumeMounts }} + {{- toYaml .Values.deployment.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.deployment.extraEnv }} + env: + {{- tpl (toYaml .Values.deployment.extraEnv) . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.deployment.resources | nindent 12 }} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + {{- if .Values.deployment.securityContext }} + securityContext: + {{- toYaml .Values.deployment.securityContext | nindent 12 }} + {{- end }} + serviceAccountName: {{ include "hydra-maester.fullname" . }}-account + automountServiceAccountToken: {{ .Values.deployment.automountServiceAccountToken }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + nodeSelector: + {{- with .Values.deployment.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/hydra/charts/hydra-maester/templates/pdb.yaml b/utils/assets/charts/hydra/charts/hydra-maester/templates/pdb.yaml new file mode 100644 index 0000000..a591fdf --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/templates/pdb.yaml @@ -0,0 +1,19 @@ +{{- if .Values.pdb.enabled -}} +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "hydra-maester.fullname" . }} +spec: + selector: + matchLabels: + control-plane: controller-manager + app.kubernetes.io/name: {{ include "hydra-maester.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.pdb.spec.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with .Values.pdb.spec.minAvailable }} + minAvailable: {{ . }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/hydra/charts/hydra-maester/templates/rbac.yaml b/utils/assets/charts/hydra/charts/hydra-maester/templates/rbac.yaml new file mode 100644 index 0000000..e67cc62 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/templates/rbac.yaml @@ -0,0 +1,95 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "hydra-maester.fullname" . }}-account + namespace: {{ .Release.Namespace }} + labels: + {{- include "hydra-maester.labels" . | nindent 4 }} + {{- with .Values.deployment.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if not .Values.singleNamespaceMode }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "hydra-maester.fullname" . }}-role +rules: + - apiGroups: ["hydra.ory.sh"] + resources: ["oauth2clients", "oauth2clients/status"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["list", "watch", "create"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "hydra-maester.fullname" . }}-role-binding +subjects: + - kind: ServiceAccount + name: {{ include "hydra-maester.fullname" . }}-account # Service account assigned to the controller pod. + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "hydra-maester.fullname" . }}-role +{{- end }} +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "hydra-maester.fullname" . }}-role + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create"] + - apiGroups: ["hydra.ory.sh"] + resources: ["oauth2clients", "oauth2clients/status"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "hydra-maester.fullname" . }}-role-binding + namespace: {{ .Release.Namespace }} +subjects: + - kind: ServiceAccount + name: {{ include "hydra-maester.fullname" . }}-account # Service account assigned to the controller pod. + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "hydra-maester.fullname" . }}-role + +{{- $name := include "hydra-maester.fullname" . -}} +{{- $namespace := .Release.Namespace -}} +{{- range .Values.enabledNamespaces }} +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ $name }}-role + namespace: {{ . }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "create", "update"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ $name }}-role-binding + namespace: {{ . }} +subjects: + - kind: ServiceAccount + name: {{ $name }}-account # Service account assigned to the controller pod. + namespace: {{ $namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ $name }}-role +{{- end }} diff --git a/utils/assets/charts/hydra/charts/hydra-maester/values.yaml b/utils/assets/charts/hydra/charts/hydra-maester/values.yaml new file mode 100644 index 0000000..08bc086 --- /dev/null +++ b/utils/assets/charts/hydra/charts/hydra-maester/values.yaml @@ -0,0 +1,159 @@ +# -- Number of replicas in deployment +replicaCount: 1 +# -- Number of revisions kept in history +revisionHistoryLimit: 5 +# -- The Controller have CREATE and READ access to all Secrets in the namespaces listed below. +enabledNamespaces: [] + +# -- Single namespace mode. If enabled the controller will watch for resources only from namespace it is deployed in, ignoring others +singleNamespaceMode: false + +image: + # -- Ory Hydra-maester image + repository: oryd/hydra-maester + # -- Ory Hydra-maester version + tag: v0.0.36 + # -- Image pull policy + pullPolicy: IfNotPresent + +# -- Image pull secrets +imagePullSecrets: [] + +# -- Pod priority +## https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +priorityClassName: "" + +## -- Connection data to admin service of Hydra +adminService: + # -- Service name + name: + # -- Service port + port: 4445 + # -- Set the clients endpoint, should be `/clients` for Hydra 1.x and + # `/admin/clients` for Hydra 2.x + endpoint: /admin/clients + # -- Scheme used by Hydra client endpoint. May be "http" or "https" + scheme: http + # -- TLS ca-cert path for hydra client + tlsTrustStorePath: "" + # -- Skip http client insecure verification + insecureSkipVerify: false + +forwardedProto: + +## -- Deployment specific config +deployment: + resources: + {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 30Mi + # requests: + # cpu: 100m + # memory: 20Mi + + # -- To set extra env vars for the container. + extraEnv: [] + + # -- If you want to mount external volume + extraVolumes: [] + # - name: my-volume + # secret: + # secretName: my-secret + extraVolumeMounts: [] + # - name: my-volume + # mountPath: /etc/secrets/my-secret + # readOnly: true + + ## -- pod securityContext + podSecurityContext: + fsGroupChangePolicy: "OnRootMismatch" + runAsNonRoot: true + runAsUser: 65534 + fsGroup: 65534 + runAsGroup: 65534 + seccompProfile: + type: RuntimeDefault + + ## -- container securityContext + securityContext: + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + allowPrivilegeEscalation: false + privileged: false + seLinuxOptions: + level: "s0:c123,c456" + + # -- Node labels for pod assignment. + nodeSelector: {} + # If you do want to specify node labels, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'annotations:'. + # foo: bar + + # -- Configure node tolerations. + tolerations: [] + # -- Deployment level extra annotations + extraAnnotations: {} + # -- Deployment level extra labels + extraLabels: {} + + # -- Configure pod topologySpreadConstraints. + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app.kubernetes.io/name: hydra + # app.kubernetes.io/instance: hydra + + # -- Configure pod dnsConfig. + dnsConfig: {} + # options: + # - name: "ndots" + # value: "1" + + # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + # -- Extra pod level labels + labels: {} + # -- Extra pod level annotations + annotations: {} + + # https://github.com/kubernetes/kubernetes/issues/57601 + # -- This applications connects to the k8s API and requires the permissions + automountServiceAccountToken: true + + terminationGracePeriodSeconds: 60 + + # -- Arguments to be passed to the program + args: + # -- The minimum frequency at which watched resources are reconciled + syncPeriod: "" + # syncPeriod: 10h + + # -- Configure service account + serviceAccount: + # -- Annotations to add to the service account + annotations: {} + +# -- Configure node affinity +affinity: {} + +## -- PodDistributionBudget configuration +pdb: + enabled: false + spec: + minAvailable: "" + maxUnavailable: "" diff --git a/utils/assets/charts/hydra/charts/ory-commons/.helmignore b/utils/assets/charts/hydra/charts/ory-commons/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/utils/assets/charts/hydra/charts/ory-commons/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/hydra/charts/ory-commons/Chart.yaml b/utils/assets/charts/hydra/charts/ory-commons/Chart.yaml new file mode 100644 index 0000000..35269f4 --- /dev/null +++ b/utils/assets/charts/hydra/charts/ory-commons/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 0.0.0 +description: 'Collection of helper function for the Ory Helm environment ' +name: ory-commons +type: library +version: 0.1.0 diff --git a/utils/assets/charts/hydra/charts/ory-commons/templates/_helpers.tpl b/utils/assets/charts/hydra/charts/ory-commons/templates/_helpers.tpl new file mode 100644 index 0000000..531b34c --- /dev/null +++ b/utils/assets/charts/hydra/charts/ory-commons/templates/_helpers.tpl @@ -0,0 +1,12 @@ +{{/* +Check if list contains object +*/}} +{{- define "ory.extraEnvContainsEnvName" -}} + {{- $extraEnvs := index . 0 -}} + {{- $envName := index . 1 -}} + {{- range $k, $v := $extraEnvs -}} + {{- if eq $v.name $envName -}} + found + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/hydra/files/watch.sh b/utils/assets/charts/hydra/files/watch.sh new file mode 100644 index 0000000..cb5b44b --- /dev/null +++ b/utils/assets/charts/hydra/files/watch.sh @@ -0,0 +1,17 @@ +set -Eeuo pipefail +set -x + +function rollOut() { + DEPLOY=$(kubectl get deploy -n "${NAMESPACE}" -l "${1}" -o name) + kubectl set env -n $NAMESPACE ${DEPLOY} sync=$(date "+%Y%m%d-%H%M%S") + kubectl rollout status -n $NAMESPACE ${DEPLOY} +} + +while true; do + # After change in the CM the symlink is recreated, so we need to restart the monitor + inotifywait --event DELETE_SELF "${WATCH_FILE}" | + while read path _ file; do + echo "---> $path$file modified" + rollOut "${LABEL_SELECTOR}" + done +done diff --git a/utils/assets/charts/hydra/templates/_helpers.tpl b/utils/assets/charts/hydra/templates/_helpers.tpl new file mode 100644 index 0000000..5b9b246 --- /dev/null +++ b/utils/assets/charts/hydra/templates/_helpers.tpl @@ -0,0 +1,229 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "hydra.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "hydra.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "hydra.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Ensure there is always a way to track down source of the deployment. +It is unlikely AppVersion will be missing, but we will fallback on the +chart's version in that case. +*/}} +{{- define "hydra.version" -}} +{{- if .Chart.AppVersion }} +{{- .Chart.AppVersion -}} +{{- else -}} +{{- printf "v%s" .Chart.Version -}} +{{- end -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "hydra.labels" -}} +"app.kubernetes.io/name": {{ include "hydra.name" . | quote }} +"app.kubernetes.io/instance": {{ .Release.Name | quote }} +"app.kubernetes.io/version": {{ include "hydra.version" . | quote }} +"app.kubernetes.io/managed-by": {{ .Release.Service | quote }} +"helm.sh/chart": {{ include "hydra.chart" . | quote }} +{{- if $.Values.watcher.enabled }} +{{ printf "\"%s\": \"%s\"" $.Values.watcher.watchLabelKey (include "hydra.name" .) }} +{{- end }} +{{- end -}} + +{{/* +Generate the dsn value +*/}} +{{- define "hydra.dsn" -}} +{{- if .Values.demo -}} +memory +{{- else if and .Values.secret.nameOverride (not .Values.secret.enabled) -}} +dsn-loaded-from-env +{{- else if not (empty (.Values.hydra.config.dsn)) -}} +{{- .Values.hydra.config.dsn }} +{{- end -}} +{{- end -}} + +{{/* +Generate the name of the secret resource containing secrets +*/}} +{{- define "hydra.secretname" -}} +{{- if .Values.secret.nameOverride -}} +{{- .Values.secret.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{ include "hydra.fullname" . }} +{{- end -}} +{{- end -}} + +{{/* +Generate the secrets.system value +*/}} +{{- define "hydra.secrets.system" -}} + {{- if (.Values.hydra.config.secrets).system -}} + {{- if kindIs "slice" .Values.hydra.config.secrets.system -}} + {{- if gt (len .Values.hydra.config.secrets.system) 1 -}} + "{{- join "\",\"" .Values.hydra.config.secrets.system -}}" + {{- else -}} + {{- join "" .Values.hydra.config.secrets.system -}} + {{- end -}} + {{- else -}} + {{- fail "Expected hydra.config.secrets.system to be a list of strings" -}} + {{- end -}} + {{- else if .Values.demo -}} + a-very-insecure-secret-for-checking-out-the-demo + {{- end -}} +{{- end -}} + +{{/* +Generate the secrets.cookie value +*/}} +{{- define "hydra.secrets.cookie" -}} + {{- if (.Values.hydra.config.secrets).cookie -}} + {{- if kindIs "slice" .Values.hydra.config.secrets.cookie -}} + {{- if gt (len .Values.hydra.config.secrets.cookie) 1 -}} + "{{- join "\",\"" .Values.hydra.config.secrets.cookie -}}" + {{- else -}} + {{- join "" .Values.hydra.config.secrets.cookie -}} + {{- end -}} + {{- else -}} + {{- fail "Expected hydra.config.secrets.cookie to be a list of strings" -}} + {{- end -}} + {{- else -}} + {{- include "hydra.secrets.system" . }} + {{- end -}} +{{- end -}} + +{{/* +Generate the configmap data, redacting secrets +*/}} +{{- define "hydra.configmap" -}} +{{- $config := omit .Values.hydra.config "dsn" "secrets" -}} +{{- tpl (toYaml $config) . -}} +{{- end -}} + +{{/* +Generate the urls.issuer value +*/}} +{{- define "hydra.config.urls.issuer" -}} +{{- if .Values.hydra.config.urls.self.issuer -}} +{{- .Values.hydra.config.urls.self.issuer }} +{{- else if .Values.ingress.public.enabled -}} +{{- $host := index .Values.ingress.public.hosts 0 -}} +http{{ if $.Values.ingress.public.tls }}s{{ end }}://{{ $host.host }} +{{- else if contains "ClusterIP" .Values.service.public.type -}} +http://127.0.0.1:{{ .Values.service.public.port }}/ +{{- end -}} +{{- end -}} + +{{/* +Check overrides consistency +*/}} +{{- define "hydra.check.override.consistency" -}} +{{- if and .Values.maester.enabled .Values.fullnameOverride -}} +{{- if not .Values.maester.hydraFullnameOverride -}} +{{ fail "hydra fullname has been overridden, but the new value has not been provided to maester. Set maester.hydraFullnameOverride" }} +{{- else if not (eq .Values.maester.hydraFullnameOverride .Values.fullnameOverride) -}} +{{ fail (tpl "hydra fullname has been overridden, but a different value was provided to maester. {{ .Values.maester.hydraFullnameOverride }} different of {{ .Values.fullnameOverride }}" . ) }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{- define "hydra.utils.joinListWithComma" -}} +{{- $local := dict "first" true -}} +{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "hydra.serviceAccountName" -}} +{{- if .Values.deployment.serviceAccount.create }} +{{- default (include "hydra.fullname" .) .Values.deployment.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.deployment.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account for the Job to use +*/}} +{{- define "hydra.job.serviceAccountName" -}} +{{- if .Values.job.serviceAccount.create }} +{{- printf "%s-job" (default (include "hydra.fullname" .) .Values.job.serviceAccount.name) }} +{{- else }} +{{- include "hydra.serviceAccountName" . }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account for the Job to use +*/}} +{{- define "hydra.cronjob.janitor.serviceAccountName" -}} +{{- if .Values.cronjob.janitor.serviceAccount.create }} +{{- printf "%s-cronjob-janitor" (default (include "hydra.fullname" .) .Values.cronjob.janitor.serviceAccount.name) }} +{{- else }} +{{- include "hydra.serviceAccountName" . }} +{{- end }} +{{- end }} + +{{/* +Checksum annotations generated from configmaps and secrets +*/}} +{{- define "hydra.annotations.checksum" -}} +{{- if .Values.configmap.hashSumEnabled }} +checksum/hydra-config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} +{{- end }} +{{- if and .Values.secret.enabled .Values.secret.hashSumEnabled }} +checksum/hydra-secrets: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} +{{- end }} +{{- end }} + +{{/* +Check the migration type value and fail if unexpected +*/}} +{{- define "hydra.automigration.typeVerification" -}} +{{- if and .Values.hydra.automigration.enabled .Values.hydra.automigration.type }} + {{- if and (ne .Values.hydra.automigration.type "initContainer") (ne .Values.hydra.automigration.type "job") }} + {{- fail "hydra.automigration.type must be either 'initContainer' or 'job'" -}} + {{- end }} +{{- end }} +{{- end }} + +{{/* +Common labels for the janitor cron job +*/}} +{{- define "hydra.janitor.labels" -}} +"app.kubernetes.io/name": {{ printf "%s-janitor" (include "hydra.name" .) | quote }} +"app.kubernetes.io/instance": {{ .Release.Name | quote }} +"app.kubernetes.io/version": {{ include "hydra.version" . | quote }} +"app.kubernetes.io/managed-by": {{ .Release.Service | quote }} +"app.kubernetes.io/component": janitor +"helm.sh/chart": {{ include "hydra.chart" . | quote }} +{{- end -}} diff --git a/utils/assets/charts/hydra/templates/configmap-automigrate.yaml b/utils/assets/charts/hydra/templates/configmap-automigrate.yaml new file mode 100644 index 0000000..6dbcc88 --- /dev/null +++ b/utils/assets/charts/hydra/templates/configmap-automigrate.yaml @@ -0,0 +1,18 @@ +{{- if and ( .Values.hydra.automigration.enabled ) ( eq .Values.hydra.automigration.type "job" ) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "hydra.fullname" . }}-migrate + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + annotations: + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" +data: + "hydra.yaml": | + {{- include "hydra.configmap" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/configmap.yaml b/utils/assets/charts/hydra/templates/configmap.yaml new file mode 100644 index 0000000..0f84335 --- /dev/null +++ b/utils/assets/charts/hydra/templates/configmap.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "hydra.fullname" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} +data: + "hydra.yaml": | + {{- include "hydra.configmap" . | nindent 4 }} diff --git a/utils/assets/charts/hydra/templates/deployment-watcher.yaml b/utils/assets/charts/hydra/templates/deployment-watcher.yaml new file mode 100644 index 0000000..a039380 --- /dev/null +++ b/utils/assets/charts/hydra/templates/deployment-watcher.yaml @@ -0,0 +1,77 @@ +{{- if .Values.watcher.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "hydra.fullname" . }}-watcher + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "hydra.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.deployment.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + revisionHistoryLimit: {{ .Values.watcher.revisionHistoryLimit }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "hydra.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "hydra.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.watcher.podMetadata.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- with .Values.watcher.podMetadata.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + automountServiceAccountToken: {{ .Values.watcher.automountServiceAccountToken }} + serviceAccountName: {{ include "hydra.serviceAccountName" . }}-watcher + terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} + containers: + - name: watcher + {{- with .Values.watcher.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ .Values.watcher.image }} + command: + - /bin/bash + - -c + - | + {{- .Files.Get "files/watch.sh" | printf "%s" | nindent 14 }} + env: + - name: NAMESPACE + value: {{ .Release.Namespace | quote }} + - name: WATCH_FILE + value: {{ .Values.watcher.mountFile | quote }} + - name: LABEL_SELECTOR + value: '{{ $.Values.watcher.watchLabelKey }}={{ include "hydra.name" . }}' + resources: + {{- toYaml .Values.watcher.resources | nindent 12 }} + volumeMounts: + {{- with .Values.deployment.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.watcher.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.deployment.extraVolumes }} + {{- toYaml .Values.deployment.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/deployment.yaml b/utils/assets/charts/hydra/templates/deployment.yaml new file mode 100644 index 0000000..fa266bd --- /dev/null +++ b/utils/assets/charts/hydra/templates/deployment.yaml @@ -0,0 +1,236 @@ +{{- include "hydra.automigration.typeVerification" . -}} +{{- $migrationExtraEnv := ternary .Values.deployment.automigration.extraEnv .Values.deployment.extraEnv (not (empty .Values.deployment.automigration.extraEnv )) -}} + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "hydra.fullname" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.deployment.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.deployment.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} +{{- end }} + revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }} + strategy: + {{- toYaml .Values.deployment.strategy | nindent 4 }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "hydra.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + {{- include "hydra.labels" . | nindent 8 }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $.Values.deployment.podMetadata.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- include "hydra.annotations.checksum" . | nindent 8 -}} + {{- with .Values.deployment.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $.Values.deployment.podMetadata.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: {{ include "hydra.name" . }}-config-volume + configMap: + name: {{ include "hydra.fullname" . }} + {{- if .Values.deployment.extraVolumes }} + {{- toYaml .Values.deployment.extraVolumes | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "hydra.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.deployment.automountServiceAccountToken }} + terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: {{- toYaml .Values.hydra.command | nindent 12 }} + {{- if .Values.hydra.customArgs }} + args: {{- toYaml .Values.hydra.customArgs | nindent 12 }} + {{- else }} + args: + - serve + - all + {{- if .Values.hydra.dev }} + - "--dev" + {{- end }} + - --config + - /etc/config/hydra.yaml + {{- end }} + volumeMounts: + - name: {{ include "hydra.name" . }}-config-volume + mountPath: /etc/config + readOnly: true + {{- if .Values.deployment.extraVolumeMounts }} + {{- toYaml .Values.deployment.extraVolumeMounts | nindent 12 }} + {{- end }} + ports: + - name: http-public + containerPort: {{ .Values.hydra.config.serve.public.port }} + protocol: TCP + - name: http-admin + containerPort: {{ .Values.hydra.config.serve.admin.port }} + protocol: TCP + {{- if .Values.deployment.customLivenessProbe }} + livenessProbe: + {{- toYaml .Values.deployment.customLivenessProbe | nindent 12 }} + {{- end }} + readinessProbe: + {{- if .Values.deployment.customReadinessProbe }} + {{- toYaml .Values.deployment.customReadinessProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health/alive + port: {{ .Values.hydra.config.serve.admin.port }} + httpHeaders: + - name: Host + value: '127.0.0.1' + {{- toYaml .Values.deployment.readinessProbe | nindent 12 }} + {{- end }} + startupProbe: + {{- if .Values.deployment.customStartupProbe }} + {{- toYaml .Values.deployment.customStartupProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health/ready + port: {{ .Values.hydra.config.serve.admin.port }} + httpHeaders: + - name: Host + value: '127.0.0.1' + {{- toYaml .Values.deployment.startupProbe | nindent 12 }} + {{- end }} + env: + {{- $issuer := include "hydra.config.urls.issuer" . -}} + {{- if $issuer }} + - name: URLS_SELF_ISSUER + value: {{ $issuer | quote }} + {{- end }} + {{- if not (empty ( include "hydra.dsn" . )) }} + {{- if not (include "ory.extraEnvContainsEnvName" (list .Values.deployment.extraEnv "DSN")) }} + - name: DSN + valueFrom: + secretKeyRef: + name: {{ include "hydra.secretname" . }} + key: dsn + {{- end }} + {{- end }} + - name: SECRETS_SYSTEM + valueFrom: + secretKeyRef: + name: {{ include "hydra.secretname" . }} + key: secretsSystem + - name: SECRETS_COOKIE + valueFrom: + secretKeyRef: + name: {{ include "hydra.secretname" . }} + key: secretsCookie + {{- if .Values.deployment.extraEnv }} + {{- tpl (toYaml .Values.deployment.extraEnv) . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.deployment.resources | nindent 12 }} + {{- if .Values.deployment.securityContext }} + securityContext: + {{- toYaml .Values.deployment.securityContext | nindent 12 }} + {{- end }} + lifecycle: + {{- toYaml .Values.deployment.lifecycle | nindent 12 }} + {{- if .Values.deployment.extraContainers }} + {{- tpl .Values.deployment.extraContainers . | nindent 8 }} + {{- end }} + initContainers: + {{- if .Values.deployment.extraInitContainers }} + {{- tpl .Values.deployment.extraInitContainers . | nindent 8 }} + {{- end }} + {{- if and ( .Values.hydra.automigration.enabled ) ( eq .Values.hydra.automigration.type "initContainer" ) }} + - name: {{ .Chart.Name }}-automigrate + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.hydra.automigration.customCommand }} + command: {{- toYaml .Values.hydra.automigration.customCommand | nindent 12 }} + {{- else }} + command: ["hydra"] + {{- end }} + {{- if .Values.hydra.automigration.customArgs }} + args: {{- toYaml .Values.hydra.automigration.customArgs | nindent 12 }} + {{- else }} + args: ["migrate", "sql", "-e", "--yes", "--config", "/etc/config/hydra.yaml"] + {{- end }} + volumeMounts: + - name: {{ include "hydra.name" . }}-config-volume + mountPath: /etc/config + readOnly: true + {{- with .Values.deployment.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + env: + {{- if not (empty ( include "hydra.dsn" . )) }} + {{- if not (include "ory.extraEnvContainsEnvName" (list $migrationExtraEnv "DSN")) }} + - name: DSN + valueFrom: + secretKeyRef: + name: {{ include "hydra.secretname" . }} + key: dsn + {{- end }} + {{- end }} + {{- if $migrationExtraEnv }} + {{- tpl (toYaml $migrationExtraEnv) . | nindent 12 }} + {{- end }} + {{- if .Values.hydra.automigration.resources }} + resources: + {{- toYaml .Values.hydra.automigration.resources | nindent 12 }} + {{- end }} + {{- with .Values.deployment.initContainerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- with .Values.deployment.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/hydra/templates/hpa.yaml b/utils/assets/charts/hydra/templates/hpa.yaml new file mode 100644 index 0000000..5c4f5df --- /dev/null +++ b/utils/assets/charts/hydra/templates/hpa.yaml @@ -0,0 +1,36 @@ +{{- if .Values.deployment.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + name: {{ include "hydra.fullname" . }} + labels: + {{- include "hydra.labels" . | nindent 4 }} +spec: + {{- with .Values.deployment.autoscaling.behavior }} + behavior: {{- toYaml . | nindent 4 }} + {{- end }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "hydra.fullname" . }} + minReplicas: {{ .Values.deployment.autoscaling.minReplicas }} + maxReplicas: {{ .Values.deployment.autoscaling.maxReplicas }} + metrics: + {{- with .Values.deployment.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + target: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.autoscaling.targetCPU}} + - type: Resource + resource: + name: cpu + target: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/ingress-admin.yaml b/utils/assets/charts/hydra/templates/ingress-admin.yaml new file mode 100644 index 0000000..129ea28 --- /dev/null +++ b/utils/assets/charts/hydra/templates/ingress-admin.yaml @@ -0,0 +1,54 @@ +{{- if .Values.ingress.admin.enabled -}} +{{- $fullName := include "hydra.fullname" . -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else -}} +apiVersion: networking.k8s.io/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-admin + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.ingress.admin.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.admin.className }} + {{- if .Values.ingress.admin.tls }} + tls: + {{- range .Values.ingress.admin.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.admin.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if .pathType }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }}-admin + port: + name: {{ $.Values.service.admin.name }} + {{- else }} + serviceName: {{ $fullName }}-admin + servicePort: {{ $.Values.service.admin.name }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/ingress-public.yaml b/utils/assets/charts/hydra/templates/ingress-public.yaml new file mode 100644 index 0000000..45d3f2a --- /dev/null +++ b/utils/assets/charts/hydra/templates/ingress-public.yaml @@ -0,0 +1,54 @@ +{{- if or .Values.ingress.public.enabled .Values.demo -}} +{{- $fullName := include "hydra.fullname" . -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else -}} +apiVersion: networking.k8s.io/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-public + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.ingress.public.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.public.className }} + {{- if .Values.ingress.public.tls }} + tls: + {{- range .Values.ingress.public.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.public.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if .pathType }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }}-public + port: + name: {{ $.Values.service.public.name }} + {{- else }} + serviceName: {{ $fullName }}-public + servicePort: {{ $.Values.service.public.name }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/janitor-cron-job-rbac.yaml b/utils/assets/charts/hydra/templates/janitor-cron-job-rbac.yaml new file mode 100644 index 0000000..8a1d92d --- /dev/null +++ b/utils/assets/charts/hydra/templates/janitor-cron-job-rbac.yaml @@ -0,0 +1,17 @@ +{{- if .Values.cronjob.janitor.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "hydra.cronjob.janitor.serviceAccountName" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.cronjob.janitor.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: false +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/hydra/templates/janitor-cron-job.yaml b/utils/assets/charts/hydra/templates/janitor-cron-job.yaml new file mode 100644 index 0000000..aa52036 --- /dev/null +++ b/utils/assets/charts/hydra/templates/janitor-cron-job.yaml @@ -0,0 +1,137 @@ +{{- if .Values.janitor.enabled -}} +{{- $janitorExtraEnv := ternary .Values.cronjob.janitor.extraEnv .Values.deployment.extraEnv (not (empty .Values.cronjob.janitor.extraEnv )) -}} +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "hydra.fullname" . }}-janitor + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.janitor.labels" . | nindent 4 }} + {{- with .Values.cronjob.janitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.cronjob.janitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + concurrencyPolicy: Forbid + schedule: {{ .Values.cronjob.janitor.schedule | quote }} + jobTemplate: + spec: + template: + metadata: + labels: + {{- include "hydra.janitor.labels" . | nindent 12 }} + {{- with .Values.cronjob.janitor.labels }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cronjob.janitor.podMetadata.labels }} + {{- toYaml . | nindent 12 }} + {{- end }} + annotations: + {{- include "hydra.annotations.checksum" . | nindent 12 -}} + {{- with .Values.cronjob.janitor.annotations }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with $.Values.cronjob.janitor.podMetadata.annotations }} + {{- toYaml . | nindent 12 }} + {{- end }} + spec: + restartPolicy: OnFailure + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 12 }} + {{- end }} + serviceAccountName: {{ include "hydra.cronjob.janitor.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.cronjob.janitor.automountServiceAccountToken }} + volumes: + - name: {{ include "hydra.name" . }}-config-volume + configMap: + name: {{ include "hydra.fullname" . }} + {{- if .Values.cronjob.janitor.extraVolumes }} + {{- toYaml .Values.cronjob.janitor.extraVolumes | nindent 12 }} + {{- end }} + containers: + - name: janitor + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.cronjob.janitor.securityContext }} + securityContext: + {{- toYaml . | nindent 16 }} + {{- end }} + {{- if .Values.cronjob.janitor.customCommand }} + command: {{- toYaml .Values.cronjob.janitor.customCommand | nindent 14 }} + {{- else }} + command: ["hydra"] + {{- end }} + {{- if .Values.cronjob.janitor.customArgs }} + args: {{- toYaml .Values.cronjob.janitor.customArgs | nindent 14 }} + {{- else }} + args: + - janitor + {{- if .Values.janitor.cleanupGrants }} + - --grants + {{- end }} + {{- if .Values.janitor.cleanupRequests }} + - --requests + {{- end }} + {{- if .Values.janitor.cleanupTokens }} + - --tokens + {{- end }} + - --batch-size + - {{ .Values.janitor.batchSize | quote }} + - --limit + - {{ .Values.janitor.limit | quote }} + - --config + - /etc/config/hydra.yaml + {{- end }} + env: + {{- if not (empty ( include "hydra.dsn" . )) }} + {{- if not (include "ory.extraEnvContainsEnvName" (list $janitorExtraEnv "DSN")) }} + - name: DSN + valueFrom: + secretKeyRef: + name: {{ include "hydra.secretname" . }} + key: dsn + {{- end }} + {{- end }} + {{- with $janitorExtraEnv }} + {{- toYaml . | nindent 16 }} + {{- end }} + resources: + {{- toYaml .Values.cronjob.janitor.resources | nindent 16 }} + volumeMounts: + - name: {{ include "hydra.name" . }}-config-volume + mountPath: /etc/config + readOnly: true + {{- if .Values.cronjob.janitor.extraVolumeMounts }} + {{- toYaml .Values.cronjob.janitor.extraVolumeMounts | nindent 16 }} + {{- end }} + {{- if .Values.cronjob.janitor.extraContainers }} + {{- tpl .Values.cronjob.janitor.extraContainers . | nindent 12 }} + {{- end }} + {{- if .Values.cronjob.janitor.extraInitContainers }} + initContainers: + {{- tpl .Values.cronjob.janitor.extraInitContainers . | nindent 10 }} + {{- end }} + {{- with .Values.cronjob.janitor.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cronjob.janitor.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cronjob.janitor.tolerations }} + tolerations: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.cronjob.janitor.affinity }} + affinity: + {{- toYaml . | nindent 12 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/job-migration.yaml b/utils/assets/charts/hydra/templates/job-migration.yaml new file mode 100644 index 0000000..56cf3e8 --- /dev/null +++ b/utils/assets/charts/hydra/templates/job-migration.yaml @@ -0,0 +1,125 @@ +{{- include "hydra.automigration.typeVerification" . -}} +{{- if and ( .Values.hydra.automigration.enabled ) ( eq .Values.hydra.automigration.type "job" ) }} +{{- $nodeSelector := ternary .Values.job.nodeSelector .Values.deployment.nodeSelector (not (empty .Values.job.nodeSelector )) -}} +{{- $migrationExtraEnv := ternary .Values.job.extraEnv .Values.deployment.extraEnv (not (empty .Values.job.extraEnv )) -}} +{{- $resources := ternary .Values.job.resources .Values.hydra.automigration.resources (not (empty .Values.job.resources)) -}} + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "hydra.fullname" . }}-automigrate + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.job.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.job.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + template: + metadata: + annotations: + {{- with .Values.job.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.job.podMetadata.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "hydra.fullname" . }}-automigrate + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.job.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.job.podMetadata.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "hydra.job.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.job.automountServiceAccountToken }} + containers: + - name: {{ .Chart.Name }}-automigrate + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.hydra.automigration.customCommand }} + command: {{- toYaml .Values.hydra.automigration.customCommand | nindent 10 }} + {{- else }} + command: ["hydra"] + {{- end }} + {{- if .Values.hydra.automigration.customArgs }} + args: {{- toYaml .Values.hydra.automigration.customArgs | nindent 10 }} + {{- else }} + args: ["migrate", "sql", "-e", "--yes", "--config", "/etc/config/hydra.yaml"] + {{- end }} + env: + {{- if not (empty ( include "hydra.dsn" . )) }} + {{- if not (include "ory.extraEnvContainsEnvName" (list $migrationExtraEnv "DSN")) }} + - name: DSN + valueFrom: + secretKeyRef: + name: {{ include "hydra.secretname" . }} + key: dsn + {{- end }} + {{- end }} + {{- with $migrationExtraEnv }} + {{- toYaml . | nindent 10 }} + {{- end }} + lifecycle: + {{- if .Values.job.lifecycle }} + {{- tpl .Values.job.lifecycle . | nindent 10 }} + {{- end }} + {{- with .Values.deployment.securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with $resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + volumeMounts: + - name: {{ include "hydra.name" . }}-config-volume + mountPath: /etc/config + readOnly: true + {{- if .Values.deployment.extraVolumeMounts }} + {{- toYaml .Values.deployment.extraVolumeMounts | nindent 10 }} + {{- end }} + {{- if .Values.job.extraContainers }} + {{- tpl .Values.job.extraContainers . | nindent 6 }} + {{- end }} + {{- if .Values.job.extraInitContainers }} + initContainers: + {{- tpl .Values.job.extraInitContainers . | nindent 8 }} + {{- end }} + restartPolicy: Never + {{- with .Values.deployment.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + shareProcessNamespace: {{ .Values.job.shareProcessNamespace }} + volumes: + - name: {{ include "hydra.name" . }}-config-volume + configMap: + name: {{ include "hydra.fullname" . }}-migrate + {{- if .Values.deployment.extraVolumes }} + {{- toYaml .Values.deployment.extraVolumes | nindent 8 }} + {{- end }} + {{- with $nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.job.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + backoffLimit: {{ .Values.job.spec.backoffLimit }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/job-rbac.yaml b/utils/assets/charts/hydra/templates/job-rbac.yaml new file mode 100644 index 0000000..96998d8 --- /dev/null +++ b/utils/assets/charts/hydra/templates/job-rbac.yaml @@ -0,0 +1,17 @@ +{{- if .Values.job.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "hydra.job.serviceAccountName" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.job.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: false +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/hydra/templates/pdb.yaml b/utils/assets/charts/hydra/templates/pdb.yaml new file mode 100644 index 0000000..32c5df5 --- /dev/null +++ b/utils/assets/charts/hydra/templates/pdb.yaml @@ -0,0 +1,18 @@ +{{- if .Values.pdb.enabled -}} +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "hydra.fullname" . }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "hydra.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.pdb.spec.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with .Values.pdb.spec.minAvailable }} + minAvailable: {{ . }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/hydra/templates/rbac-watcher.yaml b/utils/assets/charts/hydra/templates/rbac-watcher.yaml new file mode 100644 index 0000000..d684993 --- /dev/null +++ b/utils/assets/charts/hydra/templates/rbac-watcher.yaml @@ -0,0 +1,53 @@ +{{- if .Values.watcher.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "hydra.serviceAccountName" . }}-watcher + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "hydra.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} +automountServiceAccountToken: false +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "hydra.fullname" . }}-watcher + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: + - list + - watch + - get + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: + - get + - list + - patch + - update + - watch + resourceNames: + - {{ include "hydra.fullname" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "hydra.fullname" . }}-watcher + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "hydra.fullname" . }}-watcher +subjects: + - kind: ServiceAccount + name: {{ include "hydra.fullname" . }}-watcher + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/rbac.yaml b/utils/assets/charts/hydra/templates/rbac.yaml new file mode 100644 index 0000000..3194899 --- /dev/null +++ b/utils/assets/charts/hydra/templates/rbac.yaml @@ -0,0 +1,17 @@ +{{- if .Values.deployment.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "hydra.serviceAccountName" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.deployment.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: false +{{- end }} diff --git a/utils/assets/charts/hydra/templates/secrets.yaml b/utils/assets/charts/hydra/templates/secrets.yaml new file mode 100644 index 0000000..4220c64 --- /dev/null +++ b/utils/assets/charts/hydra/templates/secrets.yaml @@ -0,0 +1,21 @@ +{{- if .Values.secret.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "hydra.secretname" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + annotations: + {{- with .Values.secret.secretAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +type: Opaque +data: + # Generate a random secret if the user doesn't give one. User given password has priority + secretsSystem: {{ ( include "hydra.secrets.system" . | default ( randAlphaNum 32 )) | required "Value secrets.system can not be empty!" | b64enc | quote }} + secretsCookie: {{ ( include "hydra.secrets.cookie" . | default ( randAlphaNum 32 )) | required "Value secrets.cookie can not be empty!" | b64enc | quote }} + dsn: {{ include "hydra.dsn" . | b64enc | quote }} +{{- end -}} diff --git a/utils/assets/charts/hydra/templates/service-admin.yaml b/utils/assets/charts/hydra/templates/service-admin.yaml new file mode 100644 index 0000000..100d958 --- /dev/null +++ b/utils/assets/charts/hydra/templates/service-admin.yaml @@ -0,0 +1,71 @@ +{{- if .Values.service.admin.enabled -}} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "hydra.fullname" . }}-admin + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.service.admin.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + app.kubernetes.io/component: admin + annotations: + {{- with .Values.service.admin.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.admin.type }} + {{- if eq .Values.service.admin.type "LoadBalancer" }} + {{- with .Values.service.admin.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- end }} + ports: + - port: {{ .Values.service.admin.port }} + targetPort: http-admin + protocol: TCP + name: {{ .Values.service.admin.name }} + selector: + app.kubernetes.io/name: {{ include "hydra.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Values.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "hydra.fullname" . }}-admin + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/component: admin + {{- include "hydra.labels" . | nindent 4 }} +{{- with .Values.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} +{{- end }} + {{- with .Values.service.admin.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + - path: {{ .Values.service.admin.metricsPath }} + port: {{ .Values.service.admin.name }} + scheme: {{ .Values.serviceMonitor.scheme }} + interval: {{ .Values.serviceMonitor.scrapeInterval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + {{- with .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 6 }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "hydra.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: admin +{{- end -}} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/service-public.yaml b/utils/assets/charts/hydra/templates/service-public.yaml new file mode 100644 index 0000000..570aad2 --- /dev/null +++ b/utils/assets/charts/hydra/templates/service-public.yaml @@ -0,0 +1,33 @@ +{{- if .Values.service.public.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "hydra.fullname" . }}-public + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.service.public.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.service.public.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.public.type }} + {{- if eq .Values.service.public.type "LoadBalancer" }} + {{- with .Values.service.public.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- end }} + ports: + - port: {{ .Values.service.public.port }} + targetPort: http-public + protocol: TCP + name: {{ .Values.service.public.name }} + selector: + app.kubernetes.io/name: {{ include "hydra.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/utils/assets/charts/hydra/templates/tests/test-connection.yaml b/utils/assets/charts/hydra/templates/tests/test-connection.yaml new file mode 100644 index 0000000..db08330 --- /dev/null +++ b/utils/assets/charts/hydra/templates/tests/test-connection.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "hydra.fullname" . }}-test-connection" + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: {{- include "hydra.labels" . | nindent 4 }} + {{- with .Values.test.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: healthcheck-ready + image: "{{ .Values.test.busybox.repository }}:{{ .Values.test.busybox.tag }}" + command: ['wget'] + args: ['{{ include "hydra.fullname" . }}-admin:{{ .Values.service.admin.port }}/health/ready'] + restartPolicy: Never diff --git a/utils/assets/charts/hydra/values.yaml b/utils/assets/charts/hydra/values.yaml new file mode 100644 index 0000000..1a3592e --- /dev/null +++ b/utils/assets/charts/hydra/values.yaml @@ -0,0 +1,670 @@ +# -- Number of ORY Hydra members +replicaCount: 1 + +image: + # -- ORY Hydra image + repository: oryd/hydra + # -- ORY Hydra version + tag: v2.2.0 + # -- Image pull policy + pullPolicy: IfNotPresent + +# -- Image pull secrets +imagePullSecrets: [] +# Chart name override +nameOverride: "" +# -- Full chart name override +fullnameOverride: "" + +# -- Pod priority +# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +priorityClassName: "" + +## -- Configures the Kubernetes service +service: + # -- Configures the Kubernetes service for the proxy port. + public: + # -- En-/disable the service + enabled: true + # -- The service type + type: ClusterIP + # -- The load balancer IP + loadBalancerIP: "" + # -- The service port + port: 4444 + # -- The service port name. Useful to set a custom service port name if it must follow a scheme (e.g. Istio) + name: http + # -- If you do want to specify annotations, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'annotations:'. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + # If you do want to specify additional labels, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'labels:'. + # e.g. app: hydra + # -- Configures the Kubernetes service for the api port. + admin: + # -- En-/disable the service + enabled: true + # -- The service type + type: ClusterIP + # -- The load balancer IP + loadBalancerIP: "" + # -- The service port + port: 4445 + # -- The service port name. Useful to set a custom service port name if it must follow a scheme (e.g. Istio) + name: http + # -- If you do want to specify annotations, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'annotations:'. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + # If you do want to specify additional labels, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'labels:'. + # e.g. app: hydra + # -- Path to the metrics endpoint + metricsPath: /admin/metrics/prometheus + +## -- Secret management +secret: + # -- switch to false to prevent creating the secret + enabled: true + # -- Provide custom name of existing secret, or custom name of secret to be created + nameOverride: "" + # nameOverride: "myCustomSecret" + # -- Annotations to be added to secret. Annotations are added only when secret is being created. Existing secret will not be modified. + secretAnnotations: + # Create the secret before installation, and only then. This saves the secret from regenerating during an upgrade + # pre-upgrade is needed to upgrade from 0.7.0 to newer. Can be deleted afterwards. + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" + helm.sh/resource-policy: "keep" + # -- switch to false to prevent checksum annotations being maintained and propogated to the pods + hashSumEnabled: true + +## -- Configure ingress +ingress: + # -- Configure ingress for the proxy port. + public: + # -- En-/Disable the proxy ingress. + enabled: true + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: public.hydra.localhost + paths: + - path: / + pathType: ImplementationSpecific + # tls: [] + # hosts: + # - proxy.hydra.local + # - secretName: hydra-proxy-example-tls + + admin: + # -- En-/Disable the api ingress. + enabled: true + className: "" + annotations: {} + # If you do want to specify annotations, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'annotations:'. + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: admin.hydra.localhost + paths: + - path: / + pathType: ImplementationSpecific +# tls: [] +# hosts: +# - api.hydra.local +# - secretName: hydra-api-example-tls + +## -- Configure ORY Hydra itself +hydra: + # -- Ability to override the entrypoint of hydra container + # (e.g. to source dynamic secrets or export environment dynamic variables) + command: ["hydra"] + # -- Ability to override arguments of the entrypoint. Can be used in-depended of customCommand + customArgs: [] + # -- The ORY Hydra configuration. For a full list of available settings, check: + # https://www.ory.sh/docs/hydra/reference/configuration + config: + serve: + public: + port: 4444 + admin: + port: 4445 + tls: + allow_termination_from: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + # -- The secrets have to be provided as a string slice, example: + # system: + # - "OG5XbmxXa3dYeGplQXpQanYxeEFuRUFa" + # - "foo bar 123 456 lorem" + # - "foo bar 123 456 lorem 1" + # - "foo bar 123 456 lorem 2" + # - "foo bar 123 456 lorem 3" + secrets: {} + + # -- Configure the urls used by hydra itself, such as the issuer. + # Note: some values are required for hydra to start, please refer to https://www.ory.sh/docs/hydra/self-hosted/kubernetes-helm-chart + # self: + # issuer: "https://public.hydra.localhost:4444/" + urls: + self: {} + + # -- Enables database migration + automigration: + enabled: false + # -- Configure the way to execute database migration. Possible values: job, initContainer + # When set to job, the migration will be executed as a job on release or upgrade. + # When set to initContainer, the migration will be executed when kratos pod is created + # Defaults to job + type: job + # -- Ability to override the entrypoint of the automigration container + # (e.g. to source dynamic secrets or export environment dynamic variables) + customCommand: [] + # -- Ability to override arguments of the entrypoint. Can be used in-depended of customCommand + # eg: + # - sleep 5; + # - kratos + customArgs: [] + # -- resource requests and limits for the automigration initcontainer + resources: {} + + # -- Enable dev mode, not secure in production environments + dev: false + +## -- Deployment specific config +deployment: + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: "25%" + maxUnavailable: "25%" + + # -- We usually recommend not to specify default resources and to leave this as a conscious choice for the user. + # This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + resources: {} + + ## -- initContainer securityContext for hydra & migration init + initContainerSecurityContext: {} + + ## -- pod securityContext for hydra & migration init + podSecurityContext: + fsGroupChangePolicy: "OnRootMismatch" + runAsNonRoot: true + runAsUser: 65534 + fsGroup: 65534 + runAsGroup: 65534 + seccompProfile: + type: RuntimeDefault + + ## -- container securityContext for hydra & migration init + securityContext: + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + allowPrivilegeEscalation: false + privileged: false + seLinuxOptions: + level: "s0:c123,c456" + + lifecycle: {} + + # -- Set custom deployment level labels + labels: {} + + # -- Set custom deployment level annotations + annotations: {} + + # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + # -- Extra pod level labels + labels: {} + # -- Extra pod level annotations + annotations: {} + + # -- Node labels for pod assignment. + nodeSelector: {} + # If you do want to specify node labels, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'nodeSelector:'. + # foo: bar + + # -- Array of extra envs to be passed to the deployment. Kubernetes format is expected. Value is processed with Helm + # `tpl` + # - name: FOO + # value: BAR + extraEnv: [] + + # -- Parameters for the automigration initContainer + automigration: + # -- Array of extra envs to be passed to the initContainer. Kubernetes format is expected. Value is processed with + # Helm `tpl` + # - name: FOO + # value: BAR + extraEnv: [] + + # -- Configure node tolerations. + tolerations: [] + + # -- Configure pod topologySpreadConstraints. + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app.kubernetes.io/name: hydra + # app.kubernetes.io/instance: hydra + + # -- Configure pod dnsConfig. + dnsConfig: {} + # options: + # - name: "ndots" + # value: "1" + + # -- Specify the serviceAccountName value. + # In some situations it is needed to provides specific permissions to Hydra deployments + # Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. + # Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. + # -- Specify the serviceAccountName value. + # In some situations it is needed to provides specific permissions to Hydra deployments + # Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. + # Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template + name: "" + + # -- If you want to mount external volume + extraVolumes: [] + # - name: my-volume + # secret: + # secretName: my-secret + extraVolumeMounts: [] + # - name: my-volume + # mountPath: /etc/secrets/my-secret + # readOnly: true + + # For example, mount a secret containing Certificate root CA to verify database + # TLS connection. + # extraVolumes: + # - name: postgresql-tls + # secret: + # secretName: postgresql-root-ca + # extraVolumeMounts: + # - name: postgresql-tls + # mountPath: "/etc/postgresql-tls" + # readOnly: true + + # -- Configure HPA + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 3 + targetCPU: {} + # type: Utilization + # averageUtilization: 80 + targetMemory: {} + # type: Utilization + # averageUtilization: 80 + # -- Set custom behavior + # https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior + behavior: {} + + # -- Default probe timers + readinessProbe: + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 5 + # -- Default probe timers + startupProbe: + failureThreshold: 5 + successThreshold: 1 + periodSeconds: 1 + timeoutSeconds: 2 + initialDelaySeconds: 1 + + automountServiceAccountToken: false + + terminationGracePeriodSeconds: 60 + + # -- If you want to add extra init containers. These are processed before the migration init container. + extraInitContainers: "" + # extraInitContainers: | + # - name: ... + # image: ... + + # -- If you want to add extra sidecar containers. + extraContainers: "" + # extraContainers: | + # - name: ... + # image: ... + + # -- Configure a custom livenessProbe. This overwrites the default object + customLivenessProbe: {} + # -- Configure a custom readinessProbe. This overwrites the default object + customReadinessProbe: {} + # -- Configure a custom startupProbe. This overwrites the default object + customStartupProbe: {} + # -- Number of revisions kept in history + revisionHistoryLimit: 5 + +## -- Values for initialization job +job: + # -- If you do want to specify annotations, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'annotations:'. + annotations: + helm.sh/hook-weight: "1" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + # -- Set custom deployment level labels + labels: {} + + # -- If you want to add extra sidecar containers. + extraContainers: "" + # extraContainers: | + # - name: ... + # image: ... + + # -- Array of extra envs to be passed to the job. This takes precedence over deployment variables. Kubernetes format + # is expected. Value is processed with Helm `tpl` + # - name: FOO + # value: BAR + extraEnv: [] + + # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + # -- Extra pod level labels + labels: {} + # -- Extra pod level annotations + annotations: {} + + # -- If you want to add extra init containers. + # extraInitContainers: | + # - name: ... + # image: ... + extraInitContainers: "" + + # -- Node labels for pod assignment. + nodeSelector: {} + # If you do want to specify node labels, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'nodeSelector:'. + # foo: bar + + # -- resource requests and limits for the automigration job + resources: {} + + # -- Configure node tolerations. + tolerations: [] + + # -- If you want to add lifecycle hooks. + lifecycle: "" + # lifecycle: | + # preStop: + # exec: + # command: [...] + + # -- Set automounting of the SA token + automountServiceAccountToken: true + + # -- Set sharing process namespace + shareProcessNamespace: false + + # -- Specify the serviceAccountName value. + # In some situations it is needed to provides specific permissions to Hydra deployments + # Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. + # Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" + # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template + name: "" + + spec: + # -- Set job back off limit + backoffLimit: 10 + +## -- Configure node affinity +affinity: {} + +## -- Configures controller setup +maester: + enabled: true + +## -- Values for the hydra admin service arguments to hydra-maester +hydra-maester: + adminService: + # -- The service name value may need to be set if you use `fullnameOverride` for the parent chart + name: "" + # -- You only need to set this port if you change the value for `service.admin.port` in the parent chart + # port: + +## -- Sidecar watcher configuration +watcher: + enabled: false + image: oryd/k8s-toolbox:v0.0.7 + # -- Path to mounted file, which wil be monitored for changes. eg: /etc/secrets/my-secret/foo + mountFile: "" + # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + # -- Extra pod level labels + labels: {} + # -- Extra pod level annotations + annotations: {} + # -- Label key used for managing applications + watchLabelKey: "ory.sh/watcher" + # -- Number of revisions kept in history + revisionHistoryLimit: 5 + + # -- pod securityContext for watcher deployment + podSecurityContext: {} + resources: {} + automountServiceAccountToken: true + + # -- container securityContext for watcher deployment + securityContext: + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 100 + allowPrivilegeEscalation: false + privileged: false + +## -- Janitor cron job configuration +janitor: + # -- Enable cleanup of stale database rows by periodically running the janitor command + enabled: false + + # -- Configure if the trust relationships must be cleaned up + cleanupGrants: false + + # -- Configure if the consent and authentication requests must be cleaned up + cleanupRequests: false + + # -- Configure if the access and refresh tokens must be cleaned up + cleanupTokens: false + + # -- Configure how many records are deleted with each iteration + batchSize: 100 + + # -- Configure how many records are retrieved from database for deletion + limit: 10000 + +## -- CronJob configuration +cronjob: + janitor: + # -- Configure how often the cron job is ran + schedule: "0 */1 * * *" + # -- Configure a custom entrypoint, overriding the default value + customCommand: [] + + # -- Configure the arguments of the entrypoint, overriding the default value + customArgs: [] + + # -- Array of extra envs to be passed to the cronjob. This takes precedence over deployment variables. Kubernetes + # format is expected. Value is processed with Helm `tpl` + # - name: FOO + # value: BAR + extraEnv: [] + + # -- If you want to add extra init containers. These are processed before the migration init container. + extraInitContainers: "" + # extraInitContainers: | + # - name: ... + # image: ... + + # -- If you want to add extra sidecar containers. + extraContainers: "" + # extraContainers: | + # - name: ... + # image: ... + + # -- If you want to mount external volume + extraVolumes: [] + # - name: my-volumep + # secret: + # secretName: my-secret + extraVolumeMounts: [] + # - name: my-volume + # mountPath: /etc/secrets/my-secret + # readOnly: true + + # -- Set custom cron job level labels + labels: {} + + # -- Set custom cron job level annotations + annotations: {} + + # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + # -- Extra pod level labels + labels: {} + + # -- Extra pod level annotations + annotations: {} + + # -- Configure node labels for pod assignment + nodeSelector: {} + + # -- Configure node tolerations + tolerations: [] + + # -- Configure node affinity + affinity: {} + + # -- Set automounting of the SA token + automountServiceAccountToken: true + + # -- Specify the serviceAccountName value. + # In some situations it is needed to provides specific permissions to Hydra deployments + # Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. + # Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" + # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template + name: "" + + # -- Configure the containers' SecurityContext for the janitor cronjob + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 100 + allowPrivilegeEscalation: false + privileged: false + + ## -- pod securityContext for the janitor cronjob + podSecurityContext: {} + + # -- We usually recommend not to specify default resources and to leave this as a conscious choice for the user. + # This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + resources: + limits: {} + requests: {} + +## -- PodDistributionBudget configuration +pdb: + enabled: false + spec: + minAvailable: "" + maxUnavailable: "" + +## -- Parameters for the Prometheus ServiceMonitor objects. +# Reference: https://docs.openshift.com/container-platform/4.6/rest_api/monitoring_apis/servicemonitor-monitoring-coreos-com-v1.html +serviceMonitor: + # -- switch to true to enable creating the ServiceMonitor + enabled: false + # -- HTTP scheme to use for scraping. + scheme: http + # -- Interval at which metrics should be scraped + scrapeInterval: 60s + # -- Timeout after which the scrape is ended + scrapeTimeout: 30s + # -- Provide additionnal labels to the ServiceMonitor ressource metadata + labels: {} + # -- TLS configuration to use when scraping the endpoint + tlsConfig: {} + +configmap: + # -- switch to false to prevent checksum annotations being maintained and propogated to the pods + hashSumEnabled: true + +test: + # -- Provide additional labels to the test pod + labels: {} + # -- use a busybox image from another repository + busybox: + repository: busybox + tag: 1 diff --git a/utils/assets/charts/keto/.helmignore b/utils/assets/charts/keto/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/utils/assets/charts/keto/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/keto/Chart.lock b/utils/assets/charts/keto/Chart.lock new file mode 100644 index 0000000..d8092d3 --- /dev/null +++ b/utils/assets/charts/keto/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: ory-commons + repository: file://../ory-commons + version: 0.1.0 +digest: sha256:eec8978215334aad38275f0171681f1200220dccef4762ddeb197679fd287abb +generated: "2024-06-11T14:47:42.552973+02:00" diff --git a/utils/assets/charts/keto/Chart.yaml b/utils/assets/charts/keto/Chart.yaml new file mode 100644 index 0000000..72ec1ee --- /dev/null +++ b/utils/assets/charts/keto/Chart.yaml @@ -0,0 +1,27 @@ +apiVersion: v2 +appVersion: v0.12.0 +dependencies: +- alias: ory + name: ory-commons + repository: file://../ory-commons + version: 0.1.0 +description: Access Control Policies as a Server +home: https://www.ory.sh/keto/ +icon: https://raw.githubusercontent.com/ory/docs/master/docs/static/img/logo-keto.svg +keywords: +- rbac +- hrbac +- acl +- iam +- api-security +- security +maintainers: +- email: hi@ory.sh + name: ORY Team + url: https://www.ory.sh/ +name: keto +sources: +- https://github.com/ory/keto +- https://github.com/ory/k8s +type: application +version: 0.50.2 diff --git a/utils/assets/charts/keto/README.md b/utils/assets/charts/keto/README.md new file mode 100644 index 0000000..a142bae --- /dev/null +++ b/utils/assets/charts/keto/README.md @@ -0,0 +1,187 @@ +# keto + +![Version: 0.50.1](https://img.shields.io/badge/Version-0.50.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.12.0](https://img.shields.io/badge/AppVersion-v0.12.0-informational?style=flat-square) + +Access Control Policies as a Server + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| ORY Team | | | + +## Source Code + +* +* + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../ory-commons | ory(ory-commons) | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| configmap.hashSumEnabled | bool | `true` | switch to false to prevent checksum annotations being maintained and propogated to the pods | +| deployment.affinity | object | `{}` | | +| deployment.annotations | object | `{}` | | +| deployment.automigration | object | `{"extraEnv":[]}` | Parameters for the automigration initContainer | +| deployment.automigration.extraEnv | list | `[]` | Array of extra envs to be passed to the initContainer. Kubernetes format is expected. Value is processed with Helm `tpl` - name: FOO value: BAR | +| deployment.automountServiceAccountToken | bool | `true` | | +| deployment.autoscaling | object | `{"behavior":{},"enabled":false,"maxReplicas":100,"minReplicas":1,"targetCPU":{},"targetMemory":{}}` | Autoscaling for keto deployment | +| deployment.autoscaling.behavior | object | `{}` | Set custom behavior https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior | +| deployment.customLivenessProbe | object | `{}` | | +| deployment.customReadinessProbe | object | `{}` | | +| deployment.customStartupProbe | object | `{}` | | +| deployment.dnsConfig | object | `{}` | Configure pod dnsConfig. | +| deployment.extraContainers | string | `""` | If you want to add extra sidecar containers. | +| deployment.extraEnv | list | `[]` | Array of extra Envs to be added to the deployment. Kubernetes format expected. Value is processed with Helm `tpl` - name: FOO value: BAR | +| deployment.extraInitContainers | object | `{}` | If you want to add extra init containers. These are processed before the migration init container. | +| deployment.extraLabels | object | `{}` | Extra labels to be added to the deployment, and pods. K8s object format expected foo: bar my.special.label/type: value | +| deployment.extraPorts | list | `[]` | Extra ports to be exposed by the main deployment | +| deployment.extraVolumeMounts | list | `[]` | Array of extra VolumeMounts to be added to the deployment. K8s format expected - name: my-volume mountPath: /etc/secrets/my-secret readOnly: true | +| deployment.extraVolumes | list | `[]` | Array of extra Volumes to be added to the deployment. K8s format expected - name: my-volume secret: secretName: my-secret | +| deployment.lifecycle | object | `{}` | | +| deployment.minReadySeconds | int | `0` | | +| deployment.nodeSelector | object | `{}` | | +| deployment.podAnnotations | object | `{}` | | +| deployment.podMetadata.annotations | object | `{}` | | +| deployment.podMetadata.labels | object | `{}` | | +| deployment.podSecurityContext | object | `{}` | | +| deployment.readinessProbe.failureThreshold | int | `5` | | +| deployment.readinessProbe.initialDelaySeconds | int | `5` | | +| deployment.readinessProbe.periodSeconds | int | `10` | | +| deployment.resources | object | `{}` | | +| deployment.revisionHistoryLimit | int | `5` | Number of revisions kept in history | +| deployment.startupProbe.failureThreshold | int | `5` | | +| deployment.startupProbe.initialDelaySeconds | int | `0` | | +| deployment.startupProbe.periodSeconds | int | `1` | | +| deployment.startupProbe.successThreshold | int | `1` | | +| deployment.startupProbe.timeoutSeconds | int | `1` | | +| deployment.strategy.rollingUpdate.maxSurge | string | `"25%"` | | +| deployment.strategy.rollingUpdate.maxUnavailable | string | `"25%"` | | +| deployment.strategy.type | string | `"RollingUpdate"` | | +| deployment.terminationGracePeriodSeconds | int | `60` | | +| deployment.tolerations | list | `[]` | | +| deployment.topologySpreadConstraints | list | `[]` | Configure pod topologySpreadConstraints. | +| extraServices | object | `{}` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | Default image pull policy | +| image.repository | string | `"oryd/keto"` | Ory KETO image | +| image.tag | string | `"v0.12.0"` | Ory KETO version | +| imagePullSecrets | list | `[]` | | +| ingress.read.annotations | object | `{}` | | +| ingress.read.className | string | `""` | | +| ingress.read.enabled | bool | `false` | | +| ingress.read.hosts[0].host | string | `"chart-example.local"` | | +| ingress.read.hosts[0].paths[0].path | string | `"/read"` | | +| ingress.read.hosts[0].paths[0].pathType | string | `"Prefix"` | | +| ingress.read.tls | list | `[]` | | +| ingress.write.annotations | object | `{}` | | +| ingress.write.className | string | `""` | | +| ingress.write.enabled | bool | `false` | | +| ingress.write.hosts[0].host | string | `"chart-example.local"` | | +| ingress.write.hosts[0].paths[0].path | string | `"/write"` | | +| ingress.write.hosts[0].paths[0].pathType | string | `"Prefix"` | | +| ingress.write.tls | list | `[]` | | +| job.annotations | object | `{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation,hook-succeeded","helm.sh/hook-weight":"1"}` | If you do want to specify annotations, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'annotations:'. | +| job.automountServiceAccountToken | bool | `false` | Set automounting of the SA token | +| job.extraContainers | string | `""` | If you want to add extra sidecar containers. | +| job.extraEnv | list | `[]` | Array of extra envs to be passed to the job. This takes precedence over deployment variables. Kubernetes format is expected. Value is processed with Helm `tpl` - name: FOO value: BAR | +| job.extraInitContainers | string | `""` | If you want to add extra init containers. | +| job.lifecycle | string | `""` | If you want to add lifecycle hooks. | +| job.nodeSelector | object | `{}` | Node labels for pod assignment. | +| job.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects | +| job.podMetadata.annotations | object | `{}` | Extra pod level annotations | +| job.podMetadata.labels | object | `{}` | Extra pod level labels | +| job.resources | object | `{}` | Job resources | +| job.serviceAccount | object | `{"annotations":{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0"},"create":true,"name":""}` | Specify the serviceAccountName value. In some situations it is needed to provides specific permissions to Hydra deployments Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. | +| job.serviceAccount.annotations | object | `{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0"}` | Annotations to add to the service account | +| job.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| job.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| job.shareProcessNamespace | bool | `false` | Set sharing process namespace | +| job.spec.backoffLimit | int | `10` | Set job back off limit | +| job.tolerations | list | `[]` | Configure node tolerations. | +| keto.automigration | object | `{"customArgs":[],"customCommand":[],"enabled":false,"resources":{},"type":"job"}` | Enables database migration | +| keto.automigration.customArgs | list | `[]` | Ability to override arguments of the entrypoint. Can be used in-depended of customCommand eg: - sleep 5; - keto | +| keto.automigration.customCommand | list | `[]` | Ability to override the entrypoint of the automigration container (e.g. to source dynamic secrets or export environment dynamic variables) | +| keto.automigration.resources | object | `{}` | resource requests and limits for the automigration initcontainer | +| keto.automigration.type | string | `"job"` | Configure the way to execute database migration. Possible values: job, initContainer When set to job, the migration will be executed as a job on release or upgrade. When set to initContainer, the migration will be executed when kratos pod is created Defaults to job | +| keto.command | list | `["keto"]` | Ability to override the entrypoint of keto container (e.g. to source dynamic secrets or export environment dynamic variables) | +| keto.config | object | `{"dsn":"memory","namespaces":[{"id":0,"name":"sample"}],"serve":{"metrics":{"port":4468},"read":{"port":4466},"write":{"port":4467}}}` | Direct keto config. Full documentation can be found in https://www.ory.sh/keto/docs/reference/configuration | +| keto.customArgs | list | `[]` | Ability to override arguments of the entrypoint. Can be used in-depended of customCommand | +| nameOverride | string | `""` | | +| pdb.enabled | bool | `false` | | +| pdb.spec.maxUnavailable | string | `""` | | +| pdb.spec.minAvailable | string | `""` | | +| podSecurityContext.fsGroup | int | `65534` | | +| podSecurityContext.fsGroupChangePolicy | string | `"OnRootMismatch"` | | +| podSecurityContext.runAsGroup | int | `65534` | | +| podSecurityContext.runAsNonRoot | bool | `true` | | +| podSecurityContext.runAsUser | int | `65534` | | +| podSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| priorityClassName | string | `""` | Pod priority https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ | +| replicaCount | int | `1` | Number of replicas in deployment | +| secret.enabled | bool | `true` | Switch to false to prevent creating the secret | +| secret.hashSumEnabled | bool | `true` | switch to false to prevent checksum annotations being maintained and propogated to the pods | +| secret.nameOverride | string | `""` | Provide custom name of existing secret, or custom name of secret to be created | +| secret.secretAnnotations | object | `{"helm.sh/hook":"pre-install, pre-upgrade","helm.sh/hook-delete-policy":"before-hook-creation","helm.sh/hook-weight":"0","helm.sh/resource-policy":"keep"}` | Annotations to be added to secret. Annotations are added only when secret is being created. Existing secret will not be modified. | +| securityContext.allowPrivilegeEscalation | bool | `false` | | +| securityContext.capabilities.drop[0] | string | `"ALL"` | | +| securityContext.privileged | bool | `false` | | +| securityContext.readOnlyRootFilesystem | bool | `true` | | +| securityContext.runAsGroup | int | `65534` | | +| securityContext.runAsNonRoot | bool | `true` | | +| securityContext.runAsUser | int | `65534` | | +| securityContext.seLinuxOptions.level | string | `"s0:c123,c456"` | | +| securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| service.metrics.annotations | object | `{}` | | +| service.metrics.enabled | bool | `false` | | +| service.metrics.loadBalancerIP | string | `""` | | +| service.metrics.name | string | `"http-metrics"` | | +| service.metrics.port | int | `80` | | +| service.metrics.type | string | `"ClusterIP"` | | +| service.read.appProtocol | string | `"grpc"` | | +| service.read.clusterIP | string | `""` | | +| service.read.enabled | bool | `true` | | +| service.read.headless.enabled | bool | `true` | | +| service.read.loadBalancerIP | string | `""` | | +| service.read.name | string | `"grpc-read"` | | +| service.read.port | int | `80` | | +| service.read.type | string | `"ClusterIP"` | | +| service.write.appProtocol | string | `"grpc"` | | +| service.write.clusterIP | string | `""` | | +| service.write.enabled | bool | `true` | | +| service.write.headless.enabled | bool | `true` | | +| service.write.loadBalancerIP | string | `""` | | +| service.write.name | string | `"grpc-write"` | | +| service.write.port | int | `80` | | +| service.write.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| serviceMonitor.labels | object | `{}` | Provide additionnal labels to the ServiceMonitor ressource metadata | +| serviceMonitor.scheme | string | `"http"` | HTTP scheme to use for scraping. | +| serviceMonitor.scrapeInterval | string | `"60s"` | Interval at which metrics should be scraped | +| serviceMonitor.scrapeTimeout | string | `"30s"` | Timeout after which the scrape is ended | +| serviceMonitor.tlsConfig | object | `{}` | TLS configuration to use when scraping the endpoint | +| test.busybox | object | `{"repository":"busybox","tag":1}` | use a busybox image from another repository | +| test.labels | object | `{}` | Provide additional labels to the test pod | +| watcher.automountServiceAccountToken | bool | `true` | | +| watcher.enabled | bool | `false` | | +| watcher.image | string | `"oryd/k8s-toolbox:v0.0.7"` | | +| watcher.mountFile | string | `""` | Path to mounted file, which wil be monitored for changes. eg: /etc/secrets/my-secret/foo | +| watcher.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects | +| watcher.podMetadata.annotations | object | `{}` | Extra pod level annotations | +| watcher.podMetadata.labels | object | `{}` | Extra pod level labels | +| watcher.resources | object | `{}` | | +| watcher.revisionHistoryLimit | int | `5` | Number of revisions kept in history | +| watcher.watchLabelKey | string | `"ory.sh/watcher"` | Label key used for managing applications | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/utils/assets/charts/keto/charts/ory-commons/.helmignore b/utils/assets/charts/keto/charts/ory-commons/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/utils/assets/charts/keto/charts/ory-commons/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/keto/charts/ory-commons/Chart.yaml b/utils/assets/charts/keto/charts/ory-commons/Chart.yaml new file mode 100644 index 0000000..35269f4 --- /dev/null +++ b/utils/assets/charts/keto/charts/ory-commons/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 0.0.0 +description: 'Collection of helper function for the Ory Helm environment ' +name: ory-commons +type: library +version: 0.1.0 diff --git a/utils/assets/charts/keto/charts/ory-commons/templates/_helpers.tpl b/utils/assets/charts/keto/charts/ory-commons/templates/_helpers.tpl new file mode 100644 index 0000000..531b34c --- /dev/null +++ b/utils/assets/charts/keto/charts/ory-commons/templates/_helpers.tpl @@ -0,0 +1,12 @@ +{{/* +Check if list contains object +*/}} +{{- define "ory.extraEnvContainsEnvName" -}} + {{- $extraEnvs := index . 0 -}} + {{- $envName := index . 1 -}} + {{- range $k, $v := $extraEnvs -}} + {{- if eq $v.name $envName -}} + found + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/keto/files/watch.sh b/utils/assets/charts/keto/files/watch.sh new file mode 100644 index 0000000..cb5b44b --- /dev/null +++ b/utils/assets/charts/keto/files/watch.sh @@ -0,0 +1,17 @@ +set -Eeuo pipefail +set -x + +function rollOut() { + DEPLOY=$(kubectl get deploy -n "${NAMESPACE}" -l "${1}" -o name) + kubectl set env -n $NAMESPACE ${DEPLOY} sync=$(date "+%Y%m%d-%H%M%S") + kubectl rollout status -n $NAMESPACE ${DEPLOY} +} + +while true; do + # After change in the CM the symlink is recreated, so we need to restart the monitor + inotifywait --event DELETE_SELF "${WATCH_FILE}" | + while read path _ file; do + echo "---> $path$file modified" + rollOut "${LABEL_SELECTOR}" + done +done diff --git a/utils/assets/charts/keto/templates/NOTES.txt b/utils/assets/charts/keto/templates/NOTES.txt new file mode 100644 index 0000000..91b1ae7 --- /dev/null +++ b/utils/assets/charts/keto/templates/NOTES.txt @@ -0,0 +1,33 @@ +1. Get the application URL by running these commands: +{{- if or .Values.ingress.read.enabled .Values.ingress.write.enabled -}} + Read endpoint available at: + {{- range $host := .Values.ingress.read.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.read.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} + {{- end }} + Write endpoint available at: + {{- range $host := .Values.ingress.write.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.write.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} + {{- end }} +{{- else if or ( contains "NodePort" .Values.service.read.type ) ( contains "NodePort" .Values.service.write.type ) }} + export NODE_PORT_READ=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "keto.fullname" . }}-read) + export NODE_PORT_READ=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "keto.fullname" . }}-write) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") +Read endpoint available at: http://$NODE_IP:$NODE_PORT_READ +Write endpoint available at: http://$NODE_IP:$NODE_PORT_WRITE +{{- else if or ( contains "LoadBalancer" .Values.service.read.type ) ( contains "LoadBalancer" .Values.service.read.type ) }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "keto.fullname" . }}-read' + export SERVICE_IP_READ=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "keto.fullname" . }}-read --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + export SERVICE_IP_WRITE=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "keto.fullname" . }}-write --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + Read endpoint available at: http://$SERVICE_IP_READ:{{ .Values.service.read.port }} + Write endpoint available at: http://$SERVICE_IP_READ:{{ .Values.service.write.port }} +{{- else if or ( contains "ClusterIP" .Values.service.read.type ) ( contains "ClusterIP" .Values.service.read.type ) }} + kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "keto.fullname" . }}-read {{ .Values.keto.config.serve.read.port }}:80 + kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "keto.fullname" . }}-write {{ .Values.keto.config.serve.write.port }}:80 + Read endpoint available at: http://127.0.0.1:{{ .Values.keto.config.serve.read.port }} + Write endpoint available at: http://127.0.0.1:{{ .Values.keto.config.serve.write.port }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/_helpers.tpl b/utils/assets/charts/keto/templates/_helpers.tpl new file mode 100644 index 0000000..98ba10a --- /dev/null +++ b/utils/assets/charts/keto/templates/_helpers.tpl @@ -0,0 +1,130 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "keto.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "keto.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create a secret name which can be overridden. +*/}} +{{- define "keto.secretname" -}} +{{- if .Values.secret.nameOverride -}} +{{- .Values.secret.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{ include "keto.fullname" . }} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "keto.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Generate the dsn value +*/}} +{{- define "keto.dsn" -}} +{{- if and .Values.secret.nameOverride (not .Values.secret.enabled) -}} +dsn-loaded-from-env +{{- else if not (empty (.Values.keto.config.dsn)) -}} +{{- .Values.keto.config.dsn }} +{{- end -}} +{{- end -}} + +{{/* +Generate the configmap data, redacting secrets +*/}} +{{- define "keto.configmap" -}} +{{- $config := omit .Values.keto.config "dsn" -}} +{{- tpl (toYaml $config) . -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "keto.labels" -}} +helm.sh/chart: {{ include "keto.chart" . }} +{{ include "keto.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if $.Values.watcher.enabled }} +{{ printf "\"%s\": \"%s\"" $.Values.watcher.watchLabelKey (include "keto.name" .) }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "keto.selectorLabels" -}} +app.kubernetes.io/name: {{ include "keto.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "keto.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "keto.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account for the Job to use +*/}} +{{- define "keto.job.serviceAccountName" -}} +{{- if .Values.job.serviceAccount.create }} +{{- printf "%s-job" (default (include "keto.fullname" .) .Values.job.serviceAccount.name) }} +{{- else }} +{{- include "keto.serviceAccountName" . }} +{{- end }} +{{- end }} + + +{{/* +Checksum annotations generated from configmaps and secrets +*/}} +{{- define "keto.annotations.checksum" -}} +{{- if .Values.configmap.hashSumEnabled }} +checksum/keto-config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} +{{- end }} +{{- if and .Values.secret.enabled .Values.secret.hashSumEnabled }} +checksum/keto-secrets: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} +{{- end }} +{{- end }} + +{{/* +Check the migration type value and fail if unexpected +*/}} +{{- define "keto.automigration.typeVerification" -}} +{{- if and .Values.keto.automigration.enabled .Values.keto.automigration.type }} + {{- if and (ne .Values.keto.automigration.type "initContainer") (ne .Values.keto.automigration.type "job") }} + {{- fail "keto.automigration.type must be either 'initContainer' or 'job'" -}} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/configmap-migrate.yaml b/utils/assets/charts/keto/templates/configmap-migrate.yaml new file mode 100644 index 0000000..db858a9 --- /dev/null +++ b/utils/assets/charts/keto/templates/configmap-migrate.yaml @@ -0,0 +1,18 @@ +{{- if and ( .Values.keto.automigration.enabled ) ( eq .Values.keto.automigration.type "job" ) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "keto.fullname" . }}-migrate + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: +{{ include "keto.labels" . | indent 4 }} + annotations: + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" +data: + "keto.yaml": | + {{- include "keto.configmap" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/keto/templates/configmap.yaml b/utils/assets/charts/keto/templates/configmap.yaml new file mode 100644 index 0000000..8a655d0 --- /dev/null +++ b/utils/assets/charts/keto/templates/configmap.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "keto.fullname" . }}-config + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: +{{ include "keto.labels" . | indent 4 }} +data: + "keto.yaml": | + {{- include "keto.configmap" . | nindent 4 }} diff --git a/utils/assets/charts/keto/templates/deployment-watcher.yaml b/utils/assets/charts/keto/templates/deployment-watcher.yaml new file mode 100644 index 0000000..ba05cfd --- /dev/null +++ b/utils/assets/charts/keto/templates/deployment-watcher.yaml @@ -0,0 +1,75 @@ +{{- if .Values.watcher.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "keto.fullname" . }}-watcher + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "keto.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.deployment.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + revisionHistoryLimit: {{ .Values.watcher.revisionHistoryLimit }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "keto.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "keto.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.watcher.podMetadata.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- with .Values.watcher.podMetadata.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + automountServiceAccountToken: {{ .Values.watcher.automountServiceAccountToken }} + serviceAccountName: {{ include "keto.serviceAccountName" . }}-watcher + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} + containers: + - name: watcher + {{- if .Values.securityContext }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + {{- end }} + image: {{ .Values.watcher.image }} + command: + - /bin/bash + - -c + - | + {{- .Files.Get "files/watch.sh" | printf "%s" | nindent 14 }} + env: + - name: NAMESPACE + value: {{ .Release.Namespace | quote }} + - name: WATCH_FILE + value: {{ .Values.watcher.mountFile | quote }} + - name: LABEL_SELECTOR + value: '{{ $.Values.watcher.watchLabelKey }}={{ include "keto.name" . }}' + resources: + {{- toYaml .Values.watcher.resources | nindent 12 }} + volumeMounts: + {{- with .Values.deployment.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + {{- if .Values.deployment.extraVolumes }} + {{- toYaml .Values.deployment.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/deployment.yaml b/utils/assets/charts/keto/templates/deployment.yaml new file mode 100644 index 0000000..c29586a --- /dev/null +++ b/utils/assets/charts/keto/templates/deployment.yaml @@ -0,0 +1,232 @@ +{{- $podAnnotations := ternary .Values.deployment.podAnnotations .Values.podAnnotations (not (empty .Values.deployment.podAnnotations )) -}} +{{- $automountServiceAccountToken := ternary .Values.deployment.automountServiceAccountToken .Values.automountServiceAccountToken (not (empty .Values.deployment.automountServiceAccountToken )) -}} +{{- $livenessProbe := ternary .Values.deployment.livenessProbe .Values.livenessProbe (not (empty .Values.deployment.livenessProbe )) -}} +{{- $readinessProbe := ternary .Values.deployment.readinessProbe .Values.readinessProbe (not (empty .Values.deployment.readinessProbe )) -}} +{{- $autoscaling := ternary .Values.deployment.autoscaling .Values.autoscaling (not (empty .Values.deployment.autoscaling )) -}} +{{- $resources := ternary .Values.deployment.resources .Values.resources (not (empty .Values.deployment.resources )) -}} +{{- $extraInitContainers := ternary .Values.deployment.extraInitContainers .Values.extraInitContainers (not (empty .Values.deployment.extraInitContainers )) -}} +{{- $extraContainers := ternary .Values.deployment.extraContainers .Values.extraContainers (not (empty .Values.deployment.extraContainers )) -}} +{{- $extraLabels := ternary .Values.deployment.extraLabels .Values.extraLabels (not (empty .Values.deployment.extraLabels )) -}} +{{- $extraVolumeMounts := ternary .Values.deployment.extraVolumeMounts .Values.extraVolumeMounts (not (empty .Values.deployment.extraVolumeMounts )) -}} +{{- $extraVolumes := ternary .Values.deployment.extraVolumes .Values.extraVolumes (not (empty .Values.deployment.extraVolumes )) -}} +{{- $nodeSelector := ternary .Values.deployment.nodeSelector .Values.nodeSelector (not (empty .Values.deployment.nodeSelector )) -}} +{{- $affinity := ternary .Values.deployment.affinity .Values.affinity (not (empty .Values.deployment.affinity )) -}} +{{- $tolerations := ternary .Values.deployment.tolerations .Values.tolerations (not (empty .Values.deployment.tolerations )) -}} +{{- $topologySpreadConstraints := ternary .Values.deployment.topologySpreadConstraints .Values.topologySpreadConstraints (not (empty .Values.deployment.topologySpreadConstraints )) -}} +{{- include "keto.automigration.typeVerification" . -}} +{{- $migrationExtraEnv := ternary .Values.deployment.automigration.extraEnv .Values.deployment.extraEnv (not (empty .Values.deployment.automigration.extraEnv )) -}} + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "keto.fullname" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "keto.labels" . | nindent 4 }} + {{- with $extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.deployment.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + minReadySeconds: {{ .Values.deployment.minReadySeconds }} +{{- if not $autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} +{{- end }} + revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }} + strategy: + {{- toYaml .Values.deployment.strategy | nindent 4 }} + selector: + matchLabels: + {{- include "keto.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "keto.annotations.checksum" . | indent 8 -}} + {{- with $podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $.Values.deployment.podMetadata.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "keto.selectorLabels" . | nindent 8 }} + {{- with $extraLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $.Values.deployment.podMetadata.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: + {{- if $extraInitContainers}} + {{- tpl $extraInitContainers . | nindent 8 }} + {{- end }} + {{- if and ( .Values.keto.automigration.enabled ) ( eq .Values.keto.automigration.type "initContainer" ) }} + - name: {{ .Chart.Name }}-automigrate + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.keto.automigration.customCommand }} + command: {{- toYaml .Values.keto.automigration.customCommand | nindent 12 }} + {{- else }} + command: ["keto"] + {{- end }} + {{- if .Values.keto.automigration.customArgs }} + args: {{- toYaml .Values.keto.automigration.customArgs | nindent 12 }} + {{- else }} + args: [ "migrate", "up", "-y", "--config", "/etc/config/keto.yaml" ] + {{- end }} + volumeMounts: + - name: {{ include "keto.name" . }}-config-volume + mountPath: /etc/config + readOnly: true + {{- with $extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + env: + {{- if not (empty ( include "keto.dsn" . )) }} + {{- if not (include "ory.extraEnvContainsEnvName" (list $migrationExtraEnv "DSN")) }} + - name: DSN + valueFrom: + secretKeyRef: + name: {{ include "keto.secretname" . }} + key: dsn + {{- end }} + {{- end }} + {{- if $migrationExtraEnv }} + {{- tpl (toYaml $migrationExtraEnv) . | nindent 12 }} + {{- end }} + {{- with .Values.keto.automigration.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "keto.serviceAccountName" . }} + automountServiceAccountToken: {{ $automountServiceAccountToken }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: {{- toYaml .Values.keto.command | nindent 12 }} + {{- if .Values.keto.customArgs }} + args: {{- toYaml .Values.keto.customArgs | nindent 12 }} + {{- else }} + args: + - serve + - --config + - /etc/config/keto.yaml + {{- end }} + ports: + - name: {{ .Values.service.read.name }} + containerPort: {{ .Values.keto.config.serve.read.port }} + protocol: TCP + - name: {{ .Values.service.write.name }} + containerPort: {{ .Values.keto.config.serve.write.port }} + protocol: TCP + - name: {{ .Values.service.metrics.name }} + containerPort: {{ .Values.keto.config.serve.metrics.port }} + protocol: TCP + {{- with .Values.deployment.extraPorts }} + {{- toYaml . | nindent 12 }} + {{- end }} + lifecycle: + {{- toYaml .Values.deployment.lifecycle | nindent 12 }} + {{- if .Values.deployment.customLivenessProbe }} + livenessProbe: + {{- toYaml .Values.deployment.customLivenessProbe | nindent 12 }} + {{- end }} + readinessProbe: + {{- if .Values.deployment.customReadinessProbe }} + {{- toYaml .Values.deployment.customReadinessProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health/alive + port: {{ .Values.keto.config.serve.write.port }} + httpHeaders: + - name: Host + value: '127.0.0.1' + {{- toYaml $readinessProbe | nindent 12 }} + {{- end }} + startupProbe: + {{- if .Values.deployment.customStartupProbe }} + {{- toYaml .Values.deployment.customStartupProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health/ready + port: {{ .Values.keto.config.serve.write.port }} + httpHeaders: + - name: Host + value: '127.0.0.1' + {{- toYaml .Values.deployment.startupProbe | nindent 12 }} + {{- end }} + resources: + {{- toYaml $resources | nindent 12 }} + env: + {{- if not (empty ( include "keto.dsn" . )) }} + {{- if not (include "ory.extraEnvContainsEnvName" (list .Values.deployment.extraEnv "DSN")) }} + - name: DSN + valueFrom: + secretKeyRef: + name: {{ include "keto.secretname" . }} + key: dsn + {{- end }} + {{- end }} + {{- if .Values.deployment.extraEnv }} + {{- tpl (toYaml .Values.deployment.extraEnv) . | nindent 12 }} + {{- end }} + volumeMounts: + - name: {{ include "keto.name" . }}-config-volume + mountPath: /etc/config + readOnly: true + {{- with $extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if $extraContainers }} + {{- tpl $extraContainers . | nindent 8 }} + {{- end }} + volumes: + - name: {{ include "keto.name" . }}-config-volume + configMap: + name: {{ include "keto.fullname" . }}-config + {{- with $extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with $nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.deployment.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/keto/templates/hpa.yaml b/utils/assets/charts/keto/templates/hpa.yaml new file mode 100644 index 0000000..acf1a59 --- /dev/null +++ b/utils/assets/charts/keto/templates/hpa.yaml @@ -0,0 +1,38 @@ +{{- $autoscaling := ternary .Values.deployment.autoscaling .Values.autoscaling (not (empty .Values.deployment.autoscaling )) -}} + +{{- if $autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "keto.fullname" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "keto.labels" . | nindent 4 }} +spec: + {{- with $autoscaling.behavior }} + behavior: {{- toYaml . | nindent 4 }} + {{- end }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "keto.fullname" . }} + minReplicas: {{ $autoscaling.minReplicas }} + maxReplicas: {{ $autoscaling.maxReplicas }} + metrics: + {{- with $autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + target: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $autoscaling.targetCPU}} + - type: Resource + resource: + name: cpu + target: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/ingress-read.yaml b/utils/assets/charts/keto/templates/ingress-read.yaml new file mode 100644 index 0000000..ff30ed1 --- /dev/null +++ b/utils/assets/charts/keto/templates/ingress-read.yaml @@ -0,0 +1,54 @@ +{{- if .Values.ingress.read.enabled -}} +{{- $fullName := include "keto.fullname" . -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else -}} +apiVersion: networking.k8s.io/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-read + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "keto.labels" . | nindent 4 }} + {{- with .Values.ingress.read.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.read.className }} + {{- if .Values.ingress.read.tls }} + tls: + {{- range .Values.ingress.read.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.read.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if .pathType }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }}-read + port: + name: {{ $.Values.service.read.name }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $.Values.service.read.name }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/ingress-write.yaml b/utils/assets/charts/keto/templates/ingress-write.yaml new file mode 100644 index 0000000..9aefbc9 --- /dev/null +++ b/utils/assets/charts/keto/templates/ingress-write.yaml @@ -0,0 +1,54 @@ +{{- if .Values.ingress.write.enabled -}} +{{- $fullName := include "keto.fullname" . -}} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else -}} +apiVersion: networking.k8s.io/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-write + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "keto.labels" . | nindent 4 }} + {{- with .Values.ingress.write.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.write.className }} + {{- if .Values.ingress.write.tls }} + tls: + {{- range .Values.ingress.write.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.write.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if .pathType }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }}-write + port: + name: {{ $.Values.service.write.name }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $.Values.service.write.name }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/job-migration.yaml b/utils/assets/charts/keto/templates/job-migration.yaml new file mode 100644 index 0000000..18b7f57 --- /dev/null +++ b/utils/assets/charts/keto/templates/job-migration.yaml @@ -0,0 +1,123 @@ +{{- include "keto.automigration.typeVerification" . -}} +{{- if and ( .Values.keto.automigration.enabled ) ( eq .Values.keto.automigration.type "job" ) }} +{{- $extraLabels := ternary .Values.deployment.extraLabels .Values.extraLabels (not (empty .Values.deployment.extraLabels )) -}} +{{- $extraVolumeMounts := ternary .Values.deployment.extraVolumeMounts .Values.extraVolumeMounts (not (empty .Values.deployment.extraVolumeMounts )) -}} +{{- $extraVolumes := ternary .Values.deployment.extraVolumes .Values.extraVolumes (not (empty .Values.deployment.extraVolumes )) -}} +{{- $nodeSelector := ternary .Values.job.nodeSelector .Values.deployment.nodeSelector (not (empty .Values.job.nodeSelector )) -}} +{{- $migrationExtraEnv := ternary .Values.job.extraEnv .Values.deployment.extraEnv (not (empty .Values.job.extraEnv )) -}} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "keto.fullname" . }}-automigrate + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "keto.labels" . | nindent 4 }} + {{- with $extraLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.job.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + template: + metadata: + annotations: + {{- with .Values.job.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.job.podMetadata.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "keto.fullname" . }}-automigrate + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with $extraLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.job.podMetadata.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "keto.job.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.job.automountServiceAccountToken }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }}-automigrate + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.keto.automigration.customCommand }} + command: {{- toYaml .Values.keto.automigration.customCommand | nindent 10 }} + {{- else }} + command: ["keto"] + {{- end }} + {{- if .Values.keto.automigration.customArgs }} + args: {{- toYaml .Values.keto.automigration.customArgs | nindent 10 }} + {{- else }} + args: [ "migrate", "up", "-y", "--config", "/etc/config/keto.yaml" ] + {{- end }} + {{- if .Values.job.lifecycle }} + {{- tpl .Values.job.lifecycle . | nindent 8 }} + {{- end }} + volumeMounts: + - name: {{ include "keto.name" . }}-config-volume + mountPath: /etc/config + readOnly: true + {{- with $extraVolumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + env: + {{- if not (empty ( include "keto.dsn" . )) }} + {{- if not (include "ory.extraEnvContainsEnvName" (list $migrationExtraEnv "DSN")) }} + - name: DSN + valueFrom: + secretKeyRef: + name: {{ include "keto.secretname" . }} + key: dsn + {{- end }} + {{- end }} + {{- with $migrationExtraEnv }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.job.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.securityContext }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + {{- end }} + {{- if .Values.job.extraContainers }} + {{- tpl .Values.job.extraContainers . | nindent 6 }} + {{- end }} + {{- if .Values.job.extraInitContainers }} + initContainers: + {{- tpl .Values.job.extraInitContainers . | nindent 8 }} + {{- end }} + restartPolicy: Never + volumes: + - name: {{ include "keto.name" . }}-config-volume + configMap: + name: {{ include "keto.fullname" . }}-migrate + {{- with $extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.job.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + shareProcessNamespace: {{ .Values.job.shareProcessNamespace }} + backoffLimit: {{ .Values.job.spec.backoffLimit }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/job-rbac.yaml b/utils/assets/charts/keto/templates/job-rbac.yaml new file mode 100644 index 0000000..a788af6 --- /dev/null +++ b/utils/assets/charts/keto/templates/job-rbac.yaml @@ -0,0 +1,17 @@ +{{- if .Values.job.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "keto.job.serviceAccountName" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "keto.labels" . | nindent 4 }} + {{- with .Values.job.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: false +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/keto/templates/pdb.yaml b/utils/assets/charts/keto/templates/pdb.yaml new file mode 100644 index 0000000..1e01ff1 --- /dev/null +++ b/utils/assets/charts/keto/templates/pdb.yaml @@ -0,0 +1,20 @@ +{{- if .Values.pdb.enabled -}} +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "keto.fullname" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "keto.selectorLabels" . | nindent 6 }} + {{- with .Values.pdb.spec.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with .Values.pdb.spec.minAvailable }} + minAvailable: {{ . }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/keto/templates/rbac-watcher.yaml b/utils/assets/charts/keto/templates/rbac-watcher.yaml new file mode 100644 index 0000000..15a693a --- /dev/null +++ b/utils/assets/charts/keto/templates/rbac-watcher.yaml @@ -0,0 +1,55 @@ +{{- if .Values.watcher.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "keto.serviceAccountName" . }}-watcher + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "keto.name" . }}-watcher + app.kubernetes.io/instance: {{ .Release.Name }} +automountServiceAccountToken: false +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "keto.fullname" . }}-watcher + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} +rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: + - list + - watch + - get + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: + - get + - list + - patch + - update + - watch + resourceNames: + - {{ include "keto.fullname" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "keto.fullname" . }}-watcher + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "keto.fullname" . }}-watcher +subjects: + - kind: ServiceAccount + name: {{ include "keto.fullname" . }}-watcher + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/rbac.yaml b/utils/assets/charts/keto/templates/rbac.yaml new file mode 100644 index 0000000..f616731 --- /dev/null +++ b/utils/assets/charts/keto/templates/rbac.yaml @@ -0,0 +1,17 @@ +{{- if .Values.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "keto.serviceAccountName" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "keto.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: false +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/keto/templates/secrets.yaml b/utils/assets/charts/keto/templates/secrets.yaml new file mode 100644 index 0000000..41bd0b1 --- /dev/null +++ b/utils/assets/charts/keto/templates/secrets.yaml @@ -0,0 +1,18 @@ +{{- if .Values.secret.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "keto.secretname" . }} + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: +{{ include "keto.labels" . | indent 4 }} + annotations: +{{- with .Values.secret.secretAnnotations }} + {{- toYaml . | nindent 4 }} +{{- end }} +type: Opaque +data: + dsn: {{ include "keto.dsn" . | b64enc | quote }} +{{- end }} diff --git a/utils/assets/charts/keto/templates/service-extraServices.yaml b/utils/assets/charts/keto/templates/service-extraServices.yaml new file mode 100644 index 0000000..ba04b1a --- /dev/null +++ b/utils/assets/charts/keto/templates/service-extraServices.yaml @@ -0,0 +1,32 @@ +{{- range $ServiceName, $ServiceData := .Values.extraServices }} + +{{- if $ServiceData.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keto.fullname" $ }}-{{ $ServiceName }} + {{- if $.Release.Namespace }} + namespace: {{ $.Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/component: {{ $ServiceName }} + {{- include "keto.labels" $ | nindent 4 }} +spec: + type: {{ $ServiceData.type }} + {{- if eq $ServiceData.type "LoadBalancer" }} + {{- with $ServiceData.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- end }} + ports: + - port: {{ $ServiceData.port }} + targetPort: {{ $ServiceData.name }} + protocol: TCP + name: {{ $ServiceData.name }} + selector: + app.kubernetes.io/name: {{ include "keto.name" $ }} + app.kubernetes.io/instance: {{ $.Release.Name }} +{{- end }} + +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/keto/templates/service-metrics.yaml b/utils/assets/charts/keto/templates/service-metrics.yaml new file mode 100644 index 0000000..ce15ab6 --- /dev/null +++ b/utils/assets/charts/keto/templates/service-metrics.yaml @@ -0,0 +1,27 @@ +{{- if .Values.service.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keto.fullname" . }}-metrics + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/component: metrics + {{- include "keto.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.metrics.type }} + {{- if eq .Values.service.metrics.type "LoadBalancer" }} + {{- with .Values.service.metrics.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- end }} + ports: + - port: {{ .Values.service.metrics.port }} + targetPort: {{ .Values.service.metrics.name }} + protocol: TCP + name: {{ .Values.service.metrics.name }} + selector: + app.kubernetes.io/name: {{ include "keto.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{ end }} diff --git a/utils/assets/charts/keto/templates/service-read.yaml b/utils/assets/charts/keto/templates/service-read.yaml new file mode 100644 index 0000000..b86a615 --- /dev/null +++ b/utils/assets/charts/keto/templates/service-read.yaml @@ -0,0 +1,60 @@ +{{- if .Values.service.read.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keto.fullname" . }}-read + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/component: read + {{- include "keto.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.read.type }} + {{- if eq .Values.service.read.type "LoadBalancer" }} + {{- with .Values.service.read.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- end }} + {{- if eq .Values.service.read.type "ClusterIP" }} + {{- with .Values.service.read.clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- end }} + ports: + - port: {{ .Values.service.read.port }} + targetPort: {{ .Values.service.read.name }} + protocol: TCP + name: {{ .Values.service.read.name }} + appProtocol: {{ .Values.service.read.appProtocol }} + selector: + app.kubernetes.io/name: {{ include "keto.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Values.service.read.headless.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keto.fullname" . }}-read-headless + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + service.ory.sh/type: headless + app.kubernetes.io/component: read + {{- include "keto.labels" . | nindent 4 }} +spec: + type: "ClusterIP" + clusterIP: "None" + ports: + - port: {{ .Values.keto.config.serve.read.port }} + targetPort: {{ .Values.service.read.name }} + protocol: TCP + name: {{ .Values.service.read.name }} + appProtocol: {{ .Values.service.read.appProtocol }} + selector: + app.kubernetes.io/name: {{ include "keto.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/keto/templates/service-write.yaml b/utils/assets/charts/keto/templates/service-write.yaml new file mode 100644 index 0000000..d4dab78 --- /dev/null +++ b/utils/assets/charts/keto/templates/service-write.yaml @@ -0,0 +1,59 @@ +{{- if .Values.service.write.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keto.fullname" . }}-write + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/component: write + {{- include "keto.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.write.type }} + {{- if eq .Values.service.write.type "LoadBalancer" }} + {{- with .Values.service.write.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- end }} + {{- if eq .Values.service.write.type "ClusterIP" }} + {{- with .Values.service.write.clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- end }} + ports: + - port: {{ .Values.service.write.port }} + targetPort: {{ .Values.service.write.name }} + protocol: TCP + name: {{ .Values.service.write.name }} + appProtocol: {{ .Values.service.write.appProtocol }} + selector: + app.kubernetes.io/name: {{ include "keto.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Values.service.write.headless.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "keto.fullname" . }}-write-headless + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + service.ory.sh/type: headless + app.kubernetes.io/component: write + {{- include "keto.labels" . | nindent 4 }} +spec: + type: "ClusterIP" + clusterIP: "None" + ports: + - port: {{ .Values.keto.config.serve.write.port }} + targetPort: {{ .Values.service.write.name }} + protocol: TCP + name: {{ .Values.service.write.name }} + appProtocol: {{ .Values.service.write.appProtocol }} + selector: + app.kubernetes.io/name: {{ include "keto.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/keto/templates/servicemonitor-metrics.yaml b/utils/assets/charts/keto/templates/servicemonitor-metrics.yaml new file mode 100644 index 0000000..c72b624 --- /dev/null +++ b/utils/assets/charts/keto/templates/servicemonitor-metrics.yaml @@ -0,0 +1,36 @@ +{{- if and (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") (.Values.service.metrics.enabled) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "keto.fullname" . }}-metrics + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/component: metrics +{{ include "keto.labels" . | indent 4 }} + {{- with .Values.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.metrics.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + - path: /metrics/prometheus + port: {{ .Values.service.metrics.name }} + scheme: {{ .Values.serviceMonitor.scheme }} + interval: {{ .Values.serviceMonitor.scrapeInterval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + {{- with .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 6 }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "keto.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: metrics +{{- end -}} diff --git a/utils/assets/charts/keto/templates/tests/test-connection.yaml b/utils/assets/charts/keto/templates/tests/test-connection.yaml new file mode 100644 index 0000000..1947c9b --- /dev/null +++ b/utils/assets/charts/keto/templates/tests/test-connection.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "keto.fullname" . }}-test-connection" + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: {{- include "keto.labels" . | nindent 4 }} + {{- with .Values.test.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + helm.sh/hook: test-success +spec: + containers: + - name: wget + image: "{{ .Values.test.busybox.repository }}:{{ .Values.test.busybox.tag }}" + command: ['wget'] + args: ['{{ include "keto.fullname" . }}-write:{{ .Values.service.write.port }}/health/ready'] + restartPolicy: Never diff --git a/utils/assets/charts/keto/values.yaml b/utils/assets/charts/keto/values.yaml new file mode 100644 index 0000000..5c3e181 --- /dev/null +++ b/utils/assets/charts/keto/values.yaml @@ -0,0 +1,471 @@ +# Default values for keto. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +# -- Number of replicas in deployment +replicaCount: 1 + +## -- Image configuration +image: + # -- Ory KETO image + repository: oryd/keto + # -- Default image pull policy + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + # -- Ory KETO version + tag: "v0.12.0" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +# -- Pod priority +# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +priorityClassName: "" + +## -- ServiceAccount +serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +## -- pod securityContext for hydra & migration init +podSecurityContext: + fsGroupChangePolicy: "OnRootMismatch" + runAsNonRoot: true + runAsUser: 65534 + fsGroup: 65534 + runAsGroup: 65534 + seccompProfile: + type: RuntimeDefault + +## -- container securityContext for hydra & migration init +securityContext: + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + allowPrivilegeEscalation: false + privileged: false + seLinuxOptions: + level: "s0:c123,c456" + +## -- Values for initialization job +job: + # -- If you do want to specify annotations, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'annotations:'. + annotations: + helm.sh/hook-weight: "1" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation,hook-succeeded" + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + # -- If you want to add extra sidecar containers. + extraContainers: "" + # extraContainers: | + # - name: ... + # image: ... + + # -- If you want to add extra init containers. + extraInitContainers: "" + # extraInitContainers: | + # - name: ... + # image: ... + + # -- Array of extra envs to be passed to the job. This takes precedence over deployment variables. Kubernetes format + # is expected. Value is processed with Helm `tpl` + # - name: FOO + # value: BAR + extraEnv: [] + + # -- Node labels for pod assignment. + nodeSelector: {} + # If you do want to specify node labels, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'nodeSelector:'. + # foo: bar + + # -- Configure node tolerations. + tolerations: [] + + # -- Job resources + resources: {} + + # -- If you want to add lifecycle hooks. + lifecycle: "" + # lifecycle: | + # preStop: + # exec: + # command: [...] + + # -- Set automounting of the SA token + automountServiceAccountToken: false + + # -- Set sharing process namespace + shareProcessNamespace: false + + # -- Specify the serviceAccountName value. + # In some situations it is needed to provides specific permissions to Hydra deployments + # Like for example installing Hydra on a cluster with a PosSecurityPolicy and Istio. + # Uncoment if it is needed to provide a ServiceAccount for the Hydra deployment. + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" + # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template + name: "" + + # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + # -- Extra pod level labels + labels: {} + # -- Extra pod level annotations + annotations: {} + + spec: + # -- Set job back off limit + backoffLimit: 10 + +## -- Ingress definitions +ingress: + read: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: /read + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + write: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: /write + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +## -- Service configurations +service: + ## -- Read service + read: + enabled: true + type: ClusterIP + clusterIP: "" + ## -- The load balancer IP + loadBalancerIP: "" + name: grpc-read + port: 80 + appProtocol: grpc + ## -- Enable extra headless service + headless: + enabled: true + ## -- Write service + write: + enabled: true + type: ClusterIP + clusterIP: "" + ## -- The load balancer IP + loadBalancerIP: "" + name: grpc-write + port: 80 + appProtocol: grpc + ## -- Enable extra headless service + headless: + enabled: true + ## -- Metrics service + metrics: + enabled: false + type: ClusterIP + ## -- The load balancer IP + loadBalancerIP: "" + name: http-metrics + port: 80 + annotations: {} + +## -- Extra services to be deployed +extraServices: {} + +## -- Secret management +secret: + # -- Switch to false to prevent creating the secret + enabled: true + # -- Provide custom name of existing secret, or custom name of secret to be created + nameOverride: "" + # nameOverride: "myCustomSecret" + # -- Annotations to be added to secret. Annotations are added only when secret is being created. Existing secret will not be modified. + secretAnnotations: + # Create the secret before installation, and only then. This saves the secret from regenerating during an upgrade + # pre-upgrade is needed to upgrade from 0.7.0 to newer. Can be deleted afterwards. + helm.sh/hook-weight: "0" + helm.sh/hook: "pre-install, pre-upgrade" + helm.sh/hook-delete-policy: "before-hook-creation" + helm.sh/resource-policy: "keep" + # -- switch to false to prevent checksum annotations being maintained and propogated to the pods + hashSumEnabled: true + +## -- Main application config. +keto: + # -- Ability to override the entrypoint of keto container + # (e.g. to source dynamic secrets or export environment dynamic variables) + command: ["keto"] + # -- Ability to override arguments of the entrypoint. Can be used in-depended of customCommand + customArgs: [] + # -- Enables database migration + automigration: + enabled: false + # -- Configure the way to execute database migration. Possible values: job, initContainer + # When set to job, the migration will be executed as a job on release or upgrade. + # When set to initContainer, the migration will be executed when kratos pod is created + # Defaults to job + type: job + # -- Ability to override the entrypoint of the automigration container + # (e.g. to source dynamic secrets or export environment dynamic variables) + customCommand: [] + # -- Ability to override arguments of the entrypoint. Can be used in-depended of customCommand + # eg: + # - sleep 5; + # - keto + customArgs: [] + # -- resource requests and limits for the automigration initcontainer + resources: {} + # -- Direct keto config. Full documentation can be found in https://www.ory.sh/keto/docs/reference/configuration + config: + serve: + read: + port: 4466 + write: + port: 4467 + metrics: + port: 4468 + namespaces: + - id: 0 + name: sample + dsn: memory + +## -- Configure the probes for when the deployment is considered ready and ongoing health check +deployment: + ## -- Specify pod deployment strategy + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: "25%" + maxUnavailable: "25%" + + ## -- Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) + minReadySeconds: 0 + + ## -- DEPRECATED Set custom pod annotations + podAnnotations: {} + + ## -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + ## -- Extra pod level labels + labels: {} + ## -- Extra pod level annotations + annotations: {} + + ## -- Set custom security context for pods + podSecurityContext: {} + # fsGroup: 2000 + + # https://github.com/kubernetes/kubernetes/issues/57601 + automountServiceAccountToken: true + + lifecycle: {} + ## -- Default probe timers + readinessProbe: + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 5 + ## -- Default probe timers + startupProbe: + failureThreshold: 5 + successThreshold: 1 + periodSeconds: 1 + timeoutSeconds: 1 + initialDelaySeconds: 0 + ## -- Configure a custom livenessProbe. This overwrites the default object + customLivenessProbe: {} + ## -- Configure a custom readinessProbe. This overwrites the default object + customReadinessProbe: {} + ## -- Configure a custom startupProbe. This overwrites the default object + customStartupProbe: {} + + ## -- Add custom annotations to the deployment + annotations: {} + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # -- Autoscaling for keto deployment + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPU: {} + # type: Utilization + # averageUtilization: 80 + targetMemory: {} + # type: Utilization + # averageUtilization: 80 + # -- Set custom behavior + # https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior + behavior: {} + + nodeSelector: {} + + # -- If you want to add extra sidecar containers. + extraContainers: "" + # extraContainers: | + # - name: ... + # image: ... + + # -- Array of extra Envs to be added to the deployment. Kubernetes format expected. Value is processed with Helm `tpl` + # - name: FOO + # value: BAR + extraEnv: [] + + # -- Array of extra Volumes to be added to the deployment. K8s format expected + # - name: my-volume + # secret: + # secretName: my-secret + extraVolumes: [] + + # -- Array of extra VolumeMounts to be added to the deployment. K8s format expected + # - name: my-volume + # mountPath: /etc/secrets/my-secret + # readOnly: true + extraVolumeMounts: [] + + # -- If you want to add extra init containers. These are processed before the migration init container. + extraInitContainers: {} + # extraInitContainers: | + # - name: ... + # image: ... + + # -- Extra labels to be added to the deployment, and pods. K8s object format expected + # foo: bar + # my.special.label/type: value + extraLabels: {} + + # -- Extra ports to be exposed by the main deployment + extraPorts: [] + + tolerations: [] + + affinity: {} + + # -- Configure pod topologySpreadConstraints. + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app.kubernetes.io/name: keto + # app.kubernetes.io/instance: keto + + # -- Configure pod dnsConfig. + dnsConfig: {} + # options: + # - name: "ndots" + # value: "1" + + # -- Parameters for the automigration initContainer + automigration: + # -- Array of extra envs to be passed to the initContainer. Kubernetes format is expected. Value is processed with + # Helm `tpl` + # - name: FOO + # value: BAR + extraEnv: [] + # -- Number of revisions kept in history + revisionHistoryLimit: 5 + terminationGracePeriodSeconds: 60 + +## -- Watcher sidecar configuration +watcher: + enabled: false + image: oryd/k8s-toolbox:v0.0.7 + # -- Path to mounted file, which wil be monitored for changes. eg: /etc/secrets/my-secret/foo + mountFile: "" + # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects + podMetadata: + # -- Extra pod level labels + labels: {} + # -- Extra pod level annotations + annotations: {} + # -- Label key used for managing applications + watchLabelKey: "ory.sh/watcher" + # -- Number of revisions kept in history + revisionHistoryLimit: 5 + automountServiceAccountToken: true + resources: {} + +## -- PodDistributionBudget configuration +pdb: + enabled: false + spec: + minAvailable: "" + maxUnavailable: "" + +## -- Parameters for the Prometheus ServiceMonitor objects. +# Reference: https://docs.openshift.com/container-platform/4.6/rest_api/monitoring_apis/servicemonitor-monitoring-coreos-com-v1.html +serviceMonitor: + # -- HTTP scheme to use for scraping. + scheme: http + # -- Interval at which metrics should be scraped + scrapeInterval: 60s + # -- Timeout after which the scrape is ended + scrapeTimeout: 30s + # -- Provide additionnal labels to the ServiceMonitor ressource metadata + labels: {} + # -- TLS configuration to use when scraping the endpoint + tlsConfig: {} + +configmap: + # -- switch to false to prevent checksum annotations being maintained and propogated to the pods + hashSumEnabled: true + +test: + # -- Provide additional labels to the test pod + labels: {} + # -- use a busybox image from another repository + busybox: + repository: busybox + tag: 1 diff --git a/utils/assets/charts/loki/.helmignore b/utils/assets/charts/loki/.helmignore new file mode 100644 index 0000000..6d90723 --- /dev/null +++ b/utils/assets/charts/loki/.helmignore @@ -0,0 +1,32 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ + +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ + +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +# Other +doc.yaml +README.tpl +README.md.gotmpl +ci +CHANGELOG.md diff --git a/utils/assets/charts/loki/Chart.lock b/utils/assets/charts/loki/Chart.lock new file mode 100644 index 0000000..e4ffe8c --- /dev/null +++ b/utils/assets/charts/loki/Chart.lock @@ -0,0 +1,12 @@ +dependencies: +- name: minio + repository: https://charts.min.io/ + version: 5.3.0 +- name: grafana-agent-operator + repository: https://grafana.github.io/helm-charts + version: 0.5.0 +- name: rollout-operator + repository: https://grafana.github.io/helm-charts + version: 0.20.0 +digest: sha256:7d7078dd5a08a25d152fd78a6fe60a8795cff0f940507d5b4c7ad4df396a16d9 +generated: "2024-11-28T15:43:12.190731467+01:00" diff --git a/utils/assets/charts/loki/Chart.yaml b/utils/assets/charts/loki/Chart.yaml new file mode 100644 index 0000000..8224157 --- /dev/null +++ b/utils/assets/charts/loki/Chart.yaml @@ -0,0 +1,32 @@ +apiVersion: v2 +appVersion: 3.3.1 +dependencies: +- alias: minio + condition: minio.enabled + name: minio + repository: https://charts.min.io/ + version: 5.3.0 +- alias: grafana-agent-operator + condition: monitoring.selfMonitoring.grafanaAgent.installOperator + name: grafana-agent-operator + repository: https://grafana.github.io/helm-charts + version: 0.5.0 +- alias: rollout_operator + condition: rollout_operator.enabled + name: rollout-operator + repository: https://grafana.github.io/helm-charts + version: 0.20.0 +description: Helm chart for Grafana Loki and Grafana Enterprise Logs supporting both + simple, scalable and distributed modes. +home: https://grafana.github.io/helm-charts +icon: https://grafana.com/docs/loki/latest/logo_and_name.png +maintainers: +- name: trevorwhitney +- name: jeschkies +name: loki +sources: +- https://github.com/grafana/loki +- https://grafana.com/oss/loki/ +- https://grafana.com/docs/loki/latest/ +type: application +version: 6.23.0 diff --git a/utils/assets/charts/loki/Makefile b/utils/assets/charts/loki/Makefile new file mode 100644 index 0000000..4b56414 --- /dev/null +++ b/utils/assets/charts/loki/Makefile @@ -0,0 +1,7 @@ +.DEFAULT_GOAL := all +.PHONY: lint lint-yaml + +lint: lint-yaml + +lint-yaml: + yamllint -c $(CURDIR)/src/.yamllint.yaml $(CURDIR)/src diff --git a/utils/assets/charts/loki/README.md b/utils/assets/charts/loki/README.md new file mode 100644 index 0000000..bbc39ed --- /dev/null +++ b/utils/assets/charts/loki/README.md @@ -0,0 +1,65 @@ +# loki + +![Version: 6.23.0](https://img.shields.io/badge/Version-6.23.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.3.1](https://img.shields.io/badge/AppVersion-3.3.1-informational?style=flat-square) + +Helm chart for Grafana Loki and Grafana Enterprise Logs supporting both simple, scalable and distributed modes. + +## Source Code + +* +* +* + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://charts.min.io/ | minio(minio) | 5.3.0 | +| https://grafana.github.io/helm-charts | grafana-agent-operator(grafana-agent-operator) | 0.5.0 | +| https://grafana.github.io/helm-charts | rollout_operator(rollout-operator) | 0.20.0 | + +Find more information in the Loki Helm Chart [documentation](https://grafana.com/docs/loki/next/installation/helm). + +## Contributing and releasing + +If you made any changes to the [Chart.yaml](https://github.com/grafana/loki/blob/main/production/helm/loki/Chart.yaml) or [values.yaml](https://github.com/grafana/loki/blob/main/production/helm/loki/values.yaml) run `make helm-docs` from the root of the repository to update the documentation and commit the changed files. + +Futhermore, please add an entry to the [CHANGELOG.md](./CHANGELOG.md) file about what you changed. This file has a header that looks like this: + +``` +[//]: # ( : do not remove this line. This locator is used by the CI pipeline to automatically create a changelog entry for each new Loki release. Add other chart versions and respective changelog entries bellow this line.) +```` + +Place your changes as a bulleted list below this header. The helm chart is automatically released once a week, at which point the `CHANGELOG.md` file will be updated to reflect the release of all changes between this header the the header of the previous version as the changes for that weeks release. For example, if the weekly release will be `1.21.0`, and the `CHANGELOG.md` file has the following entries: + +``` +[//]: # ( : do not remove this line. This locator is used by the CI pipeline to automatically create a changelog entry for each new Loki release. Add other chart versions and respective changelog entries bellow this line.) + +- [CHANGE] Changed the thing +- [FEATURE] Cool new feature + +## 1.20.0 + +- [BUGFIX] Fixed the bug +``` + +Then the weekly release will create a `CHANGELOG.md` with the following content: +``` +[//]: # ( : do not remove this line. This locator is used by the CI pipeline to automatically create a changelog entry for each new Loki release. Add other chart versions and respective changelog entries bellow this line.) + +## 1.21.0 + +- [CHANGE] Changed the thing +- [FEATURE] Cool new feature + +## 1.20.0 + +- [BUGFIX] Fixed the bug +``` + +#### Versioning + +Normally contributors need _not_ bump the version nor update the [CHANGELOG.md](https://github.com/grafana/loki/blob/main/production/helm/loki/CHANGELOG.md). A new version of the Chart will follow this cadence: +- Automatic weekly releases +- Releases that coincide with Loki/GEL releases +- Manual releases when necessary (ie. to address a CVE or critical bug) diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/.helmignore b/utils/assets/charts/loki/charts/grafana-agent-operator/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/Chart.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/Chart.yaml new file mode 100644 index 0000000..3281eec --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +appVersion: 0.43.3 +description: A Helm chart for Grafana Agent Operator +home: https://grafana.com/docs/agent/v0.43/ +icon: https://raw.githubusercontent.com/grafana/agent/v0.43.3/docs/sources/assets/logo_and_name.png +maintainers: +- email: grafana-agent-team@googlegroups.com + name: Grafana Agent Team +name: grafana-agent-operator +sources: +- https://github.com/grafana/agent/tree/v0.43.3/static/operator +type: application +version: 0.5.0 diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/README.md b/utils/assets/charts/loki/charts/grafana-agent-operator/README.md new file mode 100644 index 0000000..b39b26a --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/README.md @@ -0,0 +1,82 @@ +# grafana-agent-operator + +![Version: 0.5.0](https://img.shields.io/badge/Version-0.5.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.43.3](https://img.shields.io/badge/AppVersion-0.43.3-informational?style=flat-square) + +A Helm chart for Grafana Agent Operator + +⚠️ **Please create issues relating to this Helm chart in the [Agent](https://github.com/grafana/agent/issues) repo.** + +## Source Code + +* + +Note that this chart does not provision custom resources like `GrafanaAgent` and `MetricsInstance` (formerly `PrometheusInstance`) or any `*Monitor` resources. + +To learn how to deploy these resources, please see Grafana's [Agent Operator getting started guide](https://grafana.com/docs/agent/latest/operator/getting-started/). + +## CRDs + +The CRDs are synced into this chart manually (for now) from the Grafana Agent [GitHub repo](https://github.com/grafana/agent/tree/main/operations/agent-static-operator/crds). To learn more about how Helm manages CRDs, please see [Custom Resource Definitions](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/) from the Helm docs. + +## Get Repo Info + +```console +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release grafana/grafana-agent-operator +``` + +## Uninstalling the Chart + +To uninstall/delete the my-release deployment: + +```console +helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Upgrading an existing Release to a new major version + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an incompatible breaking change needing manual actions. Until this chart's version reaches `v1.0`, there are no promises of backwards compatibility. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Pod affinity configuration | +| annotations | object | `{}` | Annotations for the Deployment | +| containerSecurityContext | object | `{}` | Container security context (allowPrivilegeEscalation, etc.) | +| extraArgs | list | `[]` | List of additional cli arguments to configure agent-operator (example: `--log.level`) | +| fullnameOverride | string | `""` | Overrides the chart's computed fullname | +| global.commonLabels | object | `{}` | Common labels for all object directly managed by this chart. | +| hostAliases | list | `[]` | hostAliases to add | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| image.pullSecrets | list | `[]` | Image pull secrets | +| image.registry | string | `"docker.io"` | Image registry | +| image.repository | string | `"grafana/agent-operator"` | Image repo | +| image.tag | string | `"v0.43.3"` | Image tag | +| kubeletService | object | `{"namespace":"default","serviceName":"kubelet"}` | If both are set, Agent Operator will create and maintain a service for scraping kubelets https://grafana.com/docs/agent/latest/operator/getting-started/#monitor-kubelets | +| nameOverride | string | `""` | Overrides the chart's name | +| nodeSelector | object | `{}` | nodeSelector configuration | +| podAnnotations | object | `{}` | Annotations for the Deployment Pods | +| podLabels | object | `{}` | Annotations for the Deployment Pods | +| podSecurityContext | object | `{}` | Pod security context (runAsUser, etc.) | +| rbac.create | bool | `true` | Toggle to create ClusterRole and ClusterRoleBinding | +| rbac.podSecurityPolicyName | string | `""` | Name of a PodSecurityPolicy to use in the ClusterRole. If unset, no PodSecurityPolicy is used. | +| resources | object | `{}` | Resource limits and requests config | +| serviceAccount.create | bool | `true` | Toggle to create ServiceAccount | +| serviceAccount.name | string | `nil` | Service account name | +| test.image.registry | string | `"docker.io"` | Test image registry | +| test.image.repository | string | `"library/busybox"` | Test image repo | +| test.image.tag | string | `"latest"` | Test image tag | +| tolerations | list | `[]` | Tolerations applied to Pods | diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/README.md.gotmpl b/utils/assets/charts/loki/charts/grafana-agent-operator/README.md.gotmpl new file mode 100644 index 0000000..3dce97a --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/README.md.gotmpl @@ -0,0 +1,52 @@ +{{ template "chart.header" . }} + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +{{ template "chart.description" . }} + +⚠️ **Please create issues relating to this Helm chart in the [Agent](https://github.com/grafana/agent/issues) repo.** + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +Note that this chart does not provision custom resources like `GrafanaAgent` and `MetricsInstance` (formerly `PrometheusInstance`) or any `*Monitor` resources. + +To learn how to deploy these resources, please see Grafana's [Agent Operator getting started guide](https://grafana.com/docs/agent/latest/operator/getting-started/). + +## CRDs + +The CRDs are synced into this chart manually (for now) from the Grafana Agent [GitHub repo](https://github.com/grafana/agent/tree/main/operations/agent-static-operator/crds). To learn more about how Helm manages CRDs, please see [Custom Resource Definitions](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/) from the Helm docs. + +## Get Repo Info + +```console +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release grafana/grafana-agent-operator +``` + +## Uninstalling the Chart + +To uninstall/delete the my-release deployment: + +```console +helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Upgrading an existing Release to a new major version + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an incompatible breaking change needing manual actions. Until this chart's version reaches `v1.0`, there are no promises of backwards compatibility. + +{{ template "chart.valuesSection" . }} diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_podmonitors.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_podmonitors.yaml new file mode 100644 index 0000000..153677b --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_podmonitors.yaml @@ -0,0 +1,424 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: podmonitors.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: PodMonitor + listKind: PodMonitorList + plural: podmonitors + shortNames: + - pmon + singular: podmonitor + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + attachMetadata: + properties: + node: + type: boolean + type: object + jobLabel: + type: string + labelLimit: + format: int64 + type: integer + labelNameLengthLimit: + format: int64 + type: integer + labelValueLengthLimit: + format: int64 + type: integer + namespaceSelector: + properties: + any: + type: boolean + matchNames: + items: + type: string + type: array + type: object + podMetricsEndpoints: + items: + properties: + authorization: + properties: + credentials: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: + type: string + type: object + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + bearerTokenSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + enableHttp2: + type: boolean + filterRunning: + type: boolean + followRedirects: + type: boolean + honorLabels: + type: boolean + honorTimestamps: + type: boolean + interval: + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + metricRelabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + oauth2: + properties: + clientId: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + type: object + scopes: + items: + type: string + type: array + tokenUrl: + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + params: + additionalProperties: + items: + type: string + type: array + type: object + path: + type: string + port: + type: string + proxyUrl: + type: string + relabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + scheme: + enum: + - http + - https + type: string + scrapeTimeout: + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + insecureSkipVerify: + type: boolean + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + type: object + type: array + podTargetLabels: + items: + type: string + type: array + sampleLimit: + format: int64 + type: integer + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + targetLimit: + format: int64 + type: integer + required: + - podMetricsEndpoints + - selector + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_probes.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_probes.yaml new file mode 100644 index 0000000..13fc36f --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_probes.yaml @@ -0,0 +1,458 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: probes.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: Probe + listKind: ProbeList + plural: probes + shortNames: + - prb + singular: probe + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + authorization: + properties: + credentials: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: + type: string + type: object + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + bearerTokenSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + interval: + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + jobName: + type: string + labelLimit: + format: int64 + type: integer + labelNameLengthLimit: + format: int64 + type: integer + labelValueLengthLimit: + format: int64 + type: integer + metricRelabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + module: + type: string + oauth2: + properties: + clientId: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + type: object + scopes: + items: + type: string + type: array + tokenUrl: + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + prober: + properties: + path: + default: /probe + type: string + proxyUrl: + type: string + scheme: + enum: + - http + - https + type: string + url: + type: string + required: + - url + type: object + sampleLimit: + format: int64 + type: integer + scrapeTimeout: + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetLimit: + format: int64 + type: integer + targets: + properties: + ingress: + properties: + namespaceSelector: + properties: + any: + type: boolean + matchNames: + items: + type: string + type: array + type: object + relabelingConfigs: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + type: object + staticConfig: + properties: + labels: + additionalProperties: + type: string + type: object + relabelingConfigs: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + static: + items: + type: string + type: array + type: object + type: object + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + insecureSkipVerify: + type: boolean + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_servicemonitors.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_servicemonitors.yaml new file mode 100644 index 0000000..ff62f8f --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.coreos.com_servicemonitors.yaml @@ -0,0 +1,436 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: servicemonitors.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: ServiceMonitor + listKind: ServiceMonitorList + plural: servicemonitors + shortNames: + - smon + singular: servicemonitor + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + attachMetadata: + properties: + node: + type: boolean + type: object + endpoints: + items: + properties: + authorization: + properties: + credentials: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: + type: string + type: object + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + bearerTokenFile: + type: string + bearerTokenSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + enableHttp2: + type: boolean + filterRunning: + type: boolean + followRedirects: + type: boolean + honorLabels: + type: boolean + honorTimestamps: + type: boolean + interval: + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + metricRelabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + oauth2: + properties: + clientId: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + type: object + scopes: + items: + type: string + type: array + tokenUrl: + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + params: + additionalProperties: + items: + type: string + type: array + type: object + path: + type: string + port: + type: string + proxyUrl: + type: string + relabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + scheme: + enum: + - http + - https + type: string + scrapeTimeout: + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + type: object + type: array + jobLabel: + type: string + labelLimit: + format: int64 + type: integer + labelNameLengthLimit: + format: int64 + type: integer + labelValueLengthLimit: + format: int64 + type: integer + namespaceSelector: + properties: + any: + type: boolean + matchNames: + items: + type: string + type: array + type: object + podTargetLabels: + items: + type: string + type: array + sampleLimit: + format: int64 + type: integer + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + targetLabels: + items: + type: string + type: array + targetLimit: + format: int64 + type: integer + required: + - endpoints + - selector + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_grafanaagents.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_grafanaagents.yaml new file mode 100644 index 0000000..4ec31d6 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_grafanaagents.yaml @@ -0,0 +1,3711 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: grafanaagents.monitoring.grafana.com +spec: + group: monitoring.grafana.com + names: + categories: + - agent-operator + kind: GrafanaAgent + listKind: GrafanaAgentList + plural: grafanaagents + singular: grafanaagent + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + apiServer: + properties: + authorization: + properties: + credentials: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + credentialsFile: + type: string + type: + type: string + type: object + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + bearerToken: + type: string + bearerTokenFile: + type: string + host: + type: string + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + required: + - host + type: object + configMaps: + items: + type: string + type: array + configReloaderImage: + type: string + configReloaderVersion: + type: string + containers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + disableReporting: + default: false + type: boolean + disableSupportBundle: + default: false + type: boolean + enableConfigReadAPI: + default: false + type: boolean + image: + type: string + imagePullSecrets: + items: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array + integrations: + properties: + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + type: object + logFormat: + type: string + logLevel: + type: string + logs: + properties: + clients: + items: + properties: + backoffConfig: + properties: + maxPeriod: + type: string + maxRetries: + type: integer + minPeriod: + type: string + type: object + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + batchSize: + type: integer + batchWait: + type: string + bearerToken: + type: string + bearerTokenFile: + type: string + externalLabels: + additionalProperties: + type: string + type: object + oauth2: + properties: + clientId: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + type: object + scopes: + items: + type: string + type: array + tokenUrl: + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyUrl: + type: string + tenantId: + type: string + timeout: + type: string + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + url: + type: string + required: + - url + type: object + type: array + enforcedNamespaceLabel: + type: string + ignoreNamespaceSelectors: + type: boolean + instanceNamespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + instanceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + logsExternalLabelName: + type: string + type: object + metrics: + properties: + arbitraryFSAccessThroughSMs: + properties: + deny: + type: boolean + type: object + enforcedNamespaceLabel: + type: string + enforcedSampleLimit: + format: int64 + type: integer + enforcedTargetLimit: + format: int64 + type: integer + externalLabels: + additionalProperties: + type: string + type: object + ignoreNamespaceSelectors: + type: boolean + instanceNamespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + instanceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + metricsExternalLabelName: + type: string + overrideHonorLabels: + type: boolean + overrideHonorTimestamps: + type: boolean + remoteWrite: + items: + properties: + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + bearerToken: + type: string + bearerTokenFile: + type: string + headers: + additionalProperties: + type: string + type: object + metadataConfig: + properties: + send: + type: boolean + sendInterval: + type: string + type: object + name: + type: string + oauth2: + properties: + clientId: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + type: object + scopes: + items: + type: string + type: array + tokenUrl: + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyUrl: + type: string + queueConfig: + properties: + batchSendDeadline: + type: string + capacity: + type: integer + maxBackoff: + type: string + maxRetries: + type: integer + maxSamplesPerSend: + type: integer + maxShards: + type: integer + minBackoff: + type: string + minShards: + type: integer + retryOnRateLimit: + type: boolean + type: object + remoteTimeout: + type: string + sigv4: + properties: + accessKey: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + profile: + type: string + region: + type: string + roleARN: + type: string + secretKey: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + url: + type: string + writeRelabelConfigs: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + required: + - url + type: object + type: array + replicaExternalLabelName: + type: string + replicas: + format: int32 + type: integer + scrapeInterval: + type: string + scrapeTimeout: + type: string + shards: + format: int32 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + paused: + type: boolean + podMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + type: object + portName: + type: string + priorityClassName: + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + runtimeClassName: + type: string + secrets: + items: + type: string + type: array + securityContext: + properties: + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccountName: + type: string + storage: + properties: + disableMountSubPath: + type: boolean + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + volumeClaimTemplate: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + phase: + type: string + type: object + type: object + type: object + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + version: + type: string + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_integrations.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_integrations.yaml new file mode 100644 index 0000000..960b2f7 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_integrations.yaml @@ -0,0 +1,810 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: integrations.monitoring.grafana.com +spec: + group: monitoring.grafana.com + names: + categories: + - agent-operator + kind: Integration + listKind: IntegrationList + plural: integrations + singular: integration + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + config: + type: object + x-kubernetes-preserve-unknown-fields: true + configMaps: + items: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: array + name: + type: string + secrets: + items: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: array + type: + properties: + allNodes: + type: boolean + unique: + type: boolean + type: object + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + type: string + kind: + type: string + readOnly: + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + wwids: + items: + type: string + type: array + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + type: string + monitors: + items: + type: string + type: array + pool: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + required: + - config + - name + - type + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_logsinstances.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_logsinstances.yaml new file mode 100644 index 0000000..517bb30 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_logsinstances.yaml @@ -0,0 +1,299 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: logsinstances.monitoring.grafana.com +spec: + group: monitoring.grafana.com + names: + categories: + - agent-operator + kind: LogsInstance + listKind: LogsInstanceList + plural: logsinstances + singular: logsinstance + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + additionalScrapeConfigs: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + clients: + items: + properties: + backoffConfig: + properties: + maxPeriod: + type: string + maxRetries: + type: integer + minPeriod: + type: string + type: object + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + batchSize: + type: integer + batchWait: + type: string + bearerToken: + type: string + bearerTokenFile: + type: string + externalLabels: + additionalProperties: + type: string + type: object + oauth2: + properties: + clientId: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + type: object + scopes: + items: + type: string + type: array + tokenUrl: + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyUrl: + type: string + tenantId: + type: string + timeout: + type: string + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + url: + type: string + required: + - url + type: object + type: array + podLogsNamespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + podLogsSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + targetConfig: + properties: + syncPeriod: + type: string + type: object + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_metricsinstances.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_metricsinstances.yaml new file mode 100644 index 0000000..610193f --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_metricsinstances.yaml @@ -0,0 +1,495 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: metricsinstances.monitoring.grafana.com +spec: + group: monitoring.grafana.com + names: + categories: + - agent-operator + kind: MetricsInstance + listKind: MetricsInstanceList + plural: metricsinstances + singular: metricsinstance + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + additionalScrapeConfigs: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + maxWALTime: + type: string + minWALTime: + type: string + podMonitorNamespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + podMonitorSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + probeNamespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + probeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + remoteFlushDeadline: + type: string + remoteWrite: + items: + properties: + basicAuth: + properties: + password: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + username: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + bearerToken: + type: string + bearerTokenFile: + type: string + headers: + additionalProperties: + type: string + type: object + metadataConfig: + properties: + send: + type: boolean + sendInterval: + type: string + type: object + name: + type: string + oauth2: + properties: + clientId: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + clientSecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + type: object + scopes: + items: + type: string + type: array + tokenUrl: + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyUrl: + type: string + queueConfig: + properties: + batchSendDeadline: + type: string + capacity: + type: integer + maxBackoff: + type: string + maxRetries: + type: integer + maxSamplesPerSend: + type: integer + maxShards: + type: integer + minBackoff: + type: string + minShards: + type: integer + retryOnRateLimit: + type: boolean + type: object + remoteTimeout: + type: string + sigv4: + properties: + accessKey: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + profile: + type: string + region: + type: string + roleARN: + type: string + secretKey: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + serverName: + type: string + type: object + url: + type: string + writeRelabelConfigs: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + required: + - url + type: object + type: array + serviceMonitorNamespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + serviceMonitorSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + walTruncateFrequency: + type: string + writeStaleOnShutdown: + type: boolean + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_podlogs.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_podlogs.yaml new file mode 100644 index 0000000..f22d051 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/crds/monitoring.grafana.com_podlogs.yaml @@ -0,0 +1,308 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: podlogs.monitoring.grafana.com +spec: + group: monitoring.grafana.com + names: + categories: + - agent-operator + kind: PodLogs + listKind: PodLogsList + plural: podlogs + singular: podlogs + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + jobLabel: + type: string + namespaceSelector: + properties: + any: + type: boolean + matchNames: + items: + type: string + type: array + type: object + pipelineStages: + items: + properties: + cri: + type: object + docker: + type: object + drop: + properties: + dropCounterReason: + type: string + expression: + type: string + longerThan: + type: string + olderThan: + type: string + source: + type: string + value: + type: string + type: object + json: + properties: + expressions: + additionalProperties: + type: string + type: object + source: + type: string + type: object + labelAllow: + items: + type: string + type: array + labelDrop: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + limit: + properties: + burst: + type: integer + drop: + type: boolean + rate: + type: integer + type: object + match: + properties: + action: + type: string + dropCounterReason: + type: string + pipelineName: + type: string + selector: + type: string + stages: + type: string + required: + - selector + type: object + metrics: + additionalProperties: + properties: + action: + type: string + buckets: + items: + type: string + type: array + countEntryBytes: + type: boolean + description: + type: string + matchAll: + type: boolean + maxIdleDuration: + type: string + prefix: + type: string + source: + type: string + type: + type: string + value: + type: string + required: + - action + - type + type: object + type: object + multiline: + properties: + firstLine: + type: string + maxLines: + type: integer + maxWaitTime: + type: string + required: + - firstLine + type: object + output: + properties: + source: + type: string + required: + - source + type: object + pack: + properties: + ingestTimestamp: + type: boolean + labels: + items: + type: string + type: array + required: + - labels + type: object + regex: + properties: + expression: + type: string + source: + type: string + required: + - expression + type: object + replace: + properties: + expression: + type: string + replace: + type: string + source: + type: string + required: + - expression + type: object + template: + properties: + source: + type: string + template: + type: string + required: + - source + - template + type: object + tenant: + properties: + label: + type: string + source: + type: string + value: + type: string + type: object + timestamp: + properties: + actionOnFailure: + type: string + fallbackFormats: + items: + type: string + type: array + format: + type: string + location: + type: string + source: + type: string + required: + - format + - source + type: object + type: object + type: array + podTargetLabels: + items: + type: string + type: array + relabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + required: + - selector + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/templates/_helpers.tpl b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/_helpers.tpl new file mode 100644 index 0000000..e374499 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/_helpers.tpl @@ -0,0 +1,70 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ga-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ga-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ga-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ga-operator.labels" -}} +{{ include "ga-operator.selectorLabels" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: operator +helm.sh/chart: {{ include "ga-operator.chart" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if .Values.customLabels }} +{{ toYaml .Values.customLabels }} +{{- end }} +{{- with .Values.global.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ga-operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ga-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ga-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ga-operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-clusterrole.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-clusterrole.yaml new file mode 100644 index 0000000..08ad58c --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-clusterrole.yaml @@ -0,0 +1,62 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "ga-operator.fullname" . }} + labels: +{{ include "ga-operator.labels" . | indent 4 }} +rules: +- apiGroups: [monitoring.grafana.com] + resources: + - grafanaagents + - metricsinstances + - logsinstances + - podlogs + - integrations + verbs: [get, list, watch] +- apiGroups: [monitoring.grafana.com] + resources: + - grafanaagents/finalizers + - metricsinstances/finalizers + - logsinstances/finalizers + - podlogs/finalizers + - integrations/finalizers + verbs: [get, list, watch, update] +- apiGroups: [monitoring.coreos.com] + resources: + - podmonitors + - probes + - servicemonitors + verbs: [get, list, watch] +- apiGroups: [monitoring.coreos.com] + resources: + - podmonitors/finalizers + - probes/finalizers + - servicemonitors/finalizers + verbs: [get, list, watch, update] +- apiGroups: [""] + resources: + - namespaces + - nodes + verbs: [get, list, watch] +- apiGroups: [""] + resources: + - secrets + - services + - configmaps + - endpoints + verbs: [get, list, watch, create, update, patch, delete] +- apiGroups: ["apps"] + resources: + - statefulsets + - daemonsets + - deployments + verbs: [get, list, watch, create, update, patch, delete] +{{- with .Values.rbac.podSecurityPolicyName }} +- apiGroups: [policy] + resources: + - podsecuritypolicies + verbs: [use] + resourceNames: [ {{ . }} ] +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-clusterrolebinding.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-clusterrolebinding.yaml new file mode 100644 index 0000000..372d310 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-clusterrolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "ga-operator.fullname" . }} + labels: +{{ include "ga-operator.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "ga-operator.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ template "ga-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} + diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-deployment.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-deployment.yaml new file mode 100644 index 0000000..3367db1 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-deployment.yaml @@ -0,0 +1,79 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ga-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "ga-operator.labels" . | indent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: 1 + selector: + matchLabels: +{{ include "ga-operator.selectorLabels" . | indent 6 }} + template: + metadata: + labels: +{{ include "ga-operator.selectorLabels" . | indent 8 }} +{{- with .Values.podLabels }} +{{- toYaml . | nindent 8 }} +{{- end }} +{{- with .Values.podAnnotations }} + annotations: +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + serviceAccountName: {{ template "ga-operator.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ include "ga-operator.name" . }} + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if or (and .Values.kubeletService.namespace .Values.kubeletService.serviceName) (.Values.extraArgs) }} + args: + {{- if and .Values.kubeletService.namespace .Values.kubeletService.serviceName }} + - --kubelet-service={{ .Values.kubeletService.namespace }}/{{ .Values.kubeletService.serviceName }} + {{- end }} + {{- if .Values.extraArgs }} + {{- range .Values.extraArgs }} + - {{ . }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.image.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-serviceaccount.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-serviceaccount.yaml new file mode 100644 index 0000000..1f9b207 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/operator-serviceaccount.yaml @@ -0,0 +1,10 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "ga-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "ga-operator.labels" . | indent 4 }} +{{- end -}} + diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/templates/tests/test-grafanaagent.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/tests/test-grafanaagent.yaml new file mode 100644 index 0000000..4001da4 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/templates/tests/test-grafanaagent.yaml @@ -0,0 +1,118 @@ +apiVersion: monitoring.grafana.com/v1alpha1 +kind: GrafanaAgent +metadata: + name: grafana-agent-test + labels: + app: grafana-agent-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +spec: + image: "{{ .Values.image.registry }}/grafana/agent:{{ .Values.image.tag }}" + logLevel: info + serviceAccountName: grafana-agent-test-sa + metrics: + instanceSelector: + matchLabels: + agent: grafana-agent-test + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: grafana-agent-test-sa + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: grafana-agent-test-cr + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - nodes/metrics + - services + - endpoints + - pods + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch +- nonResourceURLs: + - /metrics + - /metrics/cadvisor + verbs: + - get + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: grafana-agent-test-crb + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: grafana-agent-test-cr +subjects: +- kind: ServiceAccount + name: grafana-agent-test-sa + namespace: {{ .Release.Namespace }} + +--- + +apiVersion: monitoring.grafana.com/v1alpha1 +kind: MetricsInstance +metadata: + name: primary-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + labels: + agent: grafana-agent-test +spec: {} + +--- + +apiVersion: v1 +kind: Pod +metadata: + name: grafana-agent-test-probe + annotations: + "helm.sh/hook": test + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +spec: + containers: + - name: busybox + image: "{{ .Values.test.image.registry }}/{{ .Values.test.image.repository }}:{{ .Values.test.image.tag }}" + command: ['wget'] + args: ['grafana-agent-test-operated:8080/-/healthy'] + # Wait for GrafanaAgent CR + initContainers: + - name: sleep + image: "{{ .Values.test.image.registry }}/{{ .Values.test.image.repository }}:{{ .Values.test.image.tag }}" + command: ['sleep', '60'] + restartPolicy: Never diff --git a/utils/assets/charts/loki/charts/grafana-agent-operator/values.yaml b/utils/assets/charts/loki/charts/grafana-agent-operator/values.yaml new file mode 100644 index 0000000..5f7adc5 --- /dev/null +++ b/utils/assets/charts/loki/charts/grafana-agent-operator/values.yaml @@ -0,0 +1,84 @@ +global: + # -- Common labels for all object directly managed by this chart. + commonLabels: {} + +# -- Overrides the chart's name +nameOverride: "" + +# -- Overrides the chart's computed fullname +fullnameOverride: "" + +# -- Annotations for the Deployment +annotations: {} + +# -- Annotations for the Deployment Pods +podAnnotations: {} + +# -- Annotations for the Deployment Pods +podLabels: {} + +# -- Pod security context (runAsUser, etc.) +podSecurityContext: {} + +# -- Container security context (allowPrivilegeEscalation, etc.) +containerSecurityContext: {} + +rbac: + # -- Toggle to create ClusterRole and ClusterRoleBinding + create: true + # -- Name of a PodSecurityPolicy to use in the ClusterRole. If unset, no PodSecurityPolicy is used. + podSecurityPolicyName: '' + +serviceAccount: + # -- Toggle to create ServiceAccount + create: true + # -- Service account name + name: + +image: + # -- Image registry + registry: docker.io + # -- Image repo + repository: grafana/agent-operator + # -- Image tag + tag: v0.43.3 + # -- Image pull policy + pullPolicy: IfNotPresent + # -- Image pull secrets + pullSecrets: [] + +test: + image: + # -- Test image registry + registry: docker.io + # -- Test image repo + repository: library/busybox + # -- Test image tag + tag: latest + +# -- hostAliases to add +hostAliases: [] +# - ip: 1.2.3.4 +# hostnames: +# - domain.tld + +# -- If both are set, Agent Operator will create and maintain a service for scraping kubelets +# https://grafana.com/docs/agent/latest/operator/getting-started/#monitor-kubelets +kubeletService: + namespace: default + serviceName: kubelet + +# -- List of additional cli arguments to configure agent-operator (example: `--log.level`) +extraArgs: [] + +# -- Resource limits and requests config +resources: {} + +# -- nodeSelector configuration +nodeSelector: {} + +# -- Tolerations applied to Pods +tolerations: [] + +# -- Pod affinity configuration +affinity: {} diff --git a/utils/assets/charts/loki/charts/minio/.helmignore b/utils/assets/charts/loki/charts/minio/.helmignore new file mode 100644 index 0000000..a9fe727 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +# OWNERS file for Kubernetes +OWNERS \ No newline at end of file diff --git a/utils/assets/charts/loki/charts/minio/Chart.yaml b/utils/assets/charts/loki/charts/minio/Chart.yaml new file mode 100644 index 0000000..10a6423 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +appVersion: RELEASE.2024-04-18T19-09-19Z +description: High Performance Object Storage +home: https://min.io +icon: https://min.io/resources/img/logo/MINIO_wordmark.png +keywords: +- minio +- storage +- object-storage +- s3 +- cluster +maintainers: +- email: dev@minio.io + name: MinIO, Inc +name: minio +sources: +- https://github.com/minio/minio +version: 5.3.0 diff --git a/utils/assets/charts/loki/charts/minio/README.md b/utils/assets/charts/loki/charts/minio/README.md new file mode 100644 index 0000000..a1d5c99 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/README.md @@ -0,0 +1,264 @@ +# MinIO Community Helm Chart + +[![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io) [![license](https://img.shields.io/badge/license-AGPL%20V3-blue)](https://github.com/minio/minio/blob/master/LICENSE) + +MinIO is a High Performance Object Storage released under GNU Affero General Public License v3.0. It is API compatible with Amazon S3 cloud storage service. Use MinIO to build high performance infrastructure for machine learning, analytics and application data workloads. + +| IMPORTANT | +| -------------------------- | +| This Helm chart is community built, maintained, and supported. MinIO does not guarantee support for any given bug, feature request, or update referencing this chart.

MinIO publishes a separate [MinIO Kubernetes Operator and Tenant Helm Chart](https://github.com/minio/operator/tree/master/helm) that is officially maintained and supported. MinIO strongly recommends using the MinIO Kubernetes Operator for production deployments. See [Deploy Operator With Helm](https://min.io/docs/minio/kubernetes/upstream/operations/install-deploy-manage/deploy-operator-helm.html?ref=github) for additional documentation. | + +## Introduction + +This chart bootstraps MinIO Cluster on [Kubernetes](http://kubernetes.io) using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Helm cli with Kubernetes cluster configured. +- PV provisioner support in the underlying infrastructure. (We recommend using ) +- Use Kubernetes version v1.19 and later for best experience. + +## Configure MinIO Helm repo + +```bash +helm repo add minio https://charts.min.io/ +``` + +### Installing the Chart + +Install this chart using: + +```bash +helm install --namespace minio --set rootUser=rootuser,rootPassword=rootpass123 --generate-name minio/minio +``` + +The command deploys MinIO on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. + +### Installing the Chart (toy-setup) + +Minimal toy setup for testing purposes can be deployed using: + +```bash +helm install --set resources.requests.memory=512Mi --set replicas=1 --set persistence.enabled=false --set mode=standalone --set rootUser=rootuser,rootPassword=rootpass123 --generate-name minio/minio +``` + +### Upgrading the Chart + +You can use Helm to update MinIO version in a live release. Assuming your release is named as `my-release`, get the values using the command: + +```bash +helm get values my-release > old_values.yaml +``` + +Then change the field `image.tag` in `old_values.yaml` file with MinIO image tag you want to use. Now update the chart using + +```bash +helm upgrade -f old_values.yaml my-release minio/minio +``` + +Default upgrade strategies are specified in the `values.yaml` file. Update these fields if you'd like to use a different strategy. + +### Configuration + +Refer the [Values file](./values.yaml) for all the possible config fields. + +You can specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```bash +helm install --name my-release --set persistence.size=1Ti minio/minio +``` + +The above command deploys MinIO server with a 1Ti backing persistent volume. + +Alternately, you can provide a YAML file that specifies parameter values while installing the chart. For example, + +```bash +helm install --name my-release -f values.yaml minio/minio +``` + +### Persistence + +This chart provisions a PersistentVolumeClaim and mounts corresponding persistent volume to default location `/export`. You'll need physical storage available in the Kubernetes cluster for this to work. If you'd rather use `emptyDir`, disable PersistentVolumeClaim by: + +```bash +helm install --set persistence.enabled=false minio/minio +``` + +> *"An emptyDir volume is first created when a Pod is assigned to a Node, and exists as long as that Pod is running on that node. When a Pod is removed from a node for any reason, the data in the emptyDir is deleted forever."* + +### Existing PersistentVolumeClaim + +If a Persistent Volume Claim already exists, specify it during installation. + +1. Create the PersistentVolume +2. Create the PersistentVolumeClaim +3. Install the chart + +```bash +helm install --set persistence.existingClaim=PVC_NAME minio/minio +``` + +### NetworkPolicy + +To enable network policy for MinIO, +install [a networking plugin that implements the Kubernetes +NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), +and set `networkPolicy.enabled` to `true`. + +For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting +the DefaultDeny namespace annotation. Note: this will enforce policy for *all* pods in the namespace: + +``` +kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" +``` + +When using `Cilium` as a CNI in your cluster, please edit the `flavor` field to `cilium`. + +With NetworkPolicy enabled, traffic will be limited to just port 9000. + +For more precise policy, set `networkPolicy.allowExternal=true`. This will +only allow pods with the generated client label to connect to MinIO. +This label will be displayed in the output of a successful install. + +### Existing secret + +Instead of having this chart create the secret for you, you can supply a preexisting secret, much +like an existing PersistentVolumeClaim. + +First, create the secret: + +```bash +kubectl create secret generic my-minio-secret --from-literal=rootUser=foobarbaz --from-literal=rootPassword=foobarbazqux +``` + +Then install the chart, specifying that you want to use an existing secret: + +```bash +helm install --set existingSecret=my-minio-secret minio/minio +``` + +The following fields are expected in the secret: + +| .data.\ in Secret | Corresponding variable | Description | Required | +|:------------------------|:-----------------------|:---------------|:---------| +| `rootUser` | `rootUser` | Root user. | yes | +| `rootPassword` | `rootPassword` | Root password. | yes | + +All corresponding variables will be ignored in values file. + +### Configure TLS + +To enable TLS for MinIO containers, acquire TLS certificates from a CA or create self-signed certificates. While creating / acquiring certificates ensure the corresponding domain names are set as per the standard [DNS naming conventions](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-identity) in a Kubernetes StatefulSet (for a distributed MinIO setup). Then create a secret using + +```bash +kubectl create secret generic tls-ssl-minio --from-file=path/to/private.key --from-file=path/to/public.crt +``` + +Then install the chart, specifying that you want to use the TLS secret: + +```bash +helm install --set tls.enabled=true,tls.certSecret=tls-ssl-minio minio/minio +``` + +### Installing certificates from third party CAs + +MinIO can connect to other servers, including MinIO nodes or other server types such as NATs and Redis. If these servers use certificates that were not registered with a known CA, add trust for these certificates to MinIO Server by bundling these certificates into a Kubernetes secret and providing it to Helm via the `trustedCertsSecret` value. If `.Values.tls.enabled` is `true` and you're installing certificates for third party CAs, remember to include MinIO's own certificate with key `public.crt`, if it also needs to be trusted. + +For instance, given that TLS is enabled and you need to add trust for MinIO's own CA and for the CA of a Keycloak server, a Kubernetes secret can be created from the certificate files using `kubectl`: + +``` +kubectl -n minio create secret generic minio-trusted-certs --from-file=public.crt --from-file=keycloak.crt +``` + +If TLS is not enabled, you would need only the third party CA: + +``` +kubectl -n minio create secret generic minio-trusted-certs --from-file=keycloak.crt +``` + +The name of the generated secret can then be passed to Helm using a values file or the `--set` parameter: + +``` +trustedCertsSecret: "minio-trusted-certs" + +or + +--set trustedCertsSecret=minio-trusted-certs +``` + +### Create buckets after install + +Install the chart, specifying the buckets you want to create after install: + +```bash +helm install --set buckets[0].name=bucket1,buckets[0].policy=none,buckets[0].purge=false minio/minio +``` + +Description of the configuration parameters used above - + +- `buckets[].name` - name of the bucket to create, must be a string with length > 0 +- `buckets[].policy` - can be one of none|download|upload|public +- `buckets[].purge` - purge if bucket exists already + +### Create policies after install + +Install the chart, specifying the policies you want to create after install: + +```bash +helm install --set policies[0].name=mypolicy,policies[0].statements[0].resources[0]='arn:aws:s3:::bucket1',policies[0].statements[0].actions[0]='s3:ListBucket',policies[0].statements[0].actions[1]='s3:GetObject' minio/minio +``` + +Description of the configuration parameters used above - + +- `policies[].name` - name of the policy to create, must be a string with length > 0 +- `policies[].statements[]` - list of statements, includes actions and resources +- `policies[].statements[].resources[]` - list of resources that applies the statement +- `policies[].statements[].actions[]` - list of actions granted + +### Create user after install + +Install the chart, specifying the users you want to create after install: + +```bash +helm install --set users[0].accessKey=accessKey,users[0].secretKey=secretKey,users[0].policy=none,users[1].accessKey=accessKey2,users[1].secretRef=existingSecret,users[1].secretKey=password,users[1].policy=none minio/minio +``` + +Description of the configuration parameters used above - + +- `users[].accessKey` - accessKey of user +- `users[].secretKey` - secretKey of usersecretRef +- `users[].existingSecret` - secret name that contains the secretKey of user +- `users[].existingSecretKey` - data key in existingSecret secret containing the secretKey +- `users[].policy` - name of the policy to assign to user + +### Create service account after install + +Install the chart, specifying the service accounts you want to create after install: + +```bash +helm install --set svcaccts[0].accessKey=accessKey,svcaccts[0].secretKey=secretKey,svcaccts[0].user=parentUser,svcaccts[1].accessKey=accessKey2,svcaccts[1].secretRef=existingSecret,svcaccts[1].secretKey=password,svcaccts[1].user=parentUser2 minio/minio +``` + +Description of the configuration parameters used above - + +- `svcaccts[].accessKey` - accessKey of service account +- `svcaccts[].secretKey` - secretKey of svcacctsecretRef +- `svcaccts[].existingSecret` - secret name that contains the secretKey of service account +- `svcaccts[].existingSecretKey` - data key in existingSecret secret containing the secretKey +- `svcaccts[].user` - name of the parent user to assign to service account + +## Uninstalling the Chart + +Assuming your release is named as `my-release`, delete it using the command: + +```bash +helm delete my-release +``` + +or + +```bash +helm uninstall my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. diff --git a/utils/assets/charts/loki/charts/minio/templates/NOTES.txt b/utils/assets/charts/loki/charts/minio/templates/NOTES.txt new file mode 100644 index 0000000..ba51b4c --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/NOTES.txt @@ -0,0 +1,43 @@ +{{- if eq .Values.service.type "ClusterIP" "NodePort" }} +MinIO can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: +{{ template "minio.fullname" . }}.{{ .Release.Namespace }}.{{ .Values.clusterDomain }} + +To access MinIO from localhost, run the below commands: + + 1. export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + + 2. kubectl port-forward $POD_NAME 9000 --namespace {{ .Release.Namespace }} + +Read more about port forwarding here: http://kubernetes.io/docs/user-guide/kubectl/kubectl_port-forward/ + +You can now access MinIO server on http://localhost:9000. Follow the below steps to connect to MinIO server with mc client: + + 1. Download the MinIO mc client - https://min.io/docs/minio/linux/reference/minio-mc.html#quickstart + + 2. export MC_HOST_{{ template "minio.fullname" . }}-local=http://$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "minio.secretName" . }} -o jsonpath="{.data.rootUser}" | base64 --decode):$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "minio.secretName" . }} -o jsonpath="{.data.rootPassword}" | base64 --decode)@localhost:{{ .Values.service.port }} + + 3. mc ls {{ template "minio.fullname" . }}-local + +{{- end }} +{{- if eq .Values.service.type "LoadBalancer" }} +MinIO can be accessed via port {{ .Values.service.port }} on an external IP address. Get the service external IP address by: +kubectl get svc --namespace {{ .Release.Namespace }} -l app={{ template "minio.fullname" . }} + +Note that the public IP may take a couple of minutes to be available. + +You can now access MinIO server on http://:9000. Follow the below steps to connect to MinIO server with mc client: + + 1. Download the MinIO mc client - https://min.io/docs/minio/linux/reference/minio-mc.html#quickstart + + 2. export MC_HOST_{{ template "minio.fullname" . }}-local=http://$(kubectl get secret {{ template "minio.secretName" . }} --namespace {{ .Release.Namespace }} -o jsonpath="{.data.rootUser}" | base64 --decode):$(kubectl get secret {{ template "minio.secretName" . }} -o jsonpath="{.data.rootPassword}" | base64 --decode)@:{{ .Values.service.port }} + + 3. mc ls {{ template "minio.fullname" . }} + +Alternately, you can use your browser or the MinIO SDK to access the server - https://min.io/docs/minio/linux/reference/minio-server/minio-server.html +{{- end }} + +{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} +Note: Since NetworkPolicy is enabled, only pods with label +{{ template "minio.fullname" . }}-client=true" +will be able to connect to this minio cluster. +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/_helper_create_bucket.txt b/utils/assets/charts/loki/charts/minio/templates/_helper_create_bucket.txt new file mode 100644 index 0000000..83b8dcb --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/_helper_create_bucket.txt @@ -0,0 +1,122 @@ +#!/bin/sh +set -e # Have script exit in the event of a failed command. + +{{- if .Values.configPathmc }} +MC_CONFIG_DIR="{{ .Values.configPathmc }}" +MC="/usr/bin/mc --insecure --config-dir ${MC_CONFIG_DIR}" +{{- else }} +MC="/usr/bin/mc --insecure" +{{- end }} + +# connectToMinio +# Use a check-sleep-check loop to wait for MinIO service to be available +connectToMinio() { + SCHEME=$1 + ATTEMPTS=0 + LIMIT=29 # Allow 30 attempts + set -e # fail if we can't read the keys. + ACCESS=$(cat /config/rootUser) + SECRET=$(cat /config/rootPassword) + set +e # The connections to minio are allowed to fail. + echo "Connecting to MinIO server: $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT" + MC_COMMAND="${MC} alias set myminio $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT $ACCESS $SECRET" + $MC_COMMAND + STATUS=$? + until [ $STATUS = 0 ]; do + ATTEMPTS=$(expr $ATTEMPTS + 1) + echo \"Failed attempts: $ATTEMPTS\" + if [ $ATTEMPTS -gt $LIMIT ]; then + exit 1 + fi + sleep 2 # 1 second intervals between attempts + $MC_COMMAND + STATUS=$? + done + set -e # reset `e` as active + return 0 +} + +# checkBucketExists ($bucket) +# Check if the bucket exists, by using the exit code of `mc ls` +checkBucketExists() { + BUCKET=$1 + CMD=$(${MC} stat myminio/$BUCKET >/dev/null 2>&1) + return $? +} + +# createBucket ($bucket, $policy, $purge) +# Ensure bucket exists, purging if asked to +createBucket() { + BUCKET=$1 + POLICY=$2 + PURGE=$3 + VERSIONING=$4 + OBJECTLOCKING=$5 + + # Purge the bucket, if set & exists + # Since PURGE is user input, check explicitly for `true` + if [ $PURGE = true ]; then + if checkBucketExists $BUCKET; then + echo "Purging bucket '$BUCKET'." + set +e # don't exit if this fails + ${MC} rm -r --force myminio/$BUCKET + set -e # reset `e` as active + else + echo "Bucket '$BUCKET' does not exist, skipping purge." + fi + fi + + # Create the bucket if it does not exist and set objectlocking if enabled (NOTE: versioning will be not changed if OBJECTLOCKING is set because it enables versioning to the Buckets created) + if ! checkBucketExists $BUCKET; then + if [ ! -z $OBJECTLOCKING ]; then + if [ $OBJECTLOCKING = true ]; then + echo "Creating bucket with OBJECTLOCKING '$BUCKET'" + ${MC} mb --with-lock myminio/$BUCKET + elif [ $OBJECTLOCKING = false ]; then + echo "Creating bucket '$BUCKET'" + ${MC} mb myminio/$BUCKET + fi + elif [ -z $OBJECTLOCKING ]; then + echo "Creating bucket '$BUCKET'" + ${MC} mb myminio/$BUCKET + else + echo "Bucket '$BUCKET' already exists." + fi + fi + + # set versioning for bucket if objectlocking is disabled or not set + if [ $OBJECTLOCKING = false ]; then + if [ ! -z $VERSIONING ]; then + if [ $VERSIONING = true ]; then + echo "Enabling versioning for '$BUCKET'" + ${MC} version enable myminio/$BUCKET + elif [ $VERSIONING = false ]; then + echo "Suspending versioning for '$BUCKET'" + ${MC} version suspend myminio/$BUCKET + fi + fi + else + echo "Bucket '$BUCKET' versioning unchanged." + fi + + # At this point, the bucket should exist, skip checking for existence + # Set policy on the bucket + echo "Setting policy of bucket '$BUCKET' to '$POLICY'." + ${MC} anonymous set $POLICY myminio/$BUCKET +} + +# Try connecting to MinIO instance +{{- if .Values.tls.enabled }} +scheme=https +{{- else }} +scheme=http +{{- end }} +connectToMinio $scheme + +{{ if .Values.buckets }} +{{ $global := . }} +# Create the buckets +{{- range .Values.buckets }} +createBucket {{ tpl .name $global }} {{ .policy | default "none" | quote }} {{ .purge | default false }} {{ .versioning | default false }} {{ .objectlocking | default false }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/_helper_create_policy.txt b/utils/assets/charts/loki/charts/minio/templates/_helper_create_policy.txt new file mode 100644 index 0000000..aa58495 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/_helper_create_policy.txt @@ -0,0 +1,75 @@ +#!/bin/sh +set -e ; # Have script exit in the event of a failed command. + +{{- if .Values.configPathmc }} +MC_CONFIG_DIR="{{ .Values.configPathmc }}" +MC="/usr/bin/mc --insecure --config-dir ${MC_CONFIG_DIR}" +{{- else }} +MC="/usr/bin/mc --insecure" +{{- end }} + +# connectToMinio +# Use a check-sleep-check loop to wait for MinIO service to be available +connectToMinio() { + SCHEME=$1 + ATTEMPTS=0 ; LIMIT=29 ; # Allow 30 attempts + set -e ; # fail if we can't read the keys. + ACCESS=$(cat /config/rootUser) ; SECRET=$(cat /config/rootPassword) ; + set +e ; # The connections to minio are allowed to fail. + echo "Connecting to MinIO server: $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT" ; + MC_COMMAND="${MC} alias set myminio $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT $ACCESS $SECRET" ; + $MC_COMMAND ; + STATUS=$? ; + until [ $STATUS = 0 ] + do + ATTEMPTS=`expr $ATTEMPTS + 1` ; + echo \"Failed attempts: $ATTEMPTS\" ; + if [ $ATTEMPTS -gt $LIMIT ]; then + exit 1 ; + fi ; + sleep 2 ; # 1 second intervals between attempts + $MC_COMMAND ; + STATUS=$? ; + done ; + set -e ; # reset `e` as active + return 0 +} + +# checkPolicyExists ($policy) +# Check if the policy exists, by using the exit code of `mc admin policy info` +checkPolicyExists() { + POLICY=$1 + CMD=$(${MC} admin policy info myminio $POLICY > /dev/null 2>&1) + return $? +} + +# createPolicy($name, $filename) +createPolicy () { + NAME=$1 + FILENAME=$2 + + # Create the name if it does not exist + echo "Checking policy: $NAME (in /config/$FILENAME.json)" + if ! checkPolicyExists $NAME ; then + echo "Creating policy '$NAME'" + else + echo "Policy '$NAME' already exists." + fi + ${MC} admin policy create myminio $NAME /config/$FILENAME.json + +} + +# Try connecting to MinIO instance +{{- if .Values.tls.enabled }} +scheme=https +{{- else }} +scheme=http +{{- end }} +connectToMinio $scheme + +{{ if .Values.policies }} +# Create the policies +{{- range $idx, $policy := .Values.policies }} +createPolicy {{ $policy.name }} policy_{{ $idx }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/_helper_create_svcacct.txt b/utils/assets/charts/loki/charts/minio/templates/_helper_create_svcacct.txt new file mode 100644 index 0000000..5c8aec4 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/_helper_create_svcacct.txt @@ -0,0 +1,106 @@ +#!/bin/sh +set -e ; # Have script exit in the event of a failed command. + +{{- if .Values.configPathmc }} +MC_CONFIG_DIR="{{ .Values.configPathmc }}" +MC="/usr/bin/mc --insecure --config-dir ${MC_CONFIG_DIR}" +{{- else }} +MC="/usr/bin/mc --insecure" +{{- end }} + +# AccessKey and secretkey credentials file are added to prevent shell execution errors caused by special characters. +# Special characters for example : ',",<,>,{,} +MINIO_ACCESSKEY_SECRETKEY_TMP="/tmp/accessKey_and_secretKey_svcacct_tmp" + +# connectToMinio +# Use a check-sleep-check loop to wait for MinIO service to be available +connectToMinio() { + SCHEME=$1 + ATTEMPTS=0 ; LIMIT=29 ; # Allow 30 attempts + set -e ; # fail if we can't read the keys. + ACCESS=$(cat /config/rootUser) ; SECRET=$(cat /config/rootPassword) ; + set +e ; # The connections to minio are allowed to fail. + echo "Connecting to MinIO server: $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT" ; + MC_COMMAND="${MC} alias set myminio $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT $ACCESS $SECRET" ; + $MC_COMMAND ; + STATUS=$? ; + until [ $STATUS = 0 ] + do + ATTEMPTS=`expr $ATTEMPTS + 1` ; + echo \"Failed attempts: $ATTEMPTS\" ; + if [ $ATTEMPTS -gt $LIMIT ]; then + exit 1 ; + fi ; + sleep 2 ; # 2 second intervals between attempts + $MC_COMMAND ; + STATUS=$? ; + done ; + set -e ; # reset `e` as active + return 0 +} + +# checkSvcacctExists () +# Check if the svcacct exists, by using the exit code of `mc admin user svcacct info` +checkSvcacctExists() { + CMD=$(${MC} admin user svcacct info myminio $(head -1 $MINIO_ACCESSKEY_SECRETKEY_TMP) > /dev/null 2>&1) + return $? +} + +# createSvcacct ($user) +createSvcacct () { + USER=$1 + FILENAME=$2 + #check accessKey_and_secretKey_tmp file + if [[ ! -f $MINIO_ACCESSKEY_SECRETKEY_TMP ]];then + echo "credentials file does not exist" + return 1 + fi + if [[ $(cat $MINIO_ACCESSKEY_SECRETKEY_TMP|wc -l) -ne 2 ]];then + echo "credentials file is invalid" + rm -f $MINIO_ACCESSKEY_SECRETKEY_TMP + return 1 + fi + SVCACCT=$(head -1 $MINIO_ACCESSKEY_SECRETKEY_TMP) + # Create the svcacct if it does not exist + if ! checkSvcacctExists ; then + echo "Creating svcacct '$SVCACCT'" + # Check if policy file is define + if [ -z $FILENAME ]; then + ${MC} admin user svcacct add --access-key $(head -1 $MINIO_ACCESSKEY_SECRETKEY_TMP) --secret-key $(tail -n1 $MINIO_ACCESSKEY_SECRETKEY_TMP) myminio $USER + else + ${MC} admin user svcacct add --access-key $(head -1 $MINIO_ACCESSKEY_SECRETKEY_TMP) --secret-key $(tail -n1 $MINIO_ACCESSKEY_SECRETKEY_TMP) --policy /config/$FILENAME.json myminio $USER + fi + else + echo "Svcacct '$SVCACCT' already exists." + fi + #clean up credentials files. + rm -f $MINIO_ACCESSKEY_SECRETKEY_TMP +} + +# Try connecting to MinIO instance +{{- if .Values.tls.enabled }} +scheme=https +{{- else }} +scheme=http +{{- end }} +connectToMinio $scheme + +{{ if .Values.svcaccts }} +{{ $global := . }} +# Create the svcaccts +{{- range $idx, $svc := .Values.svcaccts }} +echo {{ tpl .accessKey $global }} > $MINIO_ACCESSKEY_SECRETKEY_TMP +{{- if .existingSecret }} +cat /config/secrets-svc/{{ tpl .existingSecret $global }}/{{ tpl .existingSecretKey $global }} >> $MINIO_ACCESSKEY_SECRETKEY_TMP +# Add a new line if it doesn't exist +echo >> $MINIO_ACCESSKEY_SECRETKEY_TMP +{{ else }} +echo {{ .secretKey }} >> $MINIO_ACCESSKEY_SECRETKEY_TMP +{{- end }} +{{- if $svc.policy}} +createSvcacct {{ .user }} svc_policy_{{ $idx }} +{{ else }} +createSvcacct {{ .user }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/_helper_create_user.txt b/utils/assets/charts/loki/charts/minio/templates/_helper_create_user.txt new file mode 100644 index 0000000..bfb79be --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/_helper_create_user.txt @@ -0,0 +1,107 @@ +#!/bin/sh +set -e ; # Have script exit in the event of a failed command. + +{{- if .Values.configPathmc }} +MC_CONFIG_DIR="{{ .Values.configPathmc }}" +MC="/usr/bin/mc --insecure --config-dir ${MC_CONFIG_DIR}" +{{- else }} +MC="/usr/bin/mc --insecure" +{{- end }} + +# AccessKey and secretkey credentials file are added to prevent shell execution errors caused by special characters. +# Special characters for example : ',",<,>,{,} +MINIO_ACCESSKEY_SECRETKEY_TMP="/tmp/accessKey_and_secretKey_tmp" + +# connectToMinio +# Use a check-sleep-check loop to wait for MinIO service to be available +connectToMinio() { + SCHEME=$1 + ATTEMPTS=0 ; LIMIT=29 ; # Allow 30 attempts + set -e ; # fail if we can't read the keys. + ACCESS=$(cat /config/rootUser) ; SECRET=$(cat /config/rootPassword) ; + set +e ; # The connections to minio are allowed to fail. + echo "Connecting to MinIO server: $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT" ; + MC_COMMAND="${MC} alias set myminio $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT $ACCESS $SECRET" ; + $MC_COMMAND ; + STATUS=$? ; + until [ $STATUS = 0 ] + do + ATTEMPTS=`expr $ATTEMPTS + 1` ; + echo \"Failed attempts: $ATTEMPTS\" ; + if [ $ATTEMPTS -gt $LIMIT ]; then + exit 1 ; + fi ; + sleep 2 ; # 1 second intervals between attempts + $MC_COMMAND ; + STATUS=$? ; + done ; + set -e ; # reset `e` as active + return 0 +} + +# checkUserExists () +# Check if the user exists, by using the exit code of `mc admin user info` +checkUserExists() { + CMD=$(${MC} admin user info myminio $(head -1 $MINIO_ACCESSKEY_SECRETKEY_TMP) > /dev/null 2>&1) + return $? +} + +# createUser ($policy) +createUser() { + POLICY=$1 + #check accessKey_and_secretKey_tmp file + if [[ ! -f $MINIO_ACCESSKEY_SECRETKEY_TMP ]];then + echo "credentials file does not exist" + return 1 + fi + if [[ $(cat $MINIO_ACCESSKEY_SECRETKEY_TMP|wc -l) -ne 2 ]];then + echo "credentials file is invalid" + rm -f $MINIO_ACCESSKEY_SECRETKEY_TMP + return 1 + fi + USER=$(head -1 $MINIO_ACCESSKEY_SECRETKEY_TMP) + # Create the user if it does not exist + if ! checkUserExists ; then + echo "Creating user '$USER'" + cat $MINIO_ACCESSKEY_SECRETKEY_TMP | ${MC} admin user add myminio + else + echo "User '$USER' already exists." + fi + #clean up credentials files. + rm -f $MINIO_ACCESSKEY_SECRETKEY_TMP + + # set policy for user + if [ ! -z $POLICY -a $POLICY != " " ] ; then + echo "Adding policy '$POLICY' for '$USER'" + set +e ; # policy already attach errors out, allow it. + ${MC} admin policy attach myminio $POLICY --user=$USER + set -e + else + echo "User '$USER' has no policy attached." + fi +} + +# Try connecting to MinIO instance +{{- if .Values.tls.enabled }} +scheme=https +{{- else }} +scheme=http +{{- end }} +connectToMinio $scheme + +{{ if .Values.users }} +{{ $global := . }} +# Create the users +{{- range .Values.users }} +echo {{ tpl .accessKey $global }} > $MINIO_ACCESSKEY_SECRETKEY_TMP +{{- if .existingSecret }} +cat /config/secrets/{{ tpl .existingSecret $global }}/{{ tpl .existingSecretKey $global }} >> $MINIO_ACCESSKEY_SECRETKEY_TMP +# Add a new line if it doesn't exist +echo >> $MINIO_ACCESSKEY_SECRETKEY_TMP +createUser {{ .policy }} +{{ else }} +echo {{ .secretKey }} >> $MINIO_ACCESSKEY_SECRETKEY_TMP +createUser {{ .policy }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/_helper_custom_command.txt b/utils/assets/charts/loki/charts/minio/templates/_helper_custom_command.txt new file mode 100644 index 0000000..b583a77 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/_helper_custom_command.txt @@ -0,0 +1,58 @@ +#!/bin/sh +set -e ; # Have script exit in the event of a failed command. + +{{- if .Values.configPathmc }} +MC_CONFIG_DIR="{{ .Values.configPathmc }}" +MC="/usr/bin/mc --insecure --config-dir ${MC_CONFIG_DIR}" +{{- else }} +MC="/usr/bin/mc --insecure" +{{- end }} + +# connectToMinio +# Use a check-sleep-check loop to wait for MinIO service to be available +connectToMinio() { + SCHEME=$1 + ATTEMPTS=0 ; LIMIT=29 ; # Allow 30 attempts + set -e ; # fail if we can't read the keys. + ACCESS=$(cat /config/rootUser) ; SECRET=$(cat /config/rootPassword) ; + set +e ; # The connections to minio are allowed to fail. + echo "Connecting to MinIO server: $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT" ; + MC_COMMAND="${MC} alias set myminio $SCHEME://$MINIO_ENDPOINT:$MINIO_PORT $ACCESS $SECRET" ; + $MC_COMMAND ; + STATUS=$? ; + until [ $STATUS = 0 ] + do + ATTEMPTS=`expr $ATTEMPTS + 1` ; + echo \"Failed attempts: $ATTEMPTS\" ; + if [ $ATTEMPTS -gt $LIMIT ]; then + exit 1 ; + fi ; + sleep 2 ; # 1 second intervals between attempts + $MC_COMMAND ; + STATUS=$? ; + done ; + set -e ; # reset `e` as active + return 0 +} + +# runCommand ($@) +# Run custom mc command +runCommand() { + ${MC} "$@" + return $? +} + +# Try connecting to MinIO instance +{{- if .Values.tls.enabled }} +scheme=https +{{- else }} +scheme=http +{{- end }} +connectToMinio $scheme + +{{ if .Values.customCommands }} +# Run custom commands +{{- range .Values.customCommands }} +runCommand {{ .command }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/_helper_policy.tpl b/utils/assets/charts/loki/charts/minio/templates/_helper_policy.tpl new file mode 100644 index 0000000..8be998e --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/_helper_policy.tpl @@ -0,0 +1,28 @@ +{{- $statements_length := len .statements -}} +{{- $statements_length := sub $statements_length 1 -}} +{ + "Version": "2012-10-17", + "Statement": [ +{{- range $i, $statement := .statements }} + { + "Effect": "{{ $statement.effect | default "Allow" }}", + "Action": [ +"{{ $statement.actions | join "\",\n\"" }}" + ]{{ if $statement.resources }}, + "Resource": [ +"{{ $statement.resources | join "\",\n\"" }}" + ]{{ end }} +{{- if $statement.conditions }} +{{- $condition_len := len $statement.conditions }} +{{- $condition_len := sub $condition_len 1 }} + , + "Condition": { + {{- range $k,$v := $statement.conditions }} + {{- range $operator,$object := $v }} + "{{ $operator }}": { {{ $object }} }{{- if lt $k $condition_len }},{{- end }} + {{- end }}{{- end }} + }{{- end }} + }{{ if lt $i $statements_length }},{{end }} +{{- end }} + ] +} diff --git a/utils/assets/charts/loki/charts/minio/templates/_helpers.tpl b/utils/assets/charts/loki/charts/minio/templates/_helpers.tpl new file mode 100644 index 0000000..1cb209e --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/_helpers.tpl @@ -0,0 +1,218 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "minio.name" -}} + {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "minio.fullname" -}} + {{- if .Values.fullnameOverride -}} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- $name := default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "minio.chart" -}} + {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "minio.networkPolicy.apiVersion" -}} + {{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.Version -}} + {{- print "extensions/v1beta1" -}} + {{- else if semverCompare ">=1.7-0, <1.16-0" .Capabilities.KubeVersion.Version -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else if semverCompare "^1.16-0" .Capabilities.KubeVersion.Version -}} + {{- print "networking.k8s.io/v1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "minio.deployment.apiVersion" -}} + {{- if semverCompare "<1.9-0" .Capabilities.KubeVersion.Version -}} + {{- print "apps/v1beta2" -}} + {{- else -}} + {{- print "apps/v1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "minio.statefulset.apiVersion" -}} + {{- if semverCompare "<1.16-0" .Capabilities.KubeVersion.Version -}} + {{- print "apps/v1beta2" -}} + {{- else -}} + {{- print "apps/v1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "minio.ingress.apiVersion" -}} + {{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} + {{- print "extensions/v1beta1" -}} + {{- else if semverCompare "<1.19-0" .Capabilities.KubeVersion.GitVersion -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "networking.k8s.io/v1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for console ingress. +*/}} +{{- define "minio.consoleIngress.apiVersion" -}} + {{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} + {{- print "extensions/v1beta1" -}} + {{- else if semverCompare "<1.19-0" .Capabilities.KubeVersion.GitVersion -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "networking.k8s.io/v1" -}} + {{- end -}} +{{- end -}} + +{{/* +Determine secret name. +*/}} +{{- define "minio.secretName" -}} + {{- if .Values.existingSecret -}} + {{- .Values.existingSecret }} + {{- else -}} + {{- include "minio.fullname" . -}} + {{- end -}} +{{- end -}} + +{{/* +Determine name for scc role and rolebinding +*/}} +{{- define "minio.sccRoleName" -}} + {{- printf "%s-%s" "scc" (include "minio.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Properly format optional additional arguments to MinIO binary +*/}} +{{- define "minio.extraArgs" -}} +{{- range .Values.extraArgs -}} +{{ " " }}{{ . }} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "minio.imagePullSecrets" -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. +Also, we can not use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{- range .Values.global.imagePullSecrets }} + - name: {{ . }} +{{- end }} +{{- else if .Values.imagePullSecrets }} +imagePullSecrets: + {{ toYaml .Values.imagePullSecrets }} +{{- end -}} +{{- else if .Values.imagePullSecrets }} +imagePullSecrets: + {{ toYaml .Values.imagePullSecrets }} +{{- end -}} +{{- end -}} + +{{/* +Formats volumeMount for MinIO TLS keys and trusted certs +*/}} +{{- define "minio.tlsKeysVolumeMount" -}} +{{- if .Values.tls.enabled }} +- name: cert-secret-volume + mountPath: {{ .Values.certsPath }} +{{- end }} +{{- if or .Values.tls.enabled (ne .Values.trustedCertsSecret "") }} +{{- $casPath := printf "%s/CAs" .Values.certsPath | clean }} +- name: trusted-cert-secret-volume + mountPath: {{ $casPath }} +{{- end }} +{{- end -}} + +{{/* +Formats volume for MinIO TLS keys and trusted certs +*/}} +{{- define "minio.tlsKeysVolume" -}} +{{- if .Values.tls.enabled }} +- name: cert-secret-volume + secret: + secretName: {{ tpl .Values.tls.certSecret $ }} + items: + - key: {{ .Values.tls.publicCrt }} + path: public.crt + - key: {{ .Values.tls.privateKey }} + path: private.key +{{- end }} +{{- if or .Values.tls.enabled (ne .Values.trustedCertsSecret "") }} +{{- $certSecret := eq .Values.trustedCertsSecret "" | ternary .Values.tls.certSecret .Values.trustedCertsSecret }} +{{- $publicCrt := eq .Values.trustedCertsSecret "" | ternary .Values.tls.publicCrt "" }} +- name: trusted-cert-secret-volume + secret: + secretName: {{ $certSecret }} + {{- if ne $publicCrt "" }} + items: + - key: {{ $publicCrt }} + path: public.crt + {{- end }} +{{- end }} +{{- end -}} + +{{/* +Returns the available value for certain key in an existing secret (if it exists), +otherwise it generates a random value. +*/}} +{{- define "minio.getValueFromSecret" }} + {{- $len := (default 16 .Length) | int -}} + {{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}} + {{- if $obj }} + {{- index $obj .Key | b64dec -}} + {{- else -}} + {{- randAlphaNum $len -}} + {{- end -}} +{{- end }} + +{{- define "minio.root.username" -}} + {{- if .Values.rootUser }} + {{- .Values.rootUser | toString }} + {{- else }} + {{- include "minio.getValueFromSecret" (dict "Namespace" .Release.Namespace "Name" (include "minio.fullname" .) "Length" 20 "Key" "rootUser") }} + {{- end }} +{{- end -}} + +{{- define "minio.root.password" -}} + {{- if .Values.rootPassword }} + {{- .Values.rootPassword | toString }} + {{- else }} + {{- include "minio.getValueFromSecret" (dict "Namespace" .Release.Namespace "Name" (include "minio.fullname" .) "Length" 40 "Key" "rootPassword") }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/loki/charts/minio/templates/ciliumnetworkpolicy.yaml b/utils/assets/charts/loki/charts/minio/templates/ciliumnetworkpolicy.yaml new file mode 100644 index 0000000..1dc91bc --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/ciliumnetworkpolicy.yaml @@ -0,0 +1,33 @@ +{{- if and (.Values.networkPolicy.enabled) (eq .Values.networkPolicy.flavor "cilium") }} +kind: CiliumNetworkPolicy +apiVersion: cilium.io/v2 +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + endpointSelector: + matchLabels: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} + ingress: + - toPorts: + - ports: + - port: "{{ .Values.minioAPIPort }}" + protocol: TCP + - port: "{{ .Values.minioConsolePort }}" + protocol: TCP + {{- if not .Values.networkPolicy.allowExternal }} + fromEndpoints: + - matchLabels: + {{ template "minio.name" . }}-client: "true" + {{- end }} + egress: + {{- range $entity := .Values.networkPolicy.egressEntities }} + - toEntities: + - {{ $entity }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/configmap.yaml b/utils/assets/charts/loki/charts/minio/templates/configmap.yaml new file mode 100644 index 0000000..47f64cc --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/configmap.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + initialize: |- + {{- include (print $.Template.BasePath "/_helper_create_bucket.txt") . | nindent 4 }} + add-user: |- + {{- include (print $.Template.BasePath "/_helper_create_user.txt") . | nindent 4 }} + add-policy: |- + {{- include (print $.Template.BasePath "/_helper_create_policy.txt") . | nindent 4 }} + {{- range $idx, $policy := .Values.policies }} + # Policy: {{ $policy.name }} + policy_{{ $idx }}.json: |- + {{- include (print $.Template.BasePath "/_helper_policy.tpl") . | nindent 4 }} + {{ end }} + {{- range $idx, $svc := .Values.svcaccts }} + {{- if $svc.policy }} + # SVC: {{ $svc.accessKey }} + svc_policy_{{ $idx }}.json: |- + {{- include (print $.Template.BasePath "/_helper_policy.tpl") .policy | nindent 4 }} + {{- end }} + {{- end }} + add-svcacct: |- + {{- include (print $.Template.BasePath "/_helper_create_svcacct.txt") . | nindent 4 }} + custom-command: |- + {{- include (print $.Template.BasePath "/_helper_custom_command.txt") . | nindent 4 }} diff --git a/utils/assets/charts/loki/charts/minio/templates/console-ingress.yaml b/utils/assets/charts/loki/charts/minio/templates/console-ingress.yaml new file mode 100644 index 0000000..79a2b1b --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/console-ingress.yaml @@ -0,0 +1,55 @@ +{{- if .Values.consoleIngress.enabled -}} +{{- $fullName := printf "%s-console" (include "minio.fullname" .) -}} +{{- $servicePort := .Values.consoleService.port -}} +{{- $ingressPath := .Values.consoleIngress.path -}} +apiVersion: {{ template "minio.consoleIngress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- with .Values.consoleIngress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.consoleIngress.annotations }} + annotations: {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.consoleIngress.ingressClassName }} + ingressClassName: {{ .Values.consoleIngress.ingressClassName }} + {{- end }} + {{- if .Values.consoleIngress.tls }} + tls: + {{- range .Values.consoleIngress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.consoleIngress.hosts }} + - http: + paths: + - path: {{ $ingressPath }} + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + backend: + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- if . }} + host: {{ tpl . $ | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/console-service.yaml b/utils/assets/charts/loki/charts/minio/templates/console-service.yaml new file mode 100644 index 0000000..f09e3f3 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/console-service.yaml @@ -0,0 +1,45 @@ +{{ $scheme := .Values.tls.enabled | ternary "https" "http" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "minio.fullname" . }}-console + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.consoleService.annotations }} + annotations: {{- toYaml .Values.consoleService.annotations | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.consoleService.type }} + {{- if and (eq .Values.consoleService.type "ClusterIP") .Values.consoleService.clusterIP }} + clusterIP: {{ .Values.consoleService.clusterIP }} + {{- end }} + {{- if or (eq .Values.consoleService.type "LoadBalancer") (eq .Values.consoleService.type "NodePort") }} + externalTrafficPolicy: {{ .Values.consoleService.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.consoleService.type "LoadBalancer") .Values.consoleService.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ .Values.consoleService.loadBalancerSourceRanges }} + {{ end }} + {{- if and (eq .Values.consoleService.type "LoadBalancer") (not (empty .Values.consoleService.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.consoleService.loadBalancerIP }} + {{- end }} + ports: + - name: {{ $scheme }} + port: {{ .Values.consoleService.port }} + protocol: TCP + {{- if (and (eq .Values.consoleService.type "NodePort") ( .Values.consoleService.nodePort)) }} + nodePort: {{ .Values.consoleService.nodePort }} + {{- else }} + targetPort: {{ .Values.minioConsolePort }} + {{- end }} + {{- if .Values.consoleService.externalIPs }} + externalIPs: + {{- range $i , $ip := .Values.consoleService.externalIPs }} + - {{ $ip }} + {{- end }} + {{- end }} + selector: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} diff --git a/utils/assets/charts/loki/charts/minio/templates/deployment.yaml b/utils/assets/charts/loki/charts/minio/templates/deployment.yaml new file mode 100644 index 0000000..4c57010 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/deployment.yaml @@ -0,0 +1,213 @@ +{{- if eq .Values.mode "standalone" }} +{{ $scheme := .Values.tls.enabled | ternary "https" "http" }} +{{ $bucketRoot := or ($.Values.bucketRoot) ($.Values.mountPath) }} +apiVersion: {{ template "minio.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.additionalLabels }} + {{- toYaml .Values.additionalLabels | nindent 4 }} + {{- end }} + {{- if .Values.additionalAnnotations }} + annotations: {{- toYaml .Values.additionalAnnotations | nindent 4 }} + {{- end }} +spec: + strategy: + type: {{ .Values.deploymentUpdate.type }} + {{- if eq .Values.deploymentUpdate.type "RollingUpdate" }} + rollingUpdate: + maxSurge: {{ .Values.deploymentUpdate.maxSurge }} + maxUnavailable: {{ .Values.deploymentUpdate.maxUnavailable }} + {{- end }} + replicas: 1 + selector: + matchLabels: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} + template: + metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} + {{- if .Values.podLabels }} + {{- toYaml .Values.podLabels | nindent 8 }} + {{- end }} + annotations: + {{- if not .Values.ignoreChartChecksums }} + checksum/secrets: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- toYaml .Values.podAnnotations | trimSuffix "\n" | nindent 8 }} + {{- end }} + spec: + {{- if .Values.priorityClassName }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: "{{ .Values.runtimeClassName }}" + {{- end }} + {{- if and .Values.securityContext.enabled .Values.persistence.enabled }} + securityContext: + {{ omit .Values.securityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{ if .Values.serviceAccount.create }} + serviceAccountName: {{ .Values.serviceAccount.name }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - "/bin/sh" + - "-ce" + - "/usr/bin/docker-entrypoint.sh minio server {{ $bucketRoot }} -S {{ .Values.certsPath }} --address :{{ .Values.minioAPIPort }} --console-address :{{ .Values.minioConsolePort }} {{- template "minio.extraArgs" . }}" + volumeMounts: + - name: minio-user + mountPath: "/tmp/credentials" + readOnly: true + - name: export + mountPath: {{ .Values.mountPath }} + {{- if and .Values.persistence.enabled .Values.persistence.subPath }} + subPath: "{{ .Values.persistence.subPath }}" + {{- end }} + {{- if .Values.extraSecret }} + - name: extra-secret + mountPath: "/tmp/minio-config-env" + {{- end }} + {{- include "minio.tlsKeysVolumeMount" . | indent 12 }} + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + ports: + - name: {{ $scheme }} + containerPort: {{ .Values.minioAPIPort }} + - name: {{ $scheme }}-console + containerPort: {{ .Values.minioConsolePort }} + env: + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + name: {{ template "minio.secretName" . }} + key: rootUser + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "minio.secretName" . }} + key: rootPassword + {{- if .Values.extraSecret }} + - name: MINIO_CONFIG_ENV_FILE + value: "/tmp/minio-config-env/config.env" + {{- end }} + {{- if .Values.metrics.serviceMonitor.public }} + - name: MINIO_PROMETHEUS_AUTH_TYPE + value: "public" + {{- end }} + {{- if .Values.oidc.enabled }} + - name: MINIO_IDENTITY_OPENID_CONFIG_URL + value: {{ .Values.oidc.configUrl }} + - name: MINIO_IDENTITY_OPENID_CLIENT_ID + {{- if and .Values.oidc.existingClientSecretName .Values.oidc.existingClientIdKey }} + valueFrom: + secretKeyRef: + name: {{ .Values.oidc.existingClientSecretName }} + key: {{ .Values.oidc.existingClientIdKey }} + {{- else }} + value: {{ .Values.oidc.clientId }} + {{- end }} + - name: MINIO_IDENTITY_OPENID_CLIENT_SECRET + {{- if and .Values.oidc.existingClientSecretName .Values.oidc.existingClientSecretKey }} + valueFrom: + secretKeyRef: + name: {{ .Values.oidc.existingClientSecretName }} + key: {{ .Values.oidc.existingClientSecretKey }} + {{- else }} + value: {{ .Values.oidc.clientSecret }} + {{- end }} + - name: MINIO_IDENTITY_OPENID_CLAIM_NAME + value: {{ .Values.oidc.claimName }} + - name: MINIO_IDENTITY_OPENID_CLAIM_PREFIX + value: {{ .Values.oidc.claimPrefix }} + - name: MINIO_IDENTITY_OPENID_SCOPES + value: {{ .Values.oidc.scopes }} + - name: MINIO_IDENTITY_OPENID_COMMENT + value: {{ .Values.oidc.comment }} + - name: MINIO_IDENTITY_OPENID_REDIRECT_URI + value: {{ .Values.oidc.redirectUri }} + - name: MINIO_IDENTITY_OPENID_DISPLAY_NAME + value: {{ .Values.oidc.displayName }} + {{- end }} + {{- if .Values.etcd.endpoints }} + - name: MINIO_ETCD_ENDPOINTS + value: {{ join "," .Values.etcd.endpoints | quote }} + {{- if .Values.etcd.clientCert }} + - name: MINIO_ETCD_CLIENT_CERT + value: "/tmp/credentials/etcd_client_cert.pem" + {{- end }} + {{- if .Values.etcd.clientCertKey }} + - name: MINIO_ETCD_CLIENT_CERT_KEY + value: "/tmp/credentials/etcd_client_cert_key.pem" + {{- end }} + {{- if .Values.etcd.pathPrefix }} + - name: MINIO_ETCD_PATH_PREFIX + value: {{ .Values.etcd.pathPrefix }} + {{- end }} + {{- if .Values.etcd.corednsPathPrefix }} + - name: MINIO_ETCD_COREDNS_PATH + value: {{ .Values.etcd.corednsPathPrefix }} + {{- end }} + {{- end }} + {{- range $key, $val := .Values.environment }} + - name: {{ $key }} + value: {{ tpl $val $ | quote }} + {{- end }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- if and .Values.securityContext.enabled .Values.persistence.enabled }} + {{- with .Values.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 12}} + {{- end }} + {{- end }} + {{- with .Values.extraContainers }} + {{- if eq (typeOf .) "string" }} + {{- tpl . $ | nindent 8 }} + {{- else }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "minio.imagePullSecrets" . | indent 6 }} + {{- with .Values.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: export + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ .Values.persistence.existingClaim | default (include "minio.fullname" .) }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.extraSecret }} + - name: extra-secret + secret: + secretName: {{ .Values.extraSecret }} + {{- end }} + - name: minio-user + secret: + secretName: {{ template "minio.secretName" . }} + {{- include "minio.tlsKeysVolume" . | indent 8 }} + {{- if .Values.extraVolumes }} + {{ toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/ingress.yaml b/utils/assets/charts/loki/charts/minio/templates/ingress.yaml new file mode 100644 index 0000000..1a564c6 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/ingress.yaml @@ -0,0 +1,55 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "minio.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: {{ template "minio.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- with .Values.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingress.annotations }} + annotations: {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.ingressClassName }} + ingressClassName: {{ .Values.ingress.ingressClassName }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - http: + paths: + - path: {{ $ingressPath }} + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + backend: + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- if . }} + host: {{ tpl . $ | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/networkpolicy.yaml b/utils/assets/charts/loki/charts/minio/templates/networkpolicy.yaml new file mode 100644 index 0000000..b9c0771 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/networkpolicy.yaml @@ -0,0 +1,26 @@ +{{- if and (.Values.networkPolicy.enabled) (eq .Values.networkPolicy.flavor "kubernetes") }} +kind: NetworkPolicy +apiVersion: {{ template "minio.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + podSelector: + matchLabels: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} + ingress: + - ports: + - port: {{ .Values.minioAPIPort }} + - port: {{ .Values.minioConsolePort }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "minio.name" . }}-client: "true" + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/poddisruptionbudget.yaml b/utils/assets/charts/loki/charts/minio/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..a5f90a0 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/poddisruptionbudget.yaml @@ -0,0 +1,17 @@ +{{- if .Values.podDisruptionBudget.enabled }} +{{- if .Capabilities.APIVersions.Has "policy/v1beta1/PodDisruptionBudget" }} +apiVersion: policy/v1beta1 +{{- else }} +apiVersion: policy/v1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: minio + labels: + app: {{ template "minio.name" . }} +spec: + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + selector: + matchLabels: + app: {{ template "minio.name" . }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/post-job.yaml b/utils/assets/charts/loki/charts/minio/templates/post-job.yaml new file mode 100644 index 0000000..955d655 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/post-job.yaml @@ -0,0 +1,258 @@ +{{- if or .Values.buckets .Values.users .Values.policies .Values.customCommands .Values.svcaccts }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "minio.fullname" . }}-post-job + labels: + app: {{ template "minio.name" . }}-post-job + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation + {{- with .Values.postJob.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + template: + metadata: + labels: + app: {{ template "minio.name" . }}-job + release: {{ .Release.Name }} + {{- if .Values.podLabels }} + {{- toYaml .Values.podLabels | nindent 8 }} + {{- end }} + {{- if .Values.postJob.podAnnotations }} + annotations: {{- toYaml .Values.postJob.podAnnotations | nindent 8 }} + {{- end }} + spec: + restartPolicy: OnFailure + {{- include "minio.imagePullSecrets" . | indent 6 }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- toYaml .Values.postJob.nodeSelector | nindent 8 }} + {{- end }} + {{- with .Values.postJob.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.postJob.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.postJob.securityContext.enabled }} + securityContext: {{ omit .Values.postJob.securityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + volumes: + - name: etc-path + emptyDir: {} + - name: tmp + emptyDir: {} + - name: minio-configuration + projected: + sources: + - configMap: + name: {{ template "minio.fullname" . }} + - secret: + name: {{ template "minio.secretName" . }} + {{- range (concat .Values.users (default (list) .Values.svcaccts)) }} + {{- if .existingSecret }} + - secret: + name: {{ tpl .existingSecret $ }} + items: + - key: {{ .existingSecretKey }} + path: secrets/{{ tpl .existingSecret $ }}/{{ tpl .existingSecretKey $ }} + {{- end }} + {{- end }} + {{- range ( default list .Values.svcaccts ) }} + {{- if .existingSecret }} + - secret: + name: {{ tpl .existingSecret $ }} + items: + - key: {{ .existingSecretKey }} + path: secrets-svc/{{ tpl .existingSecret $ }}/{{ tpl .existingSecretKey $ }} + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: cert-secret-volume-mc + secret: + secretName: {{ .Values.tls.certSecret }} + items: + - key: {{ .Values.tls.publicCrt }} + path: CAs/public.crt + {{- end }} + {{- if .Values.customCommandJob.extraVolumes }} + {{- toYaml .Values.customCommandJob.extraVolumes | nindent 8 }} + {{- end }} + {{- if .Values.serviceAccount.create }} + serviceAccountName: {{ .Values.serviceAccount.name }} + {{- end }} + {{- if .Values.policies }} + initContainers: + - name: minio-make-policy + image: "{{ .Values.mcImage.repository }}:{{ .Values.mcImage.tag }}" + {{- if .Values.makePolicyJob.securityContext.enabled }} + {{- with .Values.makePolicyJob.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.mcImage.pullPolicy }} + {{- if .Values.makePolicyJob.exitCommand }} + command: [ "/bin/sh", "-c" ] + args: [ "/bin/sh /config/add-policy; EV=$?; {{ .Values.makePolicyJob.exitCommand }} && exit $EV" ] + {{- else }} + command: [ "/bin/sh", "/config/add-policy" ] + {{- end }} + env: + - name: MINIO_ENDPOINT + value: {{ template "minio.fullname" . }} + - name: MINIO_PORT + value: {{ .Values.service.port | quote }} + volumeMounts: + - name: etc-path + mountPath: /etc/minio/mc + - name: tmp + mountPath: /tmp + - name: minio-configuration + mountPath: /config + {{- if .Values.tls.enabled }} + - name: cert-secret-volume-mc + mountPath: {{ .Values.configPathmc }}certs + {{- end }} + resources: {{- toYaml .Values.makePolicyJob.resources | nindent 12 }} + {{- end }} + containers: + {{- if .Values.buckets }} + - name: minio-make-bucket + image: "{{ .Values.mcImage.repository }}:{{ .Values.mcImage.tag }}" + {{- if .Values.makeBucketJob.securityContext.enabled }} + {{- with .Values.makeBucketJob.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.mcImage.pullPolicy }} + {{- if .Values.makeBucketJob.exitCommand }} + command: [ "/bin/sh", "-c" ] + args: [ "/bin/sh /config/initialize; EV=$?; {{ .Values.makeBucketJob.exitCommand }} && exit $EV" ] + {{- else }} + command: [ "/bin/sh", "/config/initialize" ] + {{- end }} + env: + - name: MINIO_ENDPOINT + value: {{ template "minio.fullname" . }} + - name: MINIO_PORT + value: {{ .Values.service.port | quote }} + volumeMounts: + - name: etc-path + mountPath: /etc/minio/mc + - name: tmp + mountPath: /tmp + - name: minio-configuration + mountPath: /config + {{- if .Values.tls.enabled }} + - name: cert-secret-volume-mc + mountPath: {{ .Values.configPathmc }}certs + {{- end }} + resources: {{- toYaml .Values.makeBucketJob.resources | nindent 12 }} + {{- end }} + {{- if .Values.users }} + - name: minio-make-user + image: "{{ .Values.mcImage.repository }}:{{ .Values.mcImage.tag }}" + {{- if .Values.makeUserJob.securityContext.enabled }} + {{- with .Values.makeUserJob.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.mcImage.pullPolicy }} + {{- if .Values.makeUserJob.exitCommand }} + command: [ "/bin/sh", "-c" ] + args: [ "/bin/sh /config/add-user; EV=$?; {{ .Values.makeUserJob.exitCommand }} && exit $EV" ] + {{- else }} + command: [ "/bin/sh", "/config/add-user" ] + {{- end }} + env: + - name: MINIO_ENDPOINT + value: {{ template "minio.fullname" . }} + - name: MINIO_PORT + value: {{ .Values.service.port | quote }} + volumeMounts: + - name: etc-path + mountPath: /etc/minio/mc + - name: tmp + mountPath: /tmp + - name: minio-configuration + mountPath: /config + {{- if .Values.tls.enabled }} + - name: cert-secret-volume-mc + mountPath: {{ .Values.configPathmc }}certs + {{- end }} + resources: {{- toYaml .Values.makeUserJob.resources | nindent 12 }} + {{- end }} + {{- if .Values.customCommands }} + - name: minio-custom-command + image: "{{ .Values.mcImage.repository }}:{{ .Values.mcImage.tag }}" + {{- if .Values.customCommandJob.securityContext.enabled }} + {{- with .Values.customCommandJob.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.mcImage.pullPolicy }} + {{- if .Values.customCommandJob.exitCommand }} + command: [ "/bin/sh", "-c" ] + args: [ "/bin/sh /config/custom-command; EV=$?; {{ .Values.customCommandJob.exitCommand }} && exit $EV" ] + {{- else }} + command: [ "/bin/sh", "/config/custom-command" ] + {{- end }} + env: + - name: MINIO_ENDPOINT + value: {{ template "minio.fullname" . }} + - name: MINIO_PORT + value: {{ .Values.service.port | quote }} + volumeMounts: + - name: etc-path + mountPath: /etc/minio/mc + - name: tmp + mountPath: /tmp + - name: minio-configuration + mountPath: /config + {{- if .Values.tls.enabled }} + - name: cert-secret-volume-mc + mountPath: {{ .Values.configPathmc }}certs + {{- end }} + {{- if .Values.customCommandJob.extraVolumeMounts }} + {{- toYaml .Values.customCommandJob.extraVolumeMounts | nindent 12 }} + {{- end }} + resources: {{- toYaml .Values.customCommandJob.resources | nindent 12 }} + {{- end }} + {{- if .Values.svcaccts }} + - name: minio-make-svcacct + image: "{{ .Values.mcImage.repository }}:{{ .Values.mcImage.tag }}" + {{- if .Values.makeServiceAccountJob.securityContext.enabled }} + {{- with .Values.makeServiceAccountJob.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.mcImage.pullPolicy }} + {{- if .Values.makeServiceAccountJob.exitCommand }} + command: [ "/bin/sh", "-c" ] + args: ["/bin/sh /config/add-svcacct; EV=$?; {{ .Values.makeServiceAccountJob.exitCommand }} && exit $EV" ] + {{- else }} + command: ["/bin/sh", "/config/add-svcacct"] + {{- end }} + env: + - name: MINIO_ENDPOINT + value: {{ template "minio.fullname" . }} + - name: MINIO_PORT + value: {{ .Values.service.port | quote }} + volumeMounts: + - name: etc-path + mountPath: /etc/minio/mc + - name: tmp + mountPath: /tmp + - name: minio-configuration + mountPath: /config + {{- if .Values.tls.enabled }} + - name: cert-secret-volume-mc + mountPath: {{ .Values.configPathmc }}certs + {{- end }} + resources: {{- toYaml .Values.makeServiceAccountJob.resources | nindent 12 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/pvc.yaml b/utils/assets/charts/loki/charts/minio/templates/pvc.yaml new file mode 100644 index 0000000..60f5267 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/pvc.yaml @@ -0,0 +1,32 @@ +{{- if eq .Values.mode "standalone" }} +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.persistence.annotations }} + annotations: {{- toYaml .Values.persistence.annotations | nindent 4 }} + {{- end }} +spec: + accessModes: + - {{ .Values.persistence.accessMode | quote }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" + {{- end }} + {{- end }} + {{- if .Values.persistence.volumeName }} + volumeName: "{{ .Values.persistence.volumeName }}" + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/secrets.yaml b/utils/assets/charts/loki/charts/minio/templates/secrets.yaml new file mode 100644 index 0000000..476c3da --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/secrets.yaml @@ -0,0 +1,21 @@ +{{- if not .Values.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "minio.secretName" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +type: Opaque +data: + rootUser: {{ include "minio.root.username" . | b64enc | quote }} + rootPassword: {{ include "minio.root.password" . | b64enc | quote }} + {{- if .Values.etcd.clientCert }} + etcd_client.crt: {{ .Values.etcd.clientCert | toString | b64enc | quote }} + {{- end }} + {{- if .Values.etcd.clientCertKey }} + etcd_client.key: {{ .Values.etcd.clientCertKey | toString | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/securitycontextconstraints.yaml b/utils/assets/charts/loki/charts/minio/templates/securitycontextconstraints.yaml new file mode 100644 index 0000000..4bac7e3 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/securitycontextconstraints.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.securityContext.enabled .Values.persistence.enabled (.Capabilities.APIVersions.Has "security.openshift.io/v1") }} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: true +allowPrivilegedContainer: false +allowedCapabilities: [] +readOnlyRootFilesystem: false +defaultAddCapabilities: [] +requiredDropCapabilities: +- KILL +- MKNOD +- SETUID +- SETGID +fsGroup: + type: MustRunAs + ranges: + - max: {{ .Values.securityContext.fsGroup }} + min: {{ .Values.securityContext.fsGroup }} +runAsUser: + type: MustRunAs + uid: {{ .Values.securityContext.runAsUser }} +seLinuxContext: + type: MustRunAs +supplementalGroups: + type: RunAsAny +volumes: +- configMap +- downwardAPI +- emptyDir +- persistentVolumeClaim +- projected +- secret +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/service.yaml b/utils/assets/charts/loki/charts/minio/templates/service.yaml new file mode 100644 index 0000000..d872cd0 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/service.yaml @@ -0,0 +1,46 @@ +{{ $scheme := .Values.tls.enabled | ternary "https" "http" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + monitoring: "true" + {{- if .Values.service.annotations }} + annotations: {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ .Values.service.loadBalancerSourceRanges }} + {{ end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }} + loadBalancerIP: {{ default "" .Values.service.loadBalancerIP | quote }} + {{- end }} + ports: + - name: {{ $scheme }} + port: {{ .Values.service.port }} + protocol: TCP + {{- if (and (eq .Values.service.type "NodePort") ( .Values.service.nodePort)) }} + nodePort: {{ .Values.service.nodePort }} + {{- else }} + targetPort: {{ .Values.minioAPIPort }} + {{- end }} + {{- if .Values.service.externalIPs }} + externalIPs: + {{- range $i , $ip := .Values.service.externalIPs }} + - {{ $ip }} + {{- end }} + {{- end }} + selector: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} diff --git a/utils/assets/charts/loki/charts/minio/templates/serviceaccount.yaml b/utils/assets/charts/loki/charts/minio/templates/serviceaccount.yaml new file mode 100644 index 0000000..0784015 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/serviceaccount.yaml @@ -0,0 +1,6 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccount.name | quote }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/servicemonitor.yaml b/utils/assets/charts/loki/charts/minio/templates/servicemonitor.yaml new file mode 100644 index 0000000..f875a85 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/servicemonitor.yaml @@ -0,0 +1,112 @@ +{{- if and .Values.metrics.serviceMonitor.enabled .Values.metrics.serviceMonitor.includeNode }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "minio.fullname" . }} + {{- if .Values.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.metrics.serviceMonitor.namespace }} + {{- end }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- toYaml .Values.metrics.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.annotations }} + annotations: {{- toYaml .Values.metrics.serviceMonitor.annotations | nindent 4 }} + {{- end }} +spec: + endpoints: + {{- if .Values.tls.enabled }} + - port: https + scheme: https + tlsConfig: + ca: + secret: + name: {{ .Values.tls.certSecret }} + key: {{ .Values.tls.publicCrt }} + serverName: {{ template "minio.fullname" . }} + {{- else }} + - port: http + scheme: http + {{- end }} + path: /minio/v2/metrics/node + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelConfigs }} + {{- toYaml .Values.metrics.serviceMonitor.relabelConfigs | nindent 6 }} + {{- end }} + {{- if not .Values.metrics.serviceMonitor.public }} + bearerTokenSecret: + name: {{ template "minio.fullname" . }}-prometheus + key: token + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + selector: + matchLabels: + app: {{ include "minio.name" . }} + release: {{ .Release.Name }} + monitoring: "true" +{{- end }} +{{- if .Values.metrics.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: Probe +metadata: + name: {{ template "minio.fullname" . }}-cluster + {{- if .Values.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.metrics.serviceMonitor.namespace }} + {{- end }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- toYaml .Values.metrics.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} +spec: + jobName: {{ template "minio.fullname" . }} + {{- if .Values.tls.enabled }} + tlsConfig: + ca: + secret: + name: {{ .Values.tls.certSecret }} + key: {{ .Values.tls.publicCrt }} + serverName: {{ template "minio.fullname" . }} + {{- end }} + prober: + url: {{ template "minio.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.port }} + path: /minio/v2/metrics/cluster + {{- if .Values.tls.enabled }} + scheme: https + {{- else }} + scheme: http + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelConfigsCluster }} + {{- toYaml .Values.metrics.serviceMonitor.relabelConfigsCluster | nindent 2 }} + {{- end }} + targets: + staticConfig: + static: + - {{ template "minio.fullname" . }}.{{ .Release.Namespace }} + {{- if not .Values.metrics.serviceMonitor.public }} + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + bearerTokenSecret: + name: {{ template "minio.fullname" . }}-prometheus + key: token + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/templates/statefulset.yaml b/utils/assets/charts/loki/charts/minio/templates/statefulset.yaml new file mode 100644 index 0000000..d671eaa --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/templates/statefulset.yaml @@ -0,0 +1,267 @@ +{{- if eq .Values.mode "distributed" }} +{{ $poolCount := .Values.pools | int }} +{{ $nodeCount := .Values.replicas | int }} +{{ $replicas := mul $poolCount $nodeCount }} +{{ $drivesPerNode := .Values.drivesPerNode | int }} +{{ $scheme := .Values.tls.enabled | ternary "https" "http" }} +{{ $mountPath := .Values.mountPath }} +{{ $bucketRoot := or ($.Values.bucketRoot) ($.Values.mountPath) }} +{{ $subPath := .Values.persistence.subPath }} +{{ $penabled := .Values.persistence.enabled }} +{{ $accessMode := .Values.persistence.accessMode }} +{{ $storageClass := .Values.persistence.storageClass }} +{{ $psize := .Values.persistence.size }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "minio.fullname" . }}-svc + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + publishNotReadyAddresses: true + clusterIP: None + ports: + - name: {{ $scheme }} + port: {{ .Values.service.port }} + protocol: TCP + targetPort: {{ .Values.minioAPIPort }} + selector: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} +--- +apiVersion: {{ template "minio.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + chart: {{ template "minio.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.additionalLabels }} + {{- toYaml .Values.additionalLabels | nindent 4 }} + {{- end }} + {{- if .Values.additionalAnnotations }} + annotations: {{- toYaml .Values.additionalAnnotations | nindent 4 }} + {{- end }} +spec: + updateStrategy: + type: {{ .Values.statefulSetUpdate.updateStrategy }} + podManagementPolicy: "Parallel" + serviceName: {{ template "minio.fullname" . }}-svc + replicas: {{ $replicas }} + selector: + matchLabels: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} + template: + metadata: + name: {{ template "minio.fullname" . }} + labels: + app: {{ template "minio.name" . }} + release: {{ .Release.Name }} + {{- if .Values.podLabels }} + {{- toYaml .Values.podLabels | nindent 8 }} + {{- end }} + annotations: + {{- if not .Values.ignoreChartChecksums }} + checksum/secrets: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} + spec: + {{- if .Values.priorityClassName }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: "{{ .Values.runtimeClassName }}" + {{- end }} + {{- if and .Values.securityContext.enabled .Values.persistence.enabled }} + securityContext: + {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.serviceAccount.create }} + serviceAccountName: {{ .Values.serviceAccount.name }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: [ + "/bin/sh", + "-ce", + "/usr/bin/docker-entrypoint.sh minio server {{- range $i := until $poolCount }}{{ $factor := mul $i $nodeCount }}{{ $endIndex := add $factor $nodeCount }}{{ $beginIndex := mul $i $nodeCount }} {{ $scheme }}://{{ template `minio.fullname` $ }}-{{ `{` }}{{ $beginIndex }}...{{ sub $endIndex 1 }}{{ `}`}}.{{ template `minio.fullname` $ }}-svc.{{ $.Release.Namespace }}.svc{{if (gt $drivesPerNode 1)}}{{ $bucketRoot }}-{{ `{` }}0...{{ sub $drivesPerNode 1 }}{{ `}` }}{{ else }}{{ $bucketRoot }}{{end }}{{- end }} -S {{ .Values.certsPath }} --address :{{ .Values.minioAPIPort }} --console-address :{{ .Values.minioConsolePort }} {{- template `minio.extraArgs` . }}" + ] + volumeMounts: + {{- if $penabled }} + {{- if (gt $drivesPerNode 1) }} + {{- range $i := until $drivesPerNode }} + - name: export-{{ $i }} + mountPath: {{ $mountPath }}-{{ $i }} + {{- if and $penabled $subPath }} + subPath: {{ $subPath }} + {{- end }} + {{- end }} + {{- else }} + - name: export + mountPath: {{ $mountPath }} + {{- if and $penabled $subPath }} + subPath: {{ $subPath }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.extraSecret }} + - name: extra-secret + mountPath: "/tmp/minio-config-env" + {{- end }} + {{- include "minio.tlsKeysVolumeMount" . | indent 12 }} + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + ports: + - name: {{ $scheme }} + containerPort: {{ .Values.minioAPIPort }} + - name: {{ $scheme }}-console + containerPort: {{ .Values.minioConsolePort }} + env: + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + name: {{ template "minio.secretName" . }} + key: rootUser + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "minio.secretName" . }} + key: rootPassword + {{- if .Values.extraSecret }} + - name: MINIO_CONFIG_ENV_FILE + value: "/tmp/minio-config-env/config.env" + {{- end }} + {{- if .Values.metrics.serviceMonitor.public }} + - name: MINIO_PROMETHEUS_AUTH_TYPE + value: "public" + {{- end }} + {{- if .Values.oidc.enabled }} + - name: MINIO_IDENTITY_OPENID_CONFIG_URL + value: {{ .Values.oidc.configUrl }} + - name: MINIO_IDENTITY_OPENID_CLIENT_ID + {{- if and .Values.oidc.existingClientSecretName .Values.oidc.existingClientIdKey }} + valueFrom: + secretKeyRef: + name: {{ .Values.oidc.existingClientSecretName }} + key: {{ .Values.oidc.existingClientIdKey }} + {{- else }} + value: {{ .Values.oidc.clientId }} + {{- end }} + - name: MINIO_IDENTITY_OPENID_CLIENT_SECRET + {{- if and .Values.oidc.existingClientSecretName .Values.oidc.existingClientSecretKey }} + valueFrom: + secretKeyRef: + name: {{ .Values.oidc.existingClientSecretName }} + key: {{ .Values.oidc.existingClientSecretKey }} + {{- else }} + value: {{ .Values.oidc.clientSecret }} + {{- end }} + - name: MINIO_IDENTITY_OPENID_CLAIM_NAME + value: {{ .Values.oidc.claimName }} + - name: MINIO_IDENTITY_OPENID_CLAIM_PREFIX + value: {{ .Values.oidc.claimPrefix }} + - name: MINIO_IDENTITY_OPENID_SCOPES + value: {{ .Values.oidc.scopes }} + - name: MINIO_IDENTITY_OPENID_COMMENT + value: {{ .Values.oidc.comment }} + - name: MINIO_IDENTITY_OPENID_REDIRECT_URI + value: {{ .Values.oidc.redirectUri }} + - name: MINIO_IDENTITY_OPENID_DISPLAY_NAME + value: {{ .Values.oidc.displayName }} + {{- end }} + {{- range $key, $val := .Values.environment }} + - name: {{ $key }} + value: {{ tpl $val $ | quote }} + {{- end }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- if and .Values.securityContext.enabled .Values.persistence.enabled }} + {{- with .Values.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 12}} + {{- end }} + {{- end }} + {{- with .Values.extraContainers }} + {{- if eq (typeOf .) "string" }} + {{- tpl . $ | nindent 8 }} + {{- else }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "minio.imagePullSecrets" . | indent 6 }} + {{- with .Values.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and (gt $replicas 1) (ge .Capabilities.KubeVersion.Major "1") (ge .Capabilities.KubeVersion.Minor "19") }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + volumes: + - name: minio-user + secret: + secretName: {{ template "minio.secretName" . }} + {{- if .Values.extraSecret }} + - name: extra-secret + secret: + secretName: {{ .Values.extraSecret }} + {{- end }} + {{- include "minio.tlsKeysVolume" . | indent 8 }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + {{- if gt $drivesPerNode 1 }} + {{- range $diskId := until $drivesPerNode}} + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: export-{{ $diskId }} + {{- if $.Values.persistence.annotations }} + annotations: {{- toYaml $.Values.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: [ {{ $accessMode | quote }} ] + {{- if $storageClass }} + storageClassName: {{ $storageClass }} + {{- end }} + resources: + requests: + storage: {{ $psize }} + {{- end }} + {{- else }} + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: export + {{- if $.Values.persistence.annotations }} + annotations: {{- toYaml $.Values.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: [ {{ $accessMode | quote }} ] + {{- if $storageClass }} + storageClassName: {{ $storageClass }} + {{- end }} + resources: + requests: + storage: {{ $psize }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/minio/values.yaml b/utils/assets/charts/loki/charts/minio/values.yaml new file mode 100644 index 0000000..8eb9863 --- /dev/null +++ b/utils/assets/charts/loki/charts/minio/values.yaml @@ -0,0 +1,593 @@ +## Provide a name in place of minio for `app:` labels +## +nameOverride: "" + +## Provide a name to substitute for the full names of resources +## +fullnameOverride: "" + +## set kubernetes cluster domain where minio is running +## +clusterDomain: cluster.local + +## Set default image, imageTag, and imagePullPolicy. mode is used to indicate the +## +image: + repository: quay.io/minio/minio + tag: RELEASE.2024-04-18T19-09-19Z + pullPolicy: IfNotPresent + +imagePullSecrets: [] +# - name: "image-pull-secret" + +## Set default image, imageTag, and imagePullPolicy for the `mc` (the minio +## client used to create a default bucket). +## +mcImage: + repository: quay.io/minio/mc + tag: RELEASE.2024-04-18T16-45-29Z + pullPolicy: IfNotPresent + +## minio mode, i.e. standalone or distributed +mode: distributed ## other supported values are "standalone" + +## Additional labels to include with deployment or statefulset +additionalLabels: {} + +## Additional annotations to include with deployment or statefulset +additionalAnnotations: {} + +## Typically the deployment/statefulset includes checksums of secrets/config, +## So that when these change on a subsequent helm install, the deployment/statefulset +## is restarted. This can result in unnecessary restarts under GitOps tooling such as +## flux, so set to "true" to disable this behaviour. +ignoreChartChecksums: false + +## Additional arguments to pass to minio binary +extraArgs: [] +# example for enabling FTP: +# - --ftp=\"address=:8021\" +# - --ftp=\"passive-port-range=10000-10010\" + +## Additional volumes to minio container +extraVolumes: [] + +## Additional volumeMounts to minio container +extraVolumeMounts: [] + +## Additional sidecar containers +extraContainers: [] + +## Internal port number for MinIO S3 API container +## Change service.port to change external port number +minioAPIPort: "9000" + +## Internal port number for MinIO Browser Console container +## Change consoleService.port to change external port number +minioConsolePort: "9001" + +## Update strategy for Deployments +deploymentUpdate: + type: RollingUpdate + maxUnavailable: 0 + maxSurge: 100% + +## Update strategy for StatefulSets +statefulSetUpdate: + updateStrategy: RollingUpdate + +## Pod priority settings +## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +priorityClassName: "" + +## Pod runtime class name +## ref https://kubernetes.io/docs/concepts/containers/runtime-class/ +## +runtimeClassName: "" + +## Set default rootUser, rootPassword +## rootUser and rootPassword is generated when not set +## Distributed MinIO ref: https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-multi-node-multi-drive.html +## +rootUser: "" +rootPassword: "" + +## Use existing Secret that store following variables: +## +## | Chart var | .data. in Secret | +## |:----------------------|:-------------------------| +## | rootUser | rootUser | +## | rootPassword | rootPassword | +## +## All mentioned variables will be ignored in values file. +## .data.rootUser and .data.rootPassword are mandatory, +## others depend on enabled status of corresponding sections. +existingSecret: "" + +## Directory on the MinIO pof +certsPath: "/etc/minio/certs/" +configPathmc: "/etc/minio/mc/" + +## Path where PV would be mounted on the MinIO Pod +mountPath: "/export" +## Override the root directory which the minio server should serve from. +## If left empty, it defaults to the value of {{ .Values.mountPath }} +## If defined, it must be a sub-directory of the path specified in {{ .Values.mountPath }} +## +bucketRoot: "" + +# Number of drives attached to a node +drivesPerNode: 1 +# Number of MinIO containers running +replicas: 16 +# Number of expanded MinIO clusters +pools: 1 + +## TLS Settings for MinIO +tls: + enabled: false + ## Create a secret with private.key and public.crt files and pass that here. Ref: https://github.com/minio/minio/tree/master/docs/tls/kubernetes#2-create-kubernetes-secret + certSecret: "" + publicCrt: public.crt + privateKey: private.key + +## Trusted Certificates Settings for MinIO. Ref: https://min.io/docs/minio/linux/operations/network-encryption.html#third-party-certificate-authorities +## Bundle multiple trusted certificates into one secret and pass that here. Ref: https://github.com/minio/minio/tree/master/docs/tls/kubernetes#2-create-kubernetes-secret +## When using self-signed certificates, remember to include MinIO's own certificate in the bundle with key public.crt. +## If certSecret is left empty and tls is enabled, this chart installs the public certificate from .Values.tls.certSecret. +trustedCertsSecret: "" + +## Enable persistence using Persistent Volume Claims +## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + enabled: true + annotations: {} + + ## A manually managed Persistent Volume and Claim + ## Requires persistence.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## minio data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + ## Storage class of PV to bind. By default it looks for standard storage class. + ## If the PV uses a different storage class, specify that here. + storageClass: "" + volumeName: "" + accessMode: ReadWriteOnce + size: 500Gi + + ## If subPath is set mount a sub folder of a volume instead of the root of the volume. + ## This is especially handy for volume plugins that don't natively support sub mounting (like glusterfs). + ## + subPath: "" + +## Expose the MinIO service to be accessed from outside the cluster (LoadBalancer service). +## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. +## ref: http://kubernetes.io/docs/user-guide/services/ +## +service: + type: ClusterIP + clusterIP: ~ + port: "9000" + nodePort: 32000 + loadBalancerIP: ~ + externalIPs: [] + annotations: {} + + ## service.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + #loadBalancerSourceRanges: + # - 10.10.10.0/24 + loadBalancerSourceRanges: [] + + ## service.externalTrafficPolicy minio service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + +## Configure Ingress based on the documentation here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +## + +ingress: + enabled: false + ingressClassName: ~ + labels: {} + # node-role.kubernetes.io/ingress: platform + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # kubernetes.io/ingress.allow-http: "false" + # kubernetes.io/ingress.global-static-ip-name: "" + # nginx.ingress.kubernetes.io/secure-backends: "true" + # nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + # nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0 + path: / + hosts: + - minio-example.local + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +consoleService: + type: ClusterIP + clusterIP: ~ + port: "9001" + nodePort: 32001 + loadBalancerIP: ~ + externalIPs: [] + annotations: {} + ## consoleService.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + #loadBalancerSourceRanges: + # - 10.10.10.0/24 + loadBalancerSourceRanges: [] + + ## servconsoleServiceice.externalTrafficPolicy minio service external traffic policy + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + +consoleIngress: + enabled: false + ingressClassName: ~ + labels: {} + # node-role.kubernetes.io/ingress: platform + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # kubernetes.io/ingress.allow-http: "false" + # kubernetes.io/ingress.global-static-ip-name: "" + # nginx.ingress.kubernetes.io/secure-backends: "true" + # nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + # nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0 + path: / + hosts: + - console.minio-example.local + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +## Node labels for pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} +tolerations: [] +affinity: {} +topologySpreadConstraints: [] + +## Add stateful containers to have security context, if enabled MinIO will run as this +## user and group NOTE: securityContext is only enabled if persistence.enabled=true +securityContext: + enabled: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: "OnRootMismatch" + +containerSecurityContext: + readOnlyRootFilesystem: false + +# Additational pod annotations +podAnnotations: {} + +# Additional pod labels +podLabels: {} + +## Configure resource requests and limits +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + requests: + memory: 16Gi + +## List of policies to be created after minio install +## +## In addition to default policies [readonly|readwrite|writeonly|consoleAdmin|diagnostics] +## you can define additional policies with custom supported actions and resources +policies: [] +## writeexamplepolicy policy grants creation or deletion of buckets with name +## starting with example. In addition, grants objects write permissions on buckets starting with +## example. +# - name: writeexamplepolicy +# statements: +# - effect: Allow # this is the default +# resources: +# - 'arn:aws:s3:::example*/*' +# actions: +# - "s3:AbortMultipartUpload" +# - "s3:GetObject" +# - "s3:DeleteObject" +# - "s3:PutObject" +# - "s3:ListMultipartUploadParts" +# - resources: +# - 'arn:aws:s3:::example*' +# actions: +# - "s3:CreateBucket" +# - "s3:DeleteBucket" +# - "s3:GetBucketLocation" +# - "s3:ListBucket" +# - "s3:ListBucketMultipartUploads" +## readonlyexamplepolicy policy grants access to buckets with name starting with example. +## In addition, grants objects read permissions on buckets starting with example. +# - name: readonlyexamplepolicy +# statements: +# - resources: +# - 'arn:aws:s3:::example*/*' +# actions: +# - "s3:GetObject" +# - resources: +# - 'arn:aws:s3:::example*' +# actions: +# - "s3:GetBucketLocation" +# - "s3:ListBucket" +# - "s3:ListBucketMultipartUploads" +## conditionsexample policy creates all access to example bucket with aws:username="johndoe" and source ip range 10.0.0.0/8 and 192.168.0.0/24 only +# - name: conditionsexample +# statements: +# - resources: +# - 'arn:aws:s3:::example/*' +# actions: +# - 's3:*' +# conditions: +# - StringEquals: '"aws:username": "johndoe"' +# - IpAddress: | +# "aws:SourceIp": [ +# "10.0.0.0/8", +# "192.168.0.0/24" +# ] +# +## Additional Annotations for the Kubernetes Job makePolicyJob +makePolicyJob: + securityContext: + enabled: false + runAsUser: 1000 + runAsGroup: 1000 + resources: + requests: + memory: 128Mi + # Command to run after the main command on exit + exitCommand: "" + +## List of users to be created after minio install +## +users: + ## Username, password and policy to be assigned to the user + ## Default policies are [readonly|readwrite|writeonly|consoleAdmin|diagnostics] + ## Add new policies as explained here https://min.io/docs/minio/kubernetes/upstream/administration/identity-access-management.html#access-management + ## NOTE: this will fail if LDAP is enabled in your MinIO deployment + ## make sure to disable this if you are using LDAP. + - accessKey: console + secretKey: console123 + policy: consoleAdmin + # Or you can refer to specific secret + #- accessKey: externalSecret + # existingSecret: my-secret + # existingSecretKey: password + # policy: readonly + +## Additional Annotations for the Kubernetes Job makeUserJob +makeUserJob: + securityContext: + enabled: false + runAsUser: 1000 + runAsGroup: 1000 + resources: + requests: + memory: 128Mi + # Command to run after the main command on exit + exitCommand: "" + +## List of service accounts to be created after minio install +## +svcaccts: [] + ## accessKey, secretKey and parent user to be assigned to the service accounts + ## Add new service accounts as explained here https://min.io/docs/minio/kubernetes/upstream/administration/identity-access-management/minio-user-management.html#service-accounts + # - accessKey: console-svcacct + # secretKey: console123 + # user: console + ## Or you can refer to specific secret + # - accessKey: externalSecret + # existingSecret: my-secret + # existingSecretKey: password + # user: console + ## You also can pass custom policy + # - accessKey: console-svcacct + # secretKey: console123 + # user: console + # policy: + # statements: + # - resources: + # - 'arn:aws:s3:::example*/*' + # actions: + # - "s3:AbortMultipartUpload" + # - "s3:GetObject" + # - "s3:DeleteObject" + # - "s3:PutObject" + # - "s3:ListMultipartUploadParts" + +makeServiceAccountJob: + securityContext: + enabled: false + runAsUser: 1000 + runAsGroup: 1000 + resources: + requests: + memory: 128Mi + # Command to run after the main command on exit + exitCommand: "" + +## List of buckets to be created after minio install +## +buckets: [] + # # Name of the bucket + # - name: bucket1 + # # Policy to be set on the + # # bucket [none|download|upload|public] + # policy: none + # # Purge if bucket exists already + # purge: false + # # set versioning for + # # bucket [true|false] + # versioning: false # remove this key if you do not want versioning feature + # # set objectlocking for + # # bucket [true|false] NOTE: versioning is enabled by default if you use locking + # objectlocking: false + # - name: bucket2 + # policy: none + # purge: false + # versioning: true + # # set objectlocking for + # # bucket [true|false] NOTE: versioning is enabled by default if you use locking + # objectlocking: false + +## Additional Annotations for the Kubernetes Job makeBucketJob +makeBucketJob: + securityContext: + enabled: false + runAsUser: 1000 + runAsGroup: 1000 + resources: + requests: + memory: 128Mi + # Command to run after the main command on exit + exitCommand: "" + +## List of command to run after minio install +## NOTE: the mc command TARGET is always "myminio" +customCommands: + # - command: "admin policy attach myminio consoleAdmin --group='cn=ops,cn=groups,dc=example,dc=com'" + +## Additional Annotations for the Kubernetes Job customCommandJob +customCommandJob: + securityContext: + enabled: false + runAsUser: 1000 + runAsGroup: 1000 + resources: + requests: + memory: 128Mi + ## Additional volumes to add to the post-job. + extraVolumes: [] + # - name: extra-policies + # configMap: + # name: my-extra-policies-cm + ## Additional volumeMounts to add to the custom commands container when + ## running the post-job. + extraVolumeMounts: [] + # - name: extra-policies + # mountPath: /mnt/extras/ + # Command to run after the main command on exit + exitCommand: "" + +## Merge jobs +postJob: + podAnnotations: {} + annotations: {} + securityContext: + enabled: false + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + nodeSelector: {} + tolerations: [] + affinity: {} + +## Use this field to add environment variables relevant to MinIO server. These fields will be passed on to MinIO container(s) +## when Chart is deployed +environment: + ## Please refer for comprehensive list https://min.io/docs/minio/linux/reference/minio-server/minio-server.html + ## MINIO_SUBNET_LICENSE: "License key obtained from https://subnet.min.io" + ## MINIO_BROWSER: "off" + +## The name of a secret in the same kubernetes namespace which contain secret values +## This can be useful for LDAP password, etc +## The key in the secret must be 'config.env' +## +extraSecret: ~ + +## OpenID Identity Management +## The following section documents environment variables for enabling external identity management using an OpenID Connect (OIDC)-compatible provider. +## See https://min.io/docs/minio/linux/operations/external-iam/configure-openid-external-identity-management.html for a tutorial on using these variables. +oidc: + enabled: false + configUrl: "https://identity-provider-url/.well-known/openid-configuration" + clientId: "minio" + clientSecret: "" + # Provide existing client secret from the Kubernetes Secret resource, existing secret will have priority over `clientId` and/or `clientSecret`` + existingClientSecretName: "" + existingClientIdKey: "" + existingClientSecretKey: "" + claimName: "policy" + scopes: "openid,profile,email" + redirectUri: "https://console-endpoint-url/oauth_callback" + # Can leave empty + claimPrefix: "" + comment: "" + displayName: "" + +networkPolicy: + enabled: false + # Specifies whether the policies created will be standard Network Policies (flavor: kubernetes) + # or Cilium Network Policies (flavor: cilium) + flavor: kubernetes + allowExternal: true + # only when using flavor: cilium + egressEntities: + - kube-apiserver + +## PodDisruptionBudget settings +## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ +## +podDisruptionBudget: + enabled: false + maxUnavailable: 1 + +## Specify the service account to use for the MinIO pods. If 'create' is set to 'false' +## and 'name' is left unspecified, the account 'default' will be used. +serviceAccount: + create: true + ## The name of the service account to use. If 'create' is 'true', a service account with that name + ## will be created. + name: "minio-sa" + +metrics: + serviceMonitor: + enabled: false + # scrape each node/pod individually for additional metrics + includeNode: false + public: true + additionalLabels: {} + annotations: {} + # for node metrics + relabelConfigs: {} + # for cluster metrics + relabelConfigsCluster: {} + # metricRelabelings: + # - regex: (server|pod) + # action: labeldrop + namespace: ~ + # Scrape interval, for example `interval: 30s` + interval: ~ + # Scrape timeout, for example `scrapeTimeout: 10s` + scrapeTimeout: ~ + +## ETCD settings: https://github.com/minio/minio/blob/master/docs/sts/etcd.md +## Define endpoints to enable this section. +etcd: + endpoints: [] + pathPrefix: "" + corednsPathPrefix: "" + clientCert: "" + clientCertKey: "" diff --git a/utils/assets/charts/loki/charts/rollout-operator/.helmignore b/utils/assets/charts/loki/charts/rollout-operator/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/loki/charts/rollout-operator/Chart.yaml b/utils/assets/charts/loki/charts/rollout-operator/Chart.yaml new file mode 100644 index 0000000..ebdcb57 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v2 +appVersion: v0.20.0 +description: Grafana rollout-operator +home: https://github.com/grafana/rollout-operator +kubeVersion: ^1.10.0-0 +name: rollout-operator +type: application +version: 0.20.0 diff --git a/utils/assets/charts/loki/charts/rollout-operator/README.md b/utils/assets/charts/loki/charts/rollout-operator/README.md new file mode 100644 index 0000000..ddf1d17 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/README.md @@ -0,0 +1,72 @@ +# Grafana rollout-operator Helm Chart + +Helm chart for deploying [Grafana rollout-operator](https://github.com/grafana/rollout-operator) to Kubernetes. + +# rollout-operator + +![Version: 0.20.0](https://img.shields.io/badge/Version-0.20.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.20.0](https://img.shields.io/badge/AppVersion-v0.20.0-informational?style=flat-square) + +Grafana rollout-operator + +## Requirements + +Kubernetes: `^1.10.0-0` + +## Installation + +This section describes various use cases for installation, upgrade and migration from different systems and versions. + +### Preparation + +These are the common tasks to perform before any of the use cases. + +```bash +# Add the repository +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +### Installation of Grafana Rollout Operator + +```bash +helm install -n grafana/rollout-operator +``` + +The Grafana rollout-operator should be installed in the same namespace as the statefulsets it is operating upon. +It is not a highly available application and runs as a single pod. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| fullnameOverride | string | `""` | | +| global.commonLabels | object | `{}` | Common labels for all object directly managed by this chart. | +| hostAliases | list | `[]` | hostAliases to add | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"grafana/rollout-operator"` | | +| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. | +| imagePullSecrets | list | `[]` | | +| minReadySeconds | int | `10` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | Pod Annotations | +| podLabels | object | `{}` | Pod (extra) Labels | +| podSecurityContext | object | `{}` | | +| priorityClassName | string | `""` | | +| resources.limits.memory | string | `"200Mi"` | | +| resources.requests.cpu | string | `"100m"` | | +| resources.requests.memory | string | `"100Mi"` | | +| securityContext | object | `{}` | | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| serviceMonitor.annotations | object | `{}` | ServiceMonitor annotations | +| serviceMonitor.enabled | bool | `false` | Create ServiceMonitor to scrape metrics for Prometheus | +| serviceMonitor.interval | string | `nil` | ServiceMonitor scrape interval | +| serviceMonitor.labels | object | `{}` | Additional ServiceMonitor labels | +| serviceMonitor.namespace | string | `nil` | Alternative namespace for ServiceMonitor resources | +| serviceMonitor.namespaceSelector | object | `{}` | Namespace selector for ServiceMonitor resources | +| serviceMonitor.relabelings | list | `[]` | ServiceMonitor relabel configs to apply to samples before scraping https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig | +| serviceMonitor.scrapeTimeout | string | `nil` | ServiceMonitor scrape timeout in Go duration format (e.g. 15s) | +| tolerations | list | `[]` | | diff --git a/utils/assets/charts/loki/charts/rollout-operator/README.md.gotmpl b/utils/assets/charts/loki/charts/rollout-operator/README.md.gotmpl new file mode 100644 index 0000000..0ac2d47 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/README.md.gotmpl @@ -0,0 +1,38 @@ +# Grafana rollout-operator Helm Chart + +Helm chart for deploying [Grafana rollout-operator]({{ template "chart.homepage" . }}) to Kubernetes. + +{{ template "chart.header" . }} + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +{{ template "chart.description" . }} + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +## Installation + +This section describes various use cases for installation, upgrade and migration from different systems and versions. + +### Preparation + +These are the common tasks to perform before any of the use cases. + +```bash +# Add the repository +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +### Installation of Grafana Rollout Operator + +```bash +helm install -n grafana/rollout-operator +``` + +The Grafana rollout-operator should be installed in the same namespace as the statefulsets it is operating upon. +It is not a highly available application and runs as a single pod. + +{{ template "chart.valuesSection" . }} diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/NOTES.txt b/utils/assets/charts/loki/charts/rollout-operator/templates/NOTES.txt new file mode 100644 index 0000000..a76e5ba --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/NOTES.txt @@ -0,0 +1,10 @@ +Repo : {{ .Chart.Home }} + +Validation: + +Check the logs of the pod and ensure messages for reconcilliation of the statefulsets are present. +``` +kubectl logs -n {{ .Release.Namespace }} -l {{ include "cli.labels" . }} +``` +Example log line: +level=debug ts=2022-04-20T13:59:52.783051541Z msg="reconciling StatefulSet" statefulset=mimir-store-gateway-zone-a diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/_helpers.tpl b/utils/assets/charts/loki/charts/rollout-operator/templates/_helpers.tpl new file mode 100644 index 0000000..68ae702 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/_helpers.tpl @@ -0,0 +1,82 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "rollout-operator.name" -}} +{{- default (include "rollout-operator.chartName" .) .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "rollout-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default (include "rollout-operator.chartName" .) .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Recalculate the chart name, because it may be sub-chart included as rollout_operator, +and _ is not valid in resource names. +*/}} +{{- define "rollout-operator.chartName" -}} +{{- print .Chart.Name | replace "_" "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "rollout-operator.chart" -}} +{{- printf "%s-%s" (include "rollout-operator.chartName" .) .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "rollout-operator.labels" -}} +helm.sh/chart: {{ include "rollout-operator.chart" . }} +{{ include "rollout-operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.global.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "rollout-operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "rollout-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "rollout-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "rollout-operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + + +{{- define "cli.labels" -}} +{{- $list := list -}} +{{- range $k, $v := ( include "rollout-operator.selectorLabels" . | fromYaml ) -}} +{{- $list = append $list (printf "%s=%s" $k $v) -}} +{{- end -}} +{{ join "," $list }} +{{- end -}} diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/deployment.yaml b/utils/assets/charts/loki/charts/rollout-operator/templates/deployment.yaml new file mode 100644 index 0000000..d35b866 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/deployment.yaml @@ -0,0 +1,74 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "rollout-operator.fullname" . }} + labels: + {{- include "rollout-operator.labels" . | nindent 4 }} +spec: + replicas: 1 + minReadySeconds: {{ .Values.minReadySeconds }} + selector: + matchLabels: + {{- include "rollout-operator.selectorLabels" . | nindent 6 }} + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "rollout-operator.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "rollout-operator.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: rollout-operator + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - -kubernetes.namespace={{ .Release.Namespace }} + ports: + - name: http-metrics + containerPort: 8001 + protocol: TCP + readinessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 5 + timeoutSeconds: 1 + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/role.yaml b/utils/assets/charts/loki/charts/rollout-operator/templates/role.yaml new file mode 100644 index 0000000..7bc2570 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/role.yaml @@ -0,0 +1,30 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "rollout-operator.fullname" . }} + labels: + {{- include "rollout-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - list + - get + - watch + - delete +- apiGroups: + - apps + resources: + - statefulsets + verbs: + - list + - get + - watch +- apiGroups: + - apps + resources: + - statefulsets/status + verbs: + - update diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/rolebinding.yaml b/utils/assets/charts/loki/charts/rollout-operator/templates/rolebinding.yaml new file mode 100644 index 0000000..d1cfe68 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/rolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "rollout-operator.fullname" . }} + labels: + {{- include "rollout-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "rollout-operator.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "rollout-operator.serviceAccountName" . }} diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/service.yaml b/utils/assets/charts/loki/charts/rollout-operator/templates/service.yaml new file mode 100644 index 0000000..60ce5b1 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "rollout-operator.fullname" . }} + labels: + {{- include "rollout-operator.labels" . | nindent 4 }} +spec: + type: ClusterIP + clusterIP: None + ports: + - port: 8001 + targetPort: http-metrics + protocol: TCP + name: http-metrics + selector: + {{- include "rollout-operator.selectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/serviceaccount.yaml b/utils/assets/charts/loki/charts/rollout-operator/templates/serviceaccount.yaml new file mode 100644 index 0000000..37698a4 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "rollout-operator.serviceAccountName" . }} + labels: + {{- include "rollout-operator.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/charts/rollout-operator/templates/servicemonitor.yaml b/utils/assets/charts/loki/charts/rollout-operator/templates/servicemonitor.yaml new file mode 100644 index 0000000..8fa7c1b --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/templates/servicemonitor.yaml @@ -0,0 +1,36 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "rollout-operator.fullname" . }} + {{- with .Values.serviceMonitor.namespace }} + namespace: {{ . }} + {{- end }} + labels: + {{- include "rollout-operator.labels" . | nindent 4 }} + {{- with .Values.serviceMonitor.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.serviceMonitor.namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "rollout-operator.selectorLabels" . | nindent 6 }} + endpoints: + - port: http-metrics + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + scheme: http +{{- end -}} diff --git a/utils/assets/charts/loki/charts/rollout-operator/values.yaml b/utils/assets/charts/loki/charts/rollout-operator/values.yaml new file mode 100644 index 0000000..1711671 --- /dev/null +++ b/utils/assets/charts/loki/charts/rollout-operator/values.yaml @@ -0,0 +1,89 @@ +# Default values for rollout-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + + +global: + # -- Common labels for all object directly managed by this chart. + commonLabels: {} + + +image: + repository: grafana/rollout-operator + pullPolicy: IfNotPresent + # -- Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] + +# -- hostAliases to add +hostAliases: [] +# - ip: 1.2.3.4 +# hostnames: +# - domain.tld + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# -- Pod Annotations +podAnnotations: {} + +# -- Pod (extra) Labels +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +resources: + limits: + # cpu: "1" + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi + +minReadySeconds: 10 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +priorityClassName: "" + +serviceMonitor: + # -- Create ServiceMonitor to scrape metrics for Prometheus + enabled: false + # -- Alternative namespace for ServiceMonitor resources + namespace: null + # -- Namespace selector for ServiceMonitor resources + namespaceSelector: {} + # -- ServiceMonitor annotations + annotations: {} + # -- Additional ServiceMonitor labels + labels: {} + # -- ServiceMonitor scrape interval + interval: null + # -- ServiceMonitor scrape timeout in Go duration format (e.g. 15s) + scrapeTimeout: null + # -- ServiceMonitor relabel configs to apply to samples before scraping + # https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + relabelings: [] diff --git a/utils/assets/charts/loki/distributed-values.yaml b/utils/assets/charts/loki/distributed-values.yaml new file mode 100644 index 0000000..78a1f11 --- /dev/null +++ b/utils/assets/charts/loki/distributed-values.yaml @@ -0,0 +1,71 @@ +--- +loki: + schemaConfig: + configs: + - from: 2024-04-01 + store: tsdb + object_store: s3 + schema: v13 + index: + prefix: loki_index_ + period: 24h + ingester: + chunk_encoding: snappy + tracing: + enabled: true + querier: + # Default is 4, if you have enough memory and CPU you can increase, reduce if OOMing + max_concurrent: 4 + +#gateway: +# ingress: +# enabled: true +# hosts: +# - host: FIXME +# paths: +# - path: / +# pathType: Prefix + +deploymentMode: Distributed + +ingester: + replicas: 3 +querier: + replicas: 3 + maxUnavailable: 2 +queryFrontend: + replicas: 2 + maxUnavailable: 1 +queryScheduler: + replicas: 2 +distributor: + replicas: 3 + maxUnavailable: 2 +compactor: + replicas: 1 +indexGateway: + replicas: 2 + maxUnavailable: 1 + +# optional experimental components +bloomPlanner: + replicas: 0 +bloomBuilder: + replicas: 0 +bloomGateway: + replicas: 0 + +# Enable minio for storage +minio: + enabled: true + +# Zero out replica counts of other deployment modes +backend: + replicas: 0 +read: + replicas: 0 +write: + replicas: 0 + +singleBinary: + replicas: 0 diff --git a/utils/assets/charts/loki/docs/examples/README.md b/utils/assets/charts/loki/docs/examples/README.md new file mode 100644 index 0000000..84cbae3 --- /dev/null +++ b/utils/assets/charts/loki/docs/examples/README.md @@ -0,0 +1,4 @@ +## Introduction +The Helm Charts found under the examples directory are getting started examples which you can use to deploy Loki using the Simple Scalable architecture quickly. Currently, the examples include: +- [Deploying Grafana Enterprise Logs (Loki in Enterprise mode)](https://github.com/grafana/loki/tree/main/production/helm/loki/docs/examples/enterprise) +- [Deploying Loki OSS](https://github.com/grafana/loki/tree/main/production/helm/loki/docs/examples/oss) diff --git a/utils/assets/charts/loki/docs/examples/enterprise/README.md b/utils/assets/charts/loki/docs/examples/enterprise/README.md new file mode 100644 index 0000000..82c0d28 --- /dev/null +++ b/utils/assets/charts/loki/docs/examples/enterprise/README.md @@ -0,0 +1,28 @@ +## Introduction +This example gives you an example or getting started overrides value file for deploying Loki (Enterprise Licensed) using the Simple Scalable architecture in GKE and using GCS. + +## Installation of Helm Chart +These instructions assume you already have access to a Kubernetes cluster, GCS Bucket and GCP Service Account which has read/write permissions to that GCS Bucket. + +### Populate Secret Values +Populate the [enterprise-secrets.yaml](./enterprise-secrets.yaml) so that: +- The `gcp_service_account.json` secret has the contents of your GCP Service Account JSON key. +- The `license.jwt` secret has the contents of your Grafana Enterprise Logs license key given to your by Grafana Labs. + +Deploy the secrets file to your k8s cluster with the command: + +`kubectl apply -f enterprise-secrets.yaml` + +### Configure the Helm Chart +Open [overrides-enterprise-gcs.yaml](./overrides-enterprise-gcs.yaml) and replace `{YOUR_GCS_BUCKET}` with the name of your GCS bucket. If there are other things you'd like to configure, view the core [Values.yaml file](https://github.com/grafana/loki/blob/main/production/helm/loki/values.yaml) and override anything else you need to within the overrides-enterprise-gcs.yaml file. + +### Install the Helm chart + +`helm upgrade --install --values {PATH_TO_YOUR_OVERRIDES_YAML_FILE} {YOUR_RELEASE_NAME} grafana/loki-simple-scalable --namespace {KUBERNETES_NAMESPACE}` + +### Get the Token for Grafana to connect +`export POD_NAME=$(kubectl get pods --namespace {KUBERNETES_NAMESPACE} -l "job-name=enterprise-logs-tokengen" -o jsonpath="{.items[0].metadata.name}")` + +`kubectl --namespace {KUBERNETES_NAMESPACE} logs $POD_NAME loki | grep Token` + +Take note of this token, you will need it when connecting Grafana Enterprise Logs to Grafana. diff --git a/utils/assets/charts/loki/docs/examples/enterprise/enterprise-secrets.yaml b/utils/assets/charts/loki/docs/examples/enterprise/enterprise-secrets.yaml new file mode 100644 index 0000000..698e94b --- /dev/null +++ b/utils/assets/charts/loki/docs/examples/enterprise/enterprise-secrets.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: gel-secrets +type: Opaque +stringData: + gcp_service_account.json: | + { + GCP_SERVICE_ACCOUNT_JSON_HERE + } + + license.jwt: LICENSE_HERE diff --git a/utils/assets/charts/loki/docs/examples/enterprise/overrides-enterprise-gcs.yaml b/utils/assets/charts/loki/docs/examples/enterprise/overrides-enterprise-gcs.yaml new file mode 100644 index 0000000..01210d3 --- /dev/null +++ b/utils/assets/charts/loki/docs/examples/enterprise/overrides-enterprise-gcs.yaml @@ -0,0 +1,83 @@ +enterprise: + enabled: true + useExternalLicense: true + externalLicenseName: gel-secrets + tokengen: + env: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/gel_secrets/gcp_service_account.json" + extraVolumeMounts: + - name: gel-secrets + mountPath: "/etc/gel_secrets" + extraVolumes: + - name: gel-secrets + secret: + secretName: gel-secrets + items: + - key: license.jwt + path: license.jwt + - key: gcp_service_account.json + path: gcp_service_account.json +loki: + auth_enabled: true + + storage: + type: gcs + bucketNames: + chunks: {YOUR_GCS_BUCKET} + ruler: {YOUR_GCS_BUCKET} + admin: {YOUR_GCS_BUCKET} + +minio: + enabled: false + +write: + extraEnv: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/gel_secrets/gcp_service_account.json" + extraVolumeMounts: + - name: gel-secrets + mountPath: "/etc/gel_secrets" + extraVolumes: + - name: gel-secrets + secret: + secretName: gel-secrets + items: + - key: license.jwt + path: license.jwt + - key: gcp_service_account.json + path: gcp_service_account.json + +read: + extraEnv: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/gel_secrets/gcp_service_account.json" + extraVolumeMounts: + - name: gel-secrets + mountPath: "/etc/gel_secrets" + extraVolumes: + - name: gel-secrets + secret: + secretName: gel-secrets + items: + - key: license.jwt + path: license.jwt + - key: gcp_service_account.json + path: gcp_service_account.json + +gateway: + extraEnv: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/gel_secrets/gcp_service_account.json" + extraVolumeMounts: + - name: gel-secrets + mountPath: "/etc/gel_secrets" + extraVolumes: + - name: gel-secrets + secret: + secretName: gel-secrets + items: + - key: license.jwt + path: license.jwt + - key: gcp_service_account.json + path: gcp_service_account.json diff --git a/utils/assets/charts/loki/docs/examples/oss/README.md b/utils/assets/charts/loki/docs/examples/oss/README.md new file mode 100644 index 0000000..9a0a410 --- /dev/null +++ b/utils/assets/charts/loki/docs/examples/oss/README.md @@ -0,0 +1,20 @@ +## Introduction +This example gives you an example or getting started overrides value file for deploying Loki (OSS) using the Simple Scalable architecture in GKE and using GCS + +## Installation of Helm Chart +These instructions assume you have already have access to a Kubernetes cluster, GCS Bucket and GCP Service Account which has read/write permissions to that GCS Bucket. + +### Populate Secret Values +Populate the examples/enterprise/enterprise-secrets.yaml so that: +- The gcp_service_account.json secret has the contents of your GCP Service Account JSON key + +Deploy the secrets file to your k8s cluster. + +`kubectl apply -f loki-secrets.yaml` + +### Configure the Helm Chart +Open examples/enterprise/overides-oss-gcs.yaml and replace `{YOUR_GCS_BUCKET}` with the name of your GCS bucket. If there are other things you'd like to configure, view the core [Values.yaml file](https://github.com/grafana/loki/blob/main/production/helm/loki/values.yaml) and override anything else you need to within the overrides-enterprise-gcs.yaml file. + +### Install the Helm chart + +`helm upgrade --install --values {PATH_TO_YOUR_OVERRIDES_YAML_FILE} {YOUR_RELEASE_NAME} grafana/loki-simple-scalable --namespace {KUBERNETES_NAMESPACE}` diff --git a/utils/assets/charts/loki/docs/examples/oss/oss-secrets.yaml b/utils/assets/charts/loki/docs/examples/oss/oss-secrets.yaml new file mode 100644 index 0000000..4fbf5e7 --- /dev/null +++ b/utils/assets/charts/loki/docs/examples/oss/oss-secrets.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: loki-secrets +type: Opaque +stringData: + gcp_service_account.json: | + { + GCP_SERVICE_ACCOUNT_JSON_HERE + } \ No newline at end of file diff --git a/utils/assets/charts/loki/docs/examples/oss/overrides-oss-gcs.yaml b/utils/assets/charts/loki/docs/examples/oss/overrides-oss-gcs.yaml new file mode 100644 index 0000000..3e94f84 --- /dev/null +++ b/utils/assets/charts/loki/docs/examples/oss/overrides-oss-gcs.yaml @@ -0,0 +1,77 @@ +enterprise: + enabled: false + adminApi: + enabled: false + useExternalLicense: false + + config: | + admin_client: + storage: + gcs: + bucket_name: {YOUR_GCS_BUCKET} + auth: + type: trust + auth_enabled: false + cluster_name: loki-logs + +loki: + auth_enabled: false + + commonConfig: + path_prefix: /var/loki + replication_factor: 3 + + storage: + type: gcs + bucketNames: + chunks: {YOUR_GCS_BUCKET} + ruler: {YOUR_GCS_BUCKET} + admin: {YOUR_GCS_BUCKET} + +minio: + enabled: false + +write: + extraEnv: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/loki_secrets/gcp_service_account.json" + extraVolumeMounts: + - name: loki-secrets + mountPath: "/etc/loki_secrets" + extraVolumes: + - name: loki-secrets + secret: + secretName: loki-secrets + items: + - key: gcp_service_account.json + path: gcp_service_account.json + +read: + extraEnv: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/loki_secrets/gcp_service_account.json" + extraVolumeMounts: + - name: loki-secrets + mountPath: "/etc/loki_secrets" + extraVolumes: + - name: loki-secrets + secret: + secretName: loki-secrets + items: + - key: gcp_service_account.json + path: gcp_service_account.json + +gateway: + extraEnv: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/etc/loki_secrets/gcp_service_account.json" + extraVolumeMounts: + - name: loki-secrets + mountPath: "/etc/loki_secrets" + extraVolumes: + - name: loki-secrets + secret: + secretName: loki-secrets + items: + - key: gcp_service_account.json + path: gcp_service_account.json diff --git a/utils/assets/charts/loki/reference.md.gotmpl b/utils/assets/charts/loki/reference.md.gotmpl new file mode 100644 index 0000000..0efc492 --- /dev/null +++ b/utils/assets/charts/loki/reference.md.gotmpl @@ -0,0 +1,49 @@ +--- +title: Helm Chart Values +menuTitle: Helm chart values +description: Reference for Helm Chart values. +aliases: + - ../../../installation/helm/reference/ +weight: 500 +keywords: [] +--- + + + +# Helm Chart Values + + + + +This is the generated reference for the Loki Helm Chart values. + +> **Note:** This reference is for the Loki Helm chart version 3.0 or greater. +> If you are using the `grafana/loki-stack` Helm chart from the community repo, +> please refer to the `values.yaml` of the respective Github repository +> [grafana/helm-charts](https://github.com/grafana/helm-charts/tree/main/charts/loki-stack). + + +{{ define "chart.valuesTableHtml" }} +{{ `{{< responsive-table >}}` }} + + + + + + + + + {{- range .Values }} + + + + + + + {{- end }} + +
KeyTypeDescriptionDefault
{{ .Key }}{{ .Type }}{{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }}{{ template "chart.valueDefaultColumnRender" . }}
+{{ `{{< /responsive-table >}}` }} +{{ end }} + +{{ template "chart.valuesTableHtml" . }} diff --git a/utils/assets/charts/loki/scenarios/README.md b/utils/assets/charts/loki/scenarios/README.md new file mode 100644 index 0000000..1ec8692 --- /dev/null +++ b/utils/assets/charts/loki/scenarios/README.md @@ -0,0 +1,19 @@ +These scenarios are used by Github Workflow: [Publish Rendered Helm Chart Diff](../../../../.github/workflows/helm-loki-ci.yml). + +Each scenario is used as the values file for the Loki Helm chart to render Kubernetes manifests in `base` and `PR's` branch to compare the content and report the diff on Pull Request as a comment([example](https://github.com/grafana/loki/pull/14127#issuecomment-2348360828)). It gives the ability to the reviewer to understand how the changes in the chart modify resulting manifests. + +![img.png](images/img.png) + +The workflow reports three types of changes for each scenario: + +1. Added files - the manifests that are added in the current PR and that did not exist in `base` branch. + +![added.png](images/added.png) + + +2. Modified files - the manifests that exist in both branches but the changes in PRs branch modify them. +![modified.png](images/modified.png) + +3. Removed files - the manifests that exist in `base` branch but do not exist in PRs branch. + +![removed.png](images/removed.png) \ No newline at end of file diff --git a/utils/assets/charts/loki/scenarios/default-single-binary-values.yaml b/utils/assets/charts/loki/scenarios/default-single-binary-values.yaml new file mode 100644 index 0000000..78a1f11 --- /dev/null +++ b/utils/assets/charts/loki/scenarios/default-single-binary-values.yaml @@ -0,0 +1,71 @@ +--- +loki: + schemaConfig: + configs: + - from: 2024-04-01 + store: tsdb + object_store: s3 + schema: v13 + index: + prefix: loki_index_ + period: 24h + ingester: + chunk_encoding: snappy + tracing: + enabled: true + querier: + # Default is 4, if you have enough memory and CPU you can increase, reduce if OOMing + max_concurrent: 4 + +#gateway: +# ingress: +# enabled: true +# hosts: +# - host: FIXME +# paths: +# - path: / +# pathType: Prefix + +deploymentMode: Distributed + +ingester: + replicas: 3 +querier: + replicas: 3 + maxUnavailable: 2 +queryFrontend: + replicas: 2 + maxUnavailable: 1 +queryScheduler: + replicas: 2 +distributor: + replicas: 3 + maxUnavailable: 2 +compactor: + replicas: 1 +indexGateway: + replicas: 2 + maxUnavailable: 1 + +# optional experimental components +bloomPlanner: + replicas: 0 +bloomBuilder: + replicas: 0 +bloomGateway: + replicas: 0 + +# Enable minio for storage +minio: + enabled: true + +# Zero out replica counts of other deployment modes +backend: + replicas: 0 +read: + replicas: 0 +write: + replicas: 0 + +singleBinary: + replicas: 0 diff --git a/utils/assets/charts/loki/scenarios/default-values.yaml b/utils/assets/charts/loki/scenarios/default-values.yaml new file mode 100644 index 0000000..a79baee --- /dev/null +++ b/utils/assets/charts/loki/scenarios/default-values.yaml @@ -0,0 +1,16 @@ +--- +loki: + commonConfig: + replication_factor: 1 + useTestSchema: true + storage: + bucketNames: + chunks: chunks + ruler: ruler + admin: admin +read: + replicas: 1 +write: + replicas: 1 +backend: + replicas: 1 diff --git a/utils/assets/charts/loki/scenarios/images/added.png b/utils/assets/charts/loki/scenarios/images/added.png new file mode 100644 index 0000000..ced9f95 Binary files /dev/null and b/utils/assets/charts/loki/scenarios/images/added.png differ diff --git a/utils/assets/charts/loki/scenarios/images/img.png b/utils/assets/charts/loki/scenarios/images/img.png new file mode 100644 index 0000000..81ba701 Binary files /dev/null and b/utils/assets/charts/loki/scenarios/images/img.png differ diff --git a/utils/assets/charts/loki/scenarios/images/modified.png b/utils/assets/charts/loki/scenarios/images/modified.png new file mode 100644 index 0000000..39a25ba Binary files /dev/null and b/utils/assets/charts/loki/scenarios/images/modified.png differ diff --git a/utils/assets/charts/loki/scenarios/images/removed.png b/utils/assets/charts/loki/scenarios/images/removed.png new file mode 100644 index 0000000..219d64c Binary files /dev/null and b/utils/assets/charts/loki/scenarios/images/removed.png differ diff --git a/utils/assets/charts/loki/scenarios/ingress-values.yaml b/utils/assets/charts/loki/scenarios/ingress-values.yaml new file mode 100644 index 0000000..ff5ff1e --- /dev/null +++ b/utils/assets/charts/loki/scenarios/ingress-values.yaml @@ -0,0 +1,30 @@ +--- +gateway: + ingress: + enabled: true + annotations: {} + hosts: + - host: gateway.loki.example.com + paths: + - path: / + pathType: Prefix +loki: + commonConfig: + replication_factor: 1 + useTestSchema: true + storage: + bucketNames: + chunks: chunks + ruler: ruler + admin: admin +read: + replicas: 1 +write: + replicas: 1 +backend: + replicas: 1 +monitoring: + lokiCanary: + enabled: false +test: + enabled: false diff --git a/utils/assets/charts/loki/scenarios/legacy-monitoring-values.yaml b/utils/assets/charts/loki/scenarios/legacy-monitoring-values.yaml new file mode 100644 index 0000000..ad520e5 --- /dev/null +++ b/utils/assets/charts/loki/scenarios/legacy-monitoring-values.yaml @@ -0,0 +1,27 @@ +--- +loki: + commonConfig: + replication_factor: 1 + useTestSchema: true + storage: + bucketNames: + chunks: chunks + ruler: ruler + admin: admin +read: + replicas: 1 +write: + replicas: 1 +backend: + replicas: 1 +monitoring: + enabled: true + selfMonitoring: + enabled: true + grafanaAgent: + installOperator: true + serviceMonitor: + labels: + release: "prometheus" +test: + prometheusAddress: "http://prometheus-kube-prometheus-prometheus.prometheus.svc.cluster.local.:9090" diff --git a/utils/assets/charts/loki/scenarios/simple-scalable-aws-kube-irsa-values.yaml b/utils/assets/charts/loki/scenarios/simple-scalable-aws-kube-irsa-values.yaml new file mode 100644 index 0000000..28c6c3b --- /dev/null +++ b/utils/assets/charts/loki/scenarios/simple-scalable-aws-kube-irsa-values.yaml @@ -0,0 +1,67 @@ +loki: + # -- Storage config. Providing this will automatically populate all necessary storage configs in the templated config. + storage: + # Loki requires a bucket for chunks and the ruler. GEL requires a third bucket for the admin API. + # Please provide these values if you are using object storage. + bucketNames: + chunks: aws-s3-chunks-bucket + ruler: aws-s3-ruler-bucket + admin: aws-s3-admin-bucket + type: s3 + s3: + region: eu-central-1 + # -- Check https://grafana.com/docs/loki/latest/configuration/#schema_config for more info on how to configure schemas + schemaConfig: + configs: + - from: "2023-09-19" + index: + period: 1d + prefix: tsdb_index_ + object_store: s3 + schema: v13 + store: tsdb +###################################################################################################################### +# +# Enterprise Loki Configs +# +###################################################################################################################### + +# -- Configuration for running Enterprise Loki +enterprise: + # Enable enterprise features, license must be provided + enabled: true + # -- Grafana Enterprise Logs license + license: + contents: "content of licence" + tokengen: + annotations: { + eks.amazonaws.com/role-arn: arn:aws:iam::2222222:role/test-role + } + # -- Configuration for `provisioner` target + provisioner: + # -- Additional annotations for the `provisioner` Job + annotations: { + eks.amazonaws.com/role-arn: arn:aws:iam::2222222:role/test-role + } +###################################################################################################################### +# +# Service Accounts and Kubernetes RBAC +# +###################################################################################################################### +serviceAccount: + # -- Annotations for the service account + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::2222222:role/test-role + +# Configuration for the write pod(s) +write: + persistence: + storageClass: gp2 +# -- Configuration for the read pod(s) +read: + persistence: + storageClass: gp2 +# -- Configuration for the backend pod(s) +backend: + persistence: + storageClass: gp2 diff --git a/utils/assets/charts/loki/simple-scalable-values.yaml b/utils/assets/charts/loki/simple-scalable-values.yaml new file mode 100644 index 0000000..78132b6 --- /dev/null +++ b/utils/assets/charts/loki/simple-scalable-values.yaml @@ -0,0 +1,63 @@ +--- +loki: + schemaConfig: + configs: + - from: 2024-04-01 + store: tsdb + object_store: s3 + schema: v13 + index: + prefix: loki_index_ + period: 24h + ingester: + chunk_encoding: snappy + tracing: + enabled: true + querier: + # Default is 4, if you have enough memory and CPU you can increase, reduce if OOMing + max_concurrent: 4 + +#gateway: +# ingress: +# enabled: true +# hosts: +# - host: FIXME +# paths: +# - path: / +# pathType: Prefix + +deploymentMode: SimpleScalable + +backend: + replicas: 3 +read: + replicas: 3 +write: + replicas: 3 + +# Enable minio for storage +minio: + enabled: true + +# Zero out replica counts of other deployment modes +singleBinary: + replicas: 0 + +ingester: + replicas: 0 +querier: + replicas: 0 +queryFrontend: + replicas: 0 +queryScheduler: + replicas: 0 +distributor: + replicas: 0 +compactor: + replicas: 0 +indexGateway: + replicas: 0 +bloomCompactor: + replicas: 0 +bloomGateway: + replicas: 0 diff --git a/utils/assets/charts/loki/single-binary-values.yaml b/utils/assets/charts/loki/single-binary-values.yaml new file mode 100644 index 0000000..584f0fb --- /dev/null +++ b/utils/assets/charts/loki/single-binary-values.yaml @@ -0,0 +1,79 @@ +--- +loki: + commonConfig: + replication_factor: 1 + schemaConfig: + configs: + - from: 2024-04-01 + store: tsdb + object_store: s3 + schema: v13 + index: + prefix: loki_index_ + period: 24h + ingester: + chunk_encoding: snappy + tracing: + enabled: true + querier: + # Default is 4, if you have enough memory and CPU you can increase, reduce if OOMing + max_concurrent: 2 + +#gateway: +# ingress: +# enabled: true +# hosts: +# - host: FIXME +# paths: +# - path: / +# pathType: Prefix + +deploymentMode: SingleBinary +singleBinary: + replicas: 1 + resources: + limits: + cpu: 3 + memory: 4Gi + requests: + cpu: 2 + memory: 2Gi + extraEnv: + # Keep a little bit lower than memory limits + - name: GOMEMLIMIT + value: 3750MiB + +chunksCache: + # default is 500MB, with limited memory keep this smaller + writebackSizeLimit: 10MB + +# Enable minio for storage +minio: + enabled: true + +# Zero out replica counts of other deployment modes +backend: + replicas: 0 +read: + replicas: 0 +write: + replicas: 0 + +ingester: + replicas: 0 +querier: + replicas: 0 +queryFrontend: + replicas: 0 +queryScheduler: + replicas: 0 +distributor: + replicas: 0 +compactor: + replicas: 0 +indexGateway: + replicas: 0 +bloomCompactor: + replicas: 0 +bloomGateway: + replicas: 0 diff --git a/utils/assets/charts/loki/src/.yamllint.yaml b/utils/assets/charts/loki/src/.yamllint.yaml new file mode 100644 index 0000000..19e5933 --- /dev/null +++ b/utils/assets/charts/loki/src/.yamllint.yaml @@ -0,0 +1,4 @@ +--- +rules: + quoted-strings: + required: true diff --git a/utils/assets/charts/loki/src/alerts.yaml.tpl b/utils/assets/charts/loki/src/alerts.yaml.tpl new file mode 100644 index 0000000..0aa37b7 --- /dev/null +++ b/utils/assets/charts/loki/src/alerts.yaml.tpl @@ -0,0 +1,78 @@ +--- +groups: + - name: "loki_alerts" + rules: +{{- if not (.Values.monitoring.rules.disabled.LokiRequestErrors | default false) }} + - alert: "LokiRequestErrors" + annotations: + message: | + {{`{{`}} $labels.job {{`}}`}} {{`{{`}} $labels.route {{`}}`}} is experiencing {{`{{`}} printf "%.2f" $value {{`}}`}}% errors. + expr: | + 100 * sum(rate(loki_request_duration_seconds_count{status_code=~"5.."}[2m])) by (namespace, job, route) + / + sum(rate(loki_request_duration_seconds_count[2m])) by (namespace, job, route) + > 10 + for: "15m" + labels: + severity: "critical" +{{- if .Values.monitoring.rules.additionalRuleLabels }} +{{ toYaml .Values.monitoring.rules.additionalRuleLabels | indent 10 }} +{{- end }} +{{- end }} +{{- if not (.Values.monitoring.rules.disabled.LokiRequestPanics | default false) }} + - alert: "LokiRequestPanics" + annotations: + message: | + {{`{{`}} $labels.job {{`}}`}} is experiencing {{`{{`}} printf "%.2f" $value {{`}}`}}% increase of panics. + expr: | + sum(increase(loki_panic_total[10m])) by (namespace, job) > 0 + labels: + severity: "critical" +{{- if .Values.monitoring.rules.additionalRuleLabels }} +{{ toYaml .Values.monitoring.rules.additionalRuleLabels | indent 10 }} +{{- end }} +{{- end }} +{{- if not (.Values.monitoring.rules.disabled.LokiRequestLatency | default false) }} + - alert: "LokiRequestLatency" + annotations: + message: | + {{`{{`}} $labels.job {{`}}`}} {{`{{`}} $labels.route {{`}}`}} is experiencing {{`{{`}} printf "%.2f" $value {{`}}`}}s 99th percentile latency. + expr: | + namespace_job_route:loki_request_duration_seconds:99quantile{route!~"(?i).*tail.*"} > 1 + for: "15m" + labels: + severity: "critical" +{{- if .Values.monitoring.rules.additionalRuleLabels }} +{{ toYaml .Values.monitoring.rules.additionalRuleLabels | indent 10 }} +{{- end }} +{{- end }} +{{- if not (.Values.monitoring.rules.disabled.LokiTooManyCompactorsRunning | default false) }} + - alert: "LokiTooManyCompactorsRunning" + annotations: + message: | + {{`{{`}} $labels.cluster {{`}}`}} {{`{{`}} $labels.namespace {{`}}`}} has had {{`{{`}} printf "%.0f" $value {{`}}`}} compactors running for more than 5m. Only one compactor should run at a time. + expr: | + sum(loki_boltdb_shipper_compactor_running) by (cluster, namespace) > 1 + for: "5m" + labels: + severity: "warning" +{{- if .Values.monitoring.rules.additionalRuleLabels }} +{{ toYaml .Values.monitoring.rules.additionalRuleLabels | indent 10 }} +{{- end }} +{{- end }} +{{- if not (.Values.monitoring.rules.disabled.LokiCanaryLatency | default false) }} + - name: "loki_canaries_alerts" + rules: + - alert: "LokiCanaryLatency" + annotations: + message: | + {{`{{`}} $labels.job {{`}}`}} is experiencing {{`{{`}} printf "%.2f" $value {{`}}`}}s 99th percentile latency. + expr: | + histogram_quantile(0.99, sum(rate(loki_canary_response_latency_seconds_bucket[5m])) by (le, namespace, job)) > 5 + for: "15m" + labels: + severity: "warning" +{{- if .Values.monitoring.rules.additionalRuleLabels }} +{{ toYaml .Values.monitoring.rules.additionalRuleLabels | indent 10 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/src/dashboards/loki-chunks.json b/utils/assets/charts/loki/src/dashboards/loki-chunks.json new file mode 100644 index 0000000..bec1997 --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-chunks.json @@ -0,0 +1,1336 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(loki_ingester_memory_chunks{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "series", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Series", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(loki_ingester_memory_chunks{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}) / sum(loki_ingester_memory_streams{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "chunks", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Chunks per series", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Active Series / Chunks", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) by (le)) * 1", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) by (le)) * 1", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(loki_ingester_chunk_utilization_sum{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) * 1 / sum(rate(loki_ingester_chunk_utilization_count{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Utilization", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_age_seconds_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_age_seconds_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(loki_ingester_chunk_age_seconds_sum{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) * 1e3 / sum(rate(loki_ingester_chunk_age_seconds_count{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Age", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Flush Stats", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_entries_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) by (le)) * 1", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_entries_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) by (le)) * 1", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(loki_ingester_chunk_entries_sum{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) * 1 / sum(rate(loki_ingester_chunk_entries_count{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Log Entries Per Chunk", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_chunk_store_index_entries_per_chunk_sum{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[5m])) / sum(rate(loki_chunk_store_index_entries_per_chunk_count{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Index Entries", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Index Entries Per Chunk", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Flush Stats", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "loki_ingester_flush_queue_length{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"} or cortex_ingester_flush_queue_length{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Queue Length", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + "1xx": "#EAB839", + "2xx": "#7EB26D", + "3xx": "#6ED0E0", + "4xx": "#EF843C", + "5xx": "#E24D42", + "error": "#E24D42", + "success": "#7EB26D" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status) (\n label_replace(label_replace(rate(loki_ingester_chunk_age_seconds_count{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval]),\n \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n \"status\", \"${1}\", \"status_code\", \"([a-z]+)\"))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{status}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Flush Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Flush Stats", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Chunks Flushed/Second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (reason) (rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) / ignoring(reason) group_left sum(rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{reason}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Chunk Flush Reason", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": 1, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Flush Stats", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateSpectral", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "$datasource", + "heatmap": { }, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 11, + "legend": { + "show": true + }, + "span": 12, + "targets": [ + { + "expr": "sum by (le) (rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval]))", + "format": "heatmap", + "intervalFactor": 2, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Chunk Utilization", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "percentunit", + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Utilization", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateSpectral", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "$datasource", + "heatmap": { }, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 12, + "legend": { + "show": true + }, + "span": 12, + "targets": [ + { + "expr": "sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[$__rate_interval])) by (le)", + "format": "heatmap", + "intervalFactor": 2, + "legendFormat": "{{le}}", + "refId": "A" + } + ], + "title": "Chunk Size Bytes", + "tooltip": { + "show": true, + "showHistogram": true + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Utilization", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "p99", + "legendLink": null, + "step": 10 + }, + { + "expr": "histogram_quantile(0.90, sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "p90", + "legendLink": null, + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[1m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "p50", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Chunk Size Quantiles", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Utilization", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(loki_ingester_chunk_bounds_hours_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[5m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "p50", + "legendLink": null, + "step": 10 + }, + { + "expr": "histogram_quantile(0.99, sum(rate(loki_ingester_chunk_bounds_hours_bucket{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[5m])) by (le))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "p99", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(rate(loki_ingester_chunk_bounds_hours_sum{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[5m])) / sum(rate(loki_ingester_chunk_bounds_hours_count{cluster=\"$cluster\", job=~\"$namespace/(loki|enterprise-logs)-write\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "avg", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Chunk Duration hours (end-start)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Duration", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Chunks", + "uid": "chunks", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-deletion.json b/utils/assets/charts/loki/src/dashboards/loki-deletion.json new file mode 100644 index 0000000..84bfee6 --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-deletion.json @@ -0,0 +1,632 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "100px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "none", + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(loki_compactor_pending_delete_requests_count{cluster=~\"$cluster\", namespace=~\"$namespace\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Number of Pending Requests", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "dtdurations", + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(loki_compactor_oldest_pending_delete_request_age_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Oldest Pending Request Age", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Headlines", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(increase(loki_compactor_delete_requests_received_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[1d]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "received", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Delete Requests Received / Day", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(increase(loki_compactor_delete_requests_processed_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[1d]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "processed", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Delete Requests Processed / Day", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Churn", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(increase(loki_compactor_load_pending_requests_attempts_total{status=\"fail\", cluster=~\"$cluster\", namespace=~\"$namespace\"}[1h]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "failures", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Failures in Loading Delete Requests / Hour", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Failures", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_compactor_deleted_lines{cluster=~\"$cluster\",job=~\"$namespace/(loki|enterprise-logs)-read\"}[$__rate_interval])) by (user)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{user}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Lines Deleted / Sec", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Deleted lines", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Deletion", + "uid": "deletion", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-logs.json b/utils/assets/charts/loki/src/dashboards/loki-logs.json new file mode 100644 index 0000000..0f113cf --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-logs.json @@ -0,0 +1,1073 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": 8, + "iteration": 1583185057230, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(go_goroutines{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"})", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "goroutines", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 0 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(go_gc_duration_seconds{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"}) by (quantile)", + "legendFormat": "{{quantile}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "gc duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 0 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_cpu_usage_seconds_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"}[5m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "cpu", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 0 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"})", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "working set", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 0 + }, + "hiddenSeries": false, + "id": 38, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"}[5m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "tx", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 0 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\"}[5m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "rx", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "decbytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 0 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "increase(kube_pod_container_status_last_terminated_reason{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"}[30m]) > 0", + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "restarts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 3, + "x": 21, + "y": 0 + }, + "hiddenSeries": false, + "id": 42, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(promtail_custom_bad_words_total{cluster=\"$cluster\", exported_namespace=\"$namespace\", exported_pod=~\"$deployment.*\", exported_pod=~\"$pod\", container=~\"$container\"}[5m])) by (level)", + "legendFormat": "{{level}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "bad words", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$logs", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 4 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "warn", + "color": "#FF780A" + }, + { + "alias": "error", + "color": "#E02F44" + }, + { + "alias": "info", + "color": "#56A64B" + }, + { + "alias": "debug", + "color": "#3274D9" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate({cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\" } |logfmt| level=~\"$level\" |= \"$filter\" [5m])) by (level)", + "intervalFactor": 3, + "legendFormat": "{{level}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Log Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "timeseries", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "$logs", + "gridPos": { + "h": 19, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 29, + "maxDataPoints": "", + "options": { + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "targets": [ + { + "expr": "{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\", pod=~\"$pod\", container=~\"$container\"} | logfmt | level=~\"$level\" |= \"$filter\"", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Logs", + "type": "logs" + } + ], + "refresh": "10s", + "rows": [ ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "hide": 0, + "label": null, + "name": "logs", + "options": [ ], + "query": "loki", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "deployment", + "options": [ ], + "query": "label_values(kube_deployment_created{cluster=\"$cluster\", namespace=\"$namespace\"}, deployment)", + "refresh": 0, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "options": [ ], + "query": "label_values(kube_pod_container_info{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$deployment.*\"}, pod)", + "refresh": 0, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "container", + "options": [ ], + "query": "label_values(kube_pod_container_info{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$pod\", pod=~\"$deployment.*\"}, container)", + "refresh": 0, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": true, + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "label": "", + "multi": true, + "name": "level", + "options": [ + { + "selected": false, + "text": "debug", + "value": "debug" + }, + { + "selected": false, + "text": "info", + "value": "info" + }, + { + "selected": false, + "text": "warn", + "value": "warn" + }, + { + "selected": false, + "text": "error", + "value": "error" + } + ], + "query": "debug,info,warn,error", + "refresh": 0, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "label": "LogQL Filter", + "name": "filter", + "query": "", + "type": "textbox" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Logs", + "uid": "logs", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-mixin-recording-rules.json b/utils/assets/charts/loki/src/dashboards/loki-mixin-recording-rules.json new file mode 100644 index 0000000..fe49ec7 --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-mixin-recording-rules.json @@ -0,0 +1,657 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [ ], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": "${datasource}", + "enable": false, + "expr": "sum by (tenant) (changes(loki_ruler_wal_prometheus_tsdb_wal_truncations_total{tenant=~\"${tenant}\"}[$__rate_interval]))", + "iconColor": "red", + "name": "WAL Truncations", + "target": { + "queryType": "Azure Monitor", + "refId": "Anno" + }, + "titleFormat": "{{tenant}}" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": null, + "graphTooltip": 0, + "iteration": 1635347545534, + "links": [ ], + "liveNow": false, + "panels": [ + { + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ ], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [ ] + }, + "gridPos": { + "h": 10, + "w": 2, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.0-38205pre", + "targets": [ + { + "datasource": "${datasource}", + "exemplar": false, + "expr": "sum(loki_ruler_wal_appender_ready) by (pod, tenant) == 0", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Appenders Not Ready", + "type": "stat" + }, + { + "datasource": "${datasource}", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ ] + }, + "gridPos": { + "h": 10, + "w": 11, + "x": 2, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "datasource": "${datasource}", + "exemplar": true, + "expr": "sum(rate(loki_ruler_wal_samples_appended_total{tenant=~\"${tenant}\"}[$__rate_interval])) by (tenant) > 0", + "interval": "", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "title": "Samples Appended to WAL per Second", + "type": "timeseries" + }, + { + "datasource": "${datasource}", + "description": "Series are unique combinations of labels", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ ] + }, + "gridPos": { + "h": 10, + "w": 11, + "x": 13, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "datasource": "${datasource}", + "exemplar": true, + "expr": "sum(rate(loki_ruler_wal_storage_created_series_total{tenant=~\"${tenant}\"}[$__rate_interval])) by (tenant) > 0", + "interval": "", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "title": "Series Created per Second", + "type": "timeseries" + }, + { + "datasource": "${datasource}", + "description": "Difference between highest timestamp appended to WAL and highest timestamp successfully written to remote storage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "datasource": "${datasource}", + "exemplar": true, + "expr": "loki_ruler_wal_prometheus_remote_storage_highest_timestamp_in_seconds{tenant=~\"${tenant}\"}\n- on (tenant)\n (\n loki_ruler_wal_prometheus_remote_storage_queue_highest_sent_timestamp_seconds{tenant=~\"${tenant}\"}\n or vector(0)\n )", + "interval": "", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "title": "Write Behind", + "type": "timeseries" + }, + { + "datasource": "${datasource}", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "datasource": "${datasource}", + "exemplar": true, + "expr": "sum(rate(loki_ruler_wal_prometheus_remote_storage_samples_total{tenant=~\"${tenant}\"}[$__rate_interval])) by (tenant) > 0", + "interval": "", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "title": "Samples Sent per Second", + "type": "timeseries" + }, + { + "datasource": "${datasource}", + "description": "\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "datasource": "${datasource}", + "exemplar": true, + "expr": "sum by (tenant) (loki_ruler_wal_disk_size{tenant=~\"${tenant}\"})", + "interval": "", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "title": "WAL Disk Size", + "type": "timeseries" + }, + { + "datasource": "${datasource}", + "description": "Some number of pending samples is expected, but if remote-write is failing this value will remain high", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [ ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 9, + "options": { + "legend": { + "calcs": [ ], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "datasource": "${datasource}", + "exemplar": true, + "expr": "max(loki_ruler_wal_prometheus_remote_storage_samples_pending{tenant=~\"${tenant}\"}) by (tenant,pod) > 0", + "interval": "", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "title": "Pending Samples", + "type": "timeseries" + } + ], + "schemaVersion": 31, + "style": "dark", + "tags": [ ], + "templating": { + "list": [ + { + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Datasource", + "multi": false, + "name": "datasource", + "options": [ ], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "datasource": "${datasource}", + "definition": "label_values(loki_ruler_wal_samples_appended_total, tenant)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Tenant", + "multi": true, + "name": "tenant", + "options": [ ], + "query": { + "query": "label_values(loki_ruler_wal_samples_appended_total, tenant)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { }, + "timezone": "", + "title": "Recording Rules", + "uid": "2xKA_ZK7k", + "version": 9, + "weekStart": "" + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-operational.json b/utils/assets/charts/loki/src/dashboards/loki-operational.json new file mode 100644 index 0000000..b69db23 --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-operational.json @@ -0,0 +1,6173 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": 68, + "iteration": 1588704280892, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "panels": [ + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 17, + "panels": [ ], + "targets": [ ], + "title": "Main", + "type": "row" + }, + { + "aliasColors": { + "5xx": "red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 4, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status) (\nlabel_replace(\n label_replace(\n rate(loki_request_duration_seconds_count{cluster=\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"api_prom_query|api_prom_label|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\"}[5m]),\n \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n\"status\", \"${1}\", \"status_code\", \"([a-z]+)\")\n)", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Queries/Second", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 10, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "5xx": "red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 4, + "x": 4, + "y": 1 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status) (\nlabel_replace(\n label_replace(\n rate(loki_request_duration_seconds_count{cluster=\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"api_prom_push|loki_api_v1_push\"}[5m]),\n \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n\"status\", \"${1}\", \"status_code\", \"([a-z]+)\"))", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Pushes/Second", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 10, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 4, + "x": 12, + "y": 1 + }, + "hiddenSeries": false, + "id": 2, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(loki_distributor_lines_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (tenant))", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Lines Per Tenant (top 10)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 4, + "x": 16, + "y": 1 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(loki_distributor_bytes_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (tenant)) / 1024 / 1024", + "legendFormat": "{{tenant}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "MBs Per Tenant (Top 10)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 4, + "x": 20, + "y": 1 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "increase(kube_pod_container_status_restarts_total{cluster=\"$cluster\", namespace=\"$namespace\"}[10m]) > 0", + "hide": false, + "interval": "", + "legendFormat": "{{container}}-{{pod}}", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Container Restarts", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"api_prom_push|loki_api_v1_push\", cluster=~\"$cluster\"})) * 1e3", + "legendFormat": ".99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.75, sum by (le) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"api_prom_push|loki_api_v1_push\", cluster=~\"$cluster\"})) * 1e3", + "legendFormat": ".9", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum by (le) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"api_prom_push|loki_api_v1_push\", cluster=~\"$cluster\"})) * 1e3", + "legendFormat": ".5", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Push Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 6 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le) (job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", cluster=~\"$cluster\"})) * 1e3", + "legendFormat": ".99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum by (le) (job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", cluster=~\"$cluster\"})) * 1e3", + "legendFormat": ".9", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum by (le) (job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", cluster=~\"$cluster\"})) * 1e3", + "legendFormat": ".5", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Distributor Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 6 + }, + "hiddenSeries": false, + "id": 71, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\", status_code!~\"5[0-9]{2}\"}[5m])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\"}[5m])) by (route)", + "interval": "", + "legendFormat": "{{route}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Distributor Success Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "decimals": null, + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 11 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=\"/logproto.Pusher/Push\", cluster=~\"$cluster\"})) * 1e3", + "legendFormat": ".99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum by (le) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=\"/logproto.Pusher/Push\", cluster=~\"$cluster\"})) * 1e3", + "hide": false, + "legendFormat": ".9", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum by (le) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=\"/logproto.Pusher/Push\", cluster=~\"$cluster\"})) * 1e3", + "hide": false, + "legendFormat": ".5", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Ingester Latency Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 11 + }, + "hiddenSeries": false, + "id": 72, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\", status_code!~\"5[0-9]{2}\", route=\"/logproto.Pusher/Push\"}[5m])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\", route=\"/logproto.Pusher/Push\"}[5m])) by (route)", + "interval": "", + "legendFormat": "{{route}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Ingester Success Rate Write", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "decimals": null, + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 16 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"}))", + "legendFormat": "{{route}}-.99", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"}))", + "legendFormat": "{{route}}-.9", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"}))", + "legendFormat": "{{route}}-.5", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Query Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 16 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"})) * 1e3", + "legendFormat": ".99-{{route}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"})) * 1e3", + "legendFormat": ".9-{{route}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"api_prom_query|api_prom_labels|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_label|loki_api_v1_label_name_values\", cluster=\"$cluster\"})) * 1e3", + "legendFormat": ".5-{{route}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Querier Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 16 + }, + "hiddenSeries": false, + "id": 73, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-read\", status_code!~\"5[0-9]{2}\"}[5m])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-read\"}[5m])) by (route)", + "interval": "", + "legendFormat": "{{route}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Querier Success Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "decimals": null, + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 21 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\", cluster=\"$cluster\"})) * 1e3", + "legendFormat": ".99-{{route}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.9, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\", cluster=\"$cluster\"})) * 1e3", + "legendFormat": ".9-{{route}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(0.5, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\", cluster=\"$cluster\"})) * 1e3", + "legendFormat": ".5-{{route}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Ingester Latency Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { } + }, + "overrides": [ ] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 21 + }, + "hiddenSeries": false, + "id": 74, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\", status_code!~\"5[0-9]{2}\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\"}[5m])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"/logproto.Querier/Query|/logproto.Querier/Label|/logproto.Querier/Series|/logproto.Querier/QuerySample|/logproto.Querier/GetChunkIDs\"}[5m])) by (route)", + "interval": "", + "legendFormat": "{{route}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Ingester Success Rate Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "decimals": null, + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 110, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "hiddenSeries": false, + "id": 112, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10,sum by (tenant, reason) (rate(loki_discarded_samples_total{cluster=\"$cluster\",namespace=\"$namespace\"}[1m])))", + "interval": "", + "legendFormat": "{{ tenant }} - {{ reason }}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Discarded Lines", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [ ], + "datasource": "$datasource", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 113, + "pageSize": null, + "panels": [ ], + "showHeader": true, + "sort": { + "col": 3, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "tenant", + "thresholds": [ ], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "reason", + "thresholds": [ ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "align": "right", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk(10, sum by (tenant, reason) (sum_over_time(increase(loki_discarded_samples_total{cluster=\"$cluster\",namespace=\"$namespace\"}[1m])[$__range:1m])))", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "{{ tenant }} - {{ reason }}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Discarded Lines Per Interval", + "transform": "table", + "type": "table-old" + } + ], + "targets": [ ], + "title": "Limits", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 23, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": true, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"(loki|enterprise-logs)-write.*\"}", + "intervalFactor": 3, + "legendFormat": "{{pod}}-{{container}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 28 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": true, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "go_memstats_heap_inuse_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"(loki|enterprise-logs)-write.*\"}", + "instant": false, + "intervalFactor": 3, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$logs", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 28 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "{}", + "color": "#C4162A" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate({cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\"} | logfmt | level=\"error\"[1m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Error Log Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "$logs", + "gridPos": { + "h": 18, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 29, + "options": { + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "panels": [ ], + "targets": [ + { + "expr": "{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\"} | logfmt | level=\"error\"", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Logs", + "type": "logs" + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 35 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\", status_code!~\"5[0-9]{2}\"}[5m])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-write\"}[5m])) by (route)", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{route}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Success Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 35 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_distributor_ingester_append_failures_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (ingester)", + "intervalFactor": 1, + "legendFormat": "{{ingester}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Append Failures By Ingester", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 42 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_distributor_bytes_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (pod)", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Bytes Received/Second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 42 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_distributor_lines_received_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (pod)", + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Lines Received/Second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Write Path", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 104, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "hiddenSeries": false, + "id": 106, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10,sum by (tenant) (loki_ingester_memory_streams{cluster=\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\"}))", + "interval": "", + "legendFormat": "{{ tenant }}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Active Streams", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 30 + }, + "hiddenSeries": false, + "id": 108, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum by (tenant) (rate(loki_ingester_streams_created_total{cluster=\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\"}[1m]) > 0))", + "interval": "", + "legendFormat": "{{ tenant }}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Streams Created/Sec", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Streams", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 94, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 102, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "De-Dupe Ratio", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_ingester_chunks_flushed_total{cluster=\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\"}[1m]))", + "interval": "", + "legendFormat": "Chunks", + "refId": "A" + }, + { + "expr": "sum(increase(loki_chunk_store_deduped_chunks_total{cluster=\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-write\"}[1m]))/sum(increase(loki_ingester_chunks_flushed_total{cluster=\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-write\"}[1m])) < 1", + "interval": "", + "legendFormat": "De-Dupe Ratio", + "refId": "B" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Chunks Flushed/Sec", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateSpectral", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "$datasource", + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "heatmap": { }, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 100, + "legend": { + "show": true + }, + "panels": [ ], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum(rate(loki_ingester_chunk_size_bytes_bucket{cluster=\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\"}[1m])) by (le)", + "format": "heatmap", + "instant": false, + "interval": "", + "legendFormat": "{{ le }}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Chunk Size Bytes", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "bytes", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 7, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 96, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(reason) (rate(loki_ingester_chunks_flushed_total{cluster=~\"$cluster\",job=~\"$namespace/ingester\", namespace=~\"$namespace\"}[$__rate_interval])) / ignoring(reason) group_left sum(rate(loki_ingester_chunks_flushed_total{cluster=~\"$cluster\",job=~\"$namespace/ingester\", namespace=~\"$namespace\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "{{ reason }}" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Chunk Flush Reason %", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateSpectral", + "exponent": 0.5, + "max": null, + "min": null, + "mode": "spectrum" + }, + "dataFormat": "tsbuckets", + "datasource": "$datasource", + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 39 + }, + "heatmap": { }, + "hideZeroBuckets": true, + "highlightCards": true, + "id": 98, + "legend": { + "show": true + }, + "panels": [ ], + "reverseYBuckets": false, + "targets": [ + { + "expr": "sum by (le) (rate(loki_ingester_chunk_utilization_bucket{cluster=\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-write\"}[1m]))", + "format": "heatmap", + "instant": false, + "interval": "", + "legendFormat": "{{ le }}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Chunk Utilization", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": null, + "yAxis": { + "decimals": 0, + "format": "percentunit", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + } + ], + "targets": [ ], + "title": "Chunks", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 64, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 32 + }, + "hiddenSeries": false, + "id": 68, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": true, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"(loki|enterprise-logs)-read.*\"}", + "intervalFactor": 3, + "legendFormat": "{{pod}}-{{container}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 69, + "legend": { + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": true, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "go_memstats_heap_inuse_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"(loki|enterprise-logs)-read.*\"}", + "instant": false, + "intervalFactor": 3, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$logs", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 3, + "w": 18, + "x": 12, + "y": 32 + }, + "hiddenSeries": false, + "id": 65, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "{}", + "color": "#F2495C" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate({cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-read\"} | logfmt | level=\"error\"[1m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Error Log Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "$logs", + "gridPos": { + "h": 18, + "w": 18, + "x": 12, + "y": 35 + }, + "id": 66, + "options": { + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "panels": [ ], + "targets": [ + { + "expr": "{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-read\"} | logfmt | level=\"error\"", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Logs", + "type": "logs" + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 46 + }, + "hiddenSeries": false, + "id": 70, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-read\", status_code!~\"5[0-9]{2}\"}[1m])) by (route)\n/\nsum(rate(loki_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", job=~\"($namespace)/(loki|enterprise-logs)-read\"}[1m])) by (route)", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{route}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Success Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Read Path", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 52, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 30 + }, + "hiddenSeries": false, + "id": 53, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_memcache_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (method, name, le, container))", + "intervalFactor": 1, + "legendFormat": "{{container}}: .99-{{method}}-{{name}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_memcache_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (method, name, le, container))", + "hide": false, + "legendFormat": "{{container}}: .9-{{method}}-{{name}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_memcache_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (method, name, le, container))", + "hide": false, + "legendFormat": "{{container}}: .5-{{method}}-{{name}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Latency By Method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 38 + }, + "hiddenSeries": false, + "id": 54, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_memcache_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (status_code, method, name, container)", + "intervalFactor": 1, + "legendFormat": "{{container}}: {{status_code}}-{{method}}-{{name}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Status By Method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Memcached", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 33 + }, + "id": 57, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 55, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".99-{{operation}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".9-{{operation}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".5-{{operation}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Latency By Operation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 58, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_consul_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, status_code, method)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}-{{operation}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Status By Operation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Consul", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 43, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 41, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".9", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[5m])) by (operation, le))", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[5m])) by (operation, le))", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "MutateRows Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 9 + }, + "hiddenSeries": false, + "id": 46, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[5m])) by (operation, le))", + "interval": "", + "intervalFactor": 1, + "legendFormat": "99%", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[5m])) by (operation, le))", + "interval": "", + "legendFormat": "90%", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[5m])) by (operation, le))", + "interval": "", + "legendFormat": "50%", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "ReadRows Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 9 + }, + "hiddenSeries": false, + "id": 44, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[5m])) by (operation, le))", + "interval": "", + "intervalFactor": 1, + "legendFormat": "99%", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[5m])) by (operation, le))", + "interval": "", + "legendFormat": "90%", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[5m])) by (operation, le))", + "interval": "", + "legendFormat": "50%", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "GetTable Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 9 + }, + "hiddenSeries": false, + "id": 45, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".9", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[5m])) by (operation, le))", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_bigtable_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[5m])) by (operation, le))", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "ListTables Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 16 + }, + "hiddenSeries": false, + "id": 47, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/MutateRows\"}[5m])) by (status_code)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "MutateRows Status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 16 + }, + "hiddenSeries": false, + "id": 50, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.v2.Bigtable/ReadRows\"}[5m])) by (status_code)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "ReadRows Status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 16 + }, + "hiddenSeries": false, + "id": 48, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/GetTable\"}[5m])) by (status_code)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "GetTable Status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 16 + }, + "hiddenSeries": false, + "id": 49, + "interval": "", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_bigtable_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\", operation=\"/google.bigtable.admin.v2.BigtableTableAdmin/ListTables\"}[5m])) by (status_code)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "ListTables Status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Big Table", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 60, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 33 + }, + "hiddenSeries": false, + "id": 61, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_gcs_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".99-{{operation}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_gcs_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".9-{{operation}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_gcs_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".5-{{operation}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Latency By Operation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 41 + }, + "hiddenSeries": false, + "id": 62, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_gcs_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (status_code, operation)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}-{{operation}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Status By Method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "GCS", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 76, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 9 + }, + "id": 82, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cortex_dynamo_failures_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Failure Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 9 + }, + "id": 83, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cortex_dynamo_consumed_capacity_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Consumed Capacity Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 9 + }, + "id": 84, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cortex_dynamo_throttled_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Throttled Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 9 + }, + "id": 85, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cortex_dynamo_dropped_requests_total{cluster=\"$cluster\", namespace=\"$namespace\"}[5m]))", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Dropped Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 15 + }, + "id": 86, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(cortex_dynamo_query_pages_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])))", + "legendFormat": ".99", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(cortex_dynamo_query_pages_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])))", + "legendFormat": ".9", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(cortex_dynamo_query_pages_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])))", + "legendFormat": ".5", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Query Pages", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 9, + "x": 6, + "y": 15 + }, + "id": 87, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(cortex_dynamo_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".99-{{operation}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(cortex_dynamo_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".9-{{operation}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(cortex_dynamo_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".5-{{operation}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Latency By Operation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 9, + "x": 15, + "y": 15 + }, + "id": 88, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(cortex_dynamo_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (status_code, operation)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}-{{operation}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Status By Method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Dynamo", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 78, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 79, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_s3_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".99-{{operation}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_s3_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".9-{{operation}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_s3_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".5-{{operation}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Latency By Operation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 80, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_s3_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (status_code, operation)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}-{{operation}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Status By Method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "S3", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 78, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 79, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_azure_blob_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".99-{{operation}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_azure_blob_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".9-{{operation}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_azure_blob_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".5-{{operation}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Latency By Operation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 80, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_azure_blob_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (status_code, operation)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}-{{operation}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Status By Method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "Azure Blob", + "type": "row" + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 114, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 115, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "intervalFactor": 1, + "legendFormat": ".99-{{operation}}", + "refId": "A" + }, + { + "expr": "histogram_quantile(.9, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".9-{{operation}}", + "refId": "B" + }, + { + "expr": "histogram_quantile(.5, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (operation, le))", + "hide": false, + "legendFormat": ".5-{{operation}}", + "refId": "C" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Latency By Operation", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 116, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [ ] + }, + "panels": [ ], + "percentage": false, + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=\"$cluster\", namespace=\"$namespace\"}[5m])) by (status_code, operation)", + "intervalFactor": 1, + "legendFormat": "{{status_code}}-{{operation}}", + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeRegions": [ ], + "timeShift": null, + "title": "Status By Method", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "targets": [ ], + "title": "BoltDB Shipper", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "hide": 0, + "label": null, + "name": "logs", + "options": [ ], + "query": "loki", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Operational", + "uid": "operational", + "version": 0 + } diff --git a/utils/assets/charts/loki/src/dashboards/loki-reads-resources.json b/utils/assets/charts/loki/src/dashboards/loki-reads-resources.json new file mode 100644 index 0000000..6fa166f --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-reads-resources.json @@ -0,0 +1,964 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_cpu_quota{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"} / container_spec_cpu_period{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "CPU", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by(pod) (container_memory_working_set_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_memory_limit_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"} > 0)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (workingset)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (go_memstats_heap_inuse_bytes{cluster=~\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-read\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (go heap inuse)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "gridPos": { }, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(instance, pod, device) (rate(node_disk_written_bytes_total[$__rate_interval])) + ignoring(pod) group_right() (label_replace(count by(instance, pod, device) (container_fs_writes_bytes_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\", device!~\".*sda.*\"}), \"device\", \"$1\", \"device\", \"/dev/(.*)\") * 0)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}} - {{device}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Disk Writes", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "gridPos": { }, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(instance, pod, device) (rate(node_disk_read_bytes_total[$__rate_interval])) + ignoring(pod) group_right() (label_replace(count by(instance, pod, device) (container_fs_writes_bytes_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\", device!~\".*sda.*\"}), \"device\", \"$1\", \"device\", \"/dev/(.*)\") * 0)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}} - {{device}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Disk Reads", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by(persistentvolumeclaim) (kubelet_volume_stats_used_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\"} / kubelet_volume_stats_capacity_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\"}) and count by(persistentvolumeclaim) (kube_persistentvolumeclaim_labels{cluster=~\"$cluster\", namespace=~\"$namespace\",label_name=~\"(loki|enterprise-logs)-read.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{persistentvolumeclaim}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Disk Space Utilization", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "loki_boltdb_shipper_query_readiness_duration_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "duration", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Query Readiness Duration", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Read path", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_cpu_quota{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"} / container_spec_cpu_period{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "CPU", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by(pod) (container_memory_working_set_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_memory_limit_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"} > 0)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (workingset)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (go_memstats_heap_inuse_bytes{cluster=~\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-write\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (go heap inuse)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Ingester", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Reads Resources", + "uid": "reads-resources", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-reads.json b/utils/assets/charts/loki/src/dashboards/loki-reads.json new file mode 100644 index 0000000..6cae30f --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-reads.json @@ -0,0 +1,504 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + "1xx": "#EAB839", + "2xx": "#7EB26D", + "3xx": "#6ED0E0", + "4xx": "#EF843C", + "5xx": "#E24D42", + "error": "#E24D42", + "success": "#7EB26D" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status) (\n label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"loki_api_v1_series|api_prom_series|api_prom_query|api_prom_label|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_labels|loki_api_v1_label_name_values\"}[$__rate_interval]),\n \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n \"status\", \"${1}\", \"status_code\", \"([a-z]+)\"))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{status}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "QPS", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"loki_api_v1_series|api_prom_series|api_prom_query|api_prom_label|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_labels|loki_api_v1_label_name_values\", cluster=~\"$cluster\"})) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ route }} 99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum by (le,route) (job_route:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"loki_api_v1_series|api_prom_series|api_prom_query|api_prom_label|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_labels|loki_api_v1_label_name_values\", cluster=~\"$cluster\"})) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ route }} 50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "1e3 * sum(job_route:loki_request_duration_seconds_sum:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"loki_api_v1_series|api_prom_series|api_prom_query|api_prom_label|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_labels|loki_api_v1_label_name_values\", cluster=~\"$cluster\"}) by (route) / sum(job_route:loki_request_duration_seconds_count:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-read\", route=~\"loki_api_v1_series|api_prom_series|api_prom_query|api_prom_label|api_prom_label_name_values|loki_api_v1_query|loki_api_v1_query_range|loki_api_v1_labels|loki_api_v1_label_name_values\", cluster=~\"$cluster\"}) by (route) ", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ route }} Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Read Path", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + "1xx": "#EAB839", + "2xx": "#7EB26D", + "3xx": "#6ED0E0", + "4xx": "#EF843C", + "5xx": "#E24D42", + "error": "#E24D42", + "success": "#7EB26D" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status) (\n label_replace(label_replace(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-read\", operation=\"Shipper.Query\"}[$__rate_interval]),\n \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n \"status\", \"${1}\", \"status_code\", \"([a-z]+)\"))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{status}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "QPS", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-read\", operation=\"Shipper.Query\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-read\", operation=\"Shipper.Query\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(loki_boltdb_shipper_request_duration_seconds_sum{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-read\", operation=\"Shipper.Query\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-read\", operation=\"Shipper.Query\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "BoltDB Shipper", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Reads", + "uid": "reads", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-retention.json b/utils/assets/charts/loki/src/dashboards/loki-retention.json new file mode 100644 index 0000000..7fc99ec --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-retention.json @@ -0,0 +1,1537 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_cpu_quota{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"} / container_spec_cpu_period{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "CPU", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by(pod) (container_memory_working_set_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_memory_limit_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-read.*\"} > 0)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (workingset)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (go_memstats_heap_inuse_bytes{cluster=~\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-read\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (go heap inuse)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Resource Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "custom": { }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "dateTimeFromNow" + } + }, + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": { }, + "textMode": "auto" + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "loki_boltdb_shipper_compact_tables_operation_last_successful_run_timestamp_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"} * 1e3", + "format": "time_series", + "instant": true, + "refId": "A" + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Last Compact and Mark Operation Success", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "stat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "loki_boltdb_shipper_compact_tables_operation_duration_seconds{cluster=~\"$cluster\", namespace=~\"$namespace\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "duration", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Compact and Mark Operations Duration", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status)(rate(loki_boltdb_shipper_compact_tables_operation_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{success}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Compact and Mark Operations Per Status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Compact and Mark", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "count by(action)(loki_boltdb_shipper_retention_marker_table_processed_total{cluster=~\"$cluster\", namespace=~\"$namespace\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{action}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Processed Tables Per Action", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "count by(table,action)(loki_boltdb_shipper_retention_marker_table_processed_total{cluster=~\"$cluster\", namespace=~\"$namespace\" , action=~\"modified|deleted\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{table}}-{{action}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Modified Tables", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (table)(rate(loki_boltdb_shipper_retention_marker_count_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) >0", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{table}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Marks Creation Rate Per Table", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Per Table Marker", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "short", + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum (increase(loki_boltdb_shipper_retention_marker_count_total{cluster=~\"$cluster\", namespace=~\"$namespace\"}[24h]))", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Marked Chunks (24h)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 11, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_sum{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_retention_marker_table_processed_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Mark Table Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "short", + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum (increase(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[24h]))", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Delete Chunks (24h)", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_bucket{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_sum{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Delete Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Sweeper", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "time() - (loki_boltdb_shipper_retention_sweeper_marker_file_processing_current_time{cluster=~\"$cluster\", namespace=~\"$namespace\"} > 0)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "lag", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Sweeper Lag", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 15, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(loki_boltdb_shipper_retention_sweeper_marker_files_current{cluster=~\"$cluster\", namespace=~\"$namespace\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "count", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Marks Files to Process", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status)(rate(loki_boltdb_shipper_retention_sweeper_chunk_deleted_duration_seconds_count{cluster=~\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{status}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Delete Rate Per Status", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "datasource": "$logs", + "id": 17, + "span": 12, + "targets": [ + { + "expr": "{cluster=~\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-read\"}", + "refId": "A" + } + ], + "title": "Compactor Logs", + "type": "logs" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Logs", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "hide": 0, + "label": null, + "name": "logs", + "options": [ ], + "query": "loki", + "refresh": 1, + "regex": "", + "type": "datasource" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Retention", + "uid": "retention", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-writes-resources.json b/utils/assets/charts/loki/src/dashboards/loki-writes-resources.json new file mode 100644 index 0000000..1b68bd3 --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-writes-resources.json @@ -0,0 +1,700 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (loki_ingester_memory_streams{cluster=~\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-write\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "In-memory streams", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_cpu_usage_seconds_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_cpu_quota{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"} / container_spec_cpu_period{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "CPU", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "limit", + "color": "#E02F44", + "fill": 0 + } + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by(pod) (container_memory_working_set_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "min(container_spec_memory_limit_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\"} > 0)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limit", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (workingset)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (go_memstats_heap_inuse_bytes{cluster=~\"$cluster\", job=~\"($namespace)/(loki|enterprise-logs)-write\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Memory (go heap inuse)", + "tooltip": { + "sort": 2 + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "gridPos": { }, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(instance, pod, device) (rate(node_disk_written_bytes_total[$__rate_interval])) + ignoring(pod) group_right() (label_replace(count by(instance, pod, device) (container_fs_writes_bytes_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\", device!~\".*sda.*\"}), \"device\", \"$1\", \"device\", \"/dev/(.*)\") * 0)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}} - {{device}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Disk Writes", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "gridPos": { }, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(instance, pod, device) (rate(node_disk_read_bytes_total[$__rate_interval])) + ignoring(pod) group_right() (label_replace(count by(instance, pod, device) (container_fs_writes_bytes_total{cluster=~\"$cluster\", namespace=~\"$namespace\", container=\"loki\", pod=~\"(loki|enterprise-logs)-write.*\", device!~\".*sda.*\"}), \"device\", \"$1\", \"device\", \"/dev/(.*)\") * 0)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{pod}} - {{device}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Disk Reads", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "gridPos": { }, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max by(persistentvolumeclaim) (kubelet_volume_stats_used_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\"} / kubelet_volume_stats_capacity_bytes{cluster=~\"$cluster\", namespace=~\"$namespace\"}) and count by(persistentvolumeclaim) (kube_persistentvolumeclaim_labels{cluster=~\"$cluster\", namespace=~\"$namespace\",label_name=~\"(loki|enterprise-logs)-write.*\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{persistentvolumeclaim}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Disk Space Utilization", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Write path", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Writes Resources", + "uid": "writes-resources", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/dashboards/loki-writes.json b/utils/assets/charts/loki/src/dashboards/loki-writes.json new file mode 100644 index 0000000..ebaf33e --- /dev/null +++ b/utils/assets/charts/loki/src/dashboards/loki-writes.json @@ -0,0 +1,504 @@ +{ + "annotations": { + "list": [ ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "loki" + ], + "targetBlank": false, + "title": "Loki Dashboards", + "type": "dashboards" + } + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + "1xx": "#EAB839", + "2xx": "#7EB26D", + "3xx": "#6ED0E0", + "4xx": "#EF843C", + "5xx": "#E24D42", + "error": "#E24D42", + "success": "#7EB26D" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status) (\n label_replace(label_replace(rate(loki_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\", route=~\"api_prom_push|loki_api_v1_push|/httpgrpc.HTTP/Handle\"}[$__rate_interval]),\n \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n \"status\", \"${1}\", \"status_code\", \"([a-z]+)\"))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{status}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "QPS", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le) (job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", cluster=~\"$cluster\"})) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum by (le) (job:loki_request_duration_seconds_bucket:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", cluster=~\"$cluster\"})) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "1e3 * sum(job:loki_request_duration_seconds_sum:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", cluster=~\"$cluster\"}) / sum(job:loki_request_duration_seconds_count:sum_rate{job=~\"($namespace)/(loki|enterprise-logs)-write\", cluster=~\"$cluster\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Write Path", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + "1xx": "#EAB839", + "2xx": "#7EB26D", + "3xx": "#6ED0E0", + "4xx": "#EF843C", + "5xx": "#E24D42", + "error": "#E24D42", + "success": "#7EB26D" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status) (\n label_replace(label_replace(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\", operation=\"WRITE\"}[$__rate_interval]),\n \"status\", \"${1}xx\", \"status_code\", \"([0-9])..\"),\n \"status\", \"${1}\", \"status_code\", \"([a-z]+)\"))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{status}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "QPS", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\", operation=\"WRITE\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "99th Percentile", + "refId": "A", + "step": 10 + }, + { + "expr": "histogram_quantile(0.50, sum(rate(loki_boltdb_shipper_request_duration_seconds_bucket{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\", operation=\"WRITE\"}[$__rate_interval])) by (le)) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "50th Percentile", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(rate(loki_boltdb_shipper_request_duration_seconds_sum{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\", operation=\"WRITE\"}[$__rate_interval])) * 1e3 / sum(rate(loki_boltdb_shipper_request_duration_seconds_count{cluster=~\"$cluster\",job=~\"($namespace)/(loki|enterprise-logs)-write\", operation=\"WRITE\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Average", + "refId": "C", + "step": 10 + } + ], + "thresholds": [ ], + "timeFrom": null, + "timeShift": null, + "title": "Latency", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "BoltDB Shipper", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "loki" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [ ], + "query": "label_values(loki_build_info, cluster)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ ], + "query": "label_values(loki_build_info{cluster=~\"$cluster\"}, namespace)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Loki / Writes", + "uid": "writes", + "version": 0 + } \ No newline at end of file diff --git a/utils/assets/charts/loki/src/helm-test/Dockerfile b/utils/assets/charts/loki/src/helm-test/Dockerfile new file mode 100644 index 0000000..9378d53 --- /dev/null +++ b/utils/assets/charts/loki/src/helm-test/Dockerfile @@ -0,0 +1,13 @@ +ARG GO_VERSION=1.23 +FROM golang:${GO_VERSION} as build + +# build via Makefile target helm-test-image in root +# Makefile. Building from this directory will not be +# able to access source needed in rest of repo. +COPY . /src/loki +WORKDIR /src/loki +RUN make clean && make BUILD_IN_CONTAINER=false helm-test + +FROM gcr.io/distroless/static:debug +COPY --from=build /src/loki/production/helm/loki/src/helm-test/helm-test /usr/bin/helm-test +ENTRYPOINT [ "/usr/bin/helm-test" ] diff --git a/utils/assets/charts/loki/src/helm-test/README.md b/utils/assets/charts/loki/src/helm-test/README.md new file mode 100644 index 0000000..68c9bfd --- /dev/null +++ b/utils/assets/charts/loki/src/helm-test/README.md @@ -0,0 +1,7 @@ +# Loki Helm Test + +This folder contains a collection of go tests that test if a Loki canary is running correctly. It's primary use it to test that the helm chart is working correctly by using metrics from the Loki canary. In the helm chart, the template for this test is only available if you are running both the Loki canary and have self monitoring enabled (as the Loki canary's logs need to be in Loki for it to work). However, the tests in this folder can be run against any running Loki canary using `go test`. + +## Instructions + +Run `go test .` from this directory, or use the Docker image published at `grafana/loki-helm-test`. diff --git a/utils/assets/charts/loki/src/helm-test/canary_test.go b/utils/assets/charts/loki/src/helm-test/canary_test.go new file mode 100644 index 0000000..002cae4 --- /dev/null +++ b/utils/assets/charts/loki/src/helm-test/canary_test.go @@ -0,0 +1,178 @@ +//go:build helm_test +// +build helm_test + +package test + +import ( + "context" + "errors" + "fmt" + "io" + "net/http" + "os" + "testing" + "time" + + "github.com/prometheus/client_golang/api" + v1 "github.com/prometheus/client_golang/api/prometheus/v1" + promConfig "github.com/prometheus/common/config" + "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/model/textparse" + "github.com/stretchr/testify/require" +) + +type testResultFunc func(t *testing.T, ctx context.Context, metric string, test func(model.SampleValue) bool, msg string) error + +func TestCanary(t *testing.T) { + + var testResult testResultFunc + + // Default to directly querying a canary and looking for specific metrics. + testResult = testResultCanary + totalEntries := "loki_canary_entries_total" + totalEntriesMissing := "loki_canary_missing_entries_total" + + // For backwards compatibility and also for anyone who wants to validate with prometheus instead of querying + // a canary directly, if the CANARY_PROMETHEUS_ADDRESS is specified we will use prometheus to validate. + address := os.Getenv("CANARY_PROMETHEUS_ADDRESS") + if address != "" { + testResult = testResultPrometheus + // Use the sum function to aggregate the results from multiple canaries. + totalEntries = "sum(loki_canary_entries_total)" + totalEntriesMissing = "sum(loki_canary_missing_entries_total)" + } + + timeout := getEnv("CANARY_TEST_TIMEOUT", "1m") + timeoutDuration, err := time.ParseDuration(timeout) + require.NoError(t, err, "Failed to parse timeout. Please set CANARY_TEST_TIMEOUT to a valid duration.") + + ctx, cancel := context.WithTimeout(context.Background(), timeoutDuration) + + t.Cleanup(func() { + cancel() + }) + + t.Run("Canary should have entries", func(t *testing.T) { + eventually(t, func() error { + return testResult(t, ctx, totalEntries, func(v model.SampleValue) bool { + return v > 0 + }, fmt.Sprintf("Expected %s to be greater than 0", totalEntries)) + }, timeoutDuration, "Expected Loki Canary to have entries") + }) + + t.Run("Canary should not have missed any entries", func(t *testing.T) { + eventually(t, func() error { + return testResult(t, ctx, totalEntriesMissing, func(v model.SampleValue) bool { + return v == 0 + }, fmt.Sprintf("Expected %s to equal 0", totalEntriesMissing)) + }, timeoutDuration, "Expected Loki Canary to not have any missing entries") + }) +} + +func getEnv(key, fallback string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + return fallback +} + +func testResultPrometheus(t *testing.T, ctx context.Context, query string, test func(model.SampleValue) bool, msg string) error { + // TODO (ewelch): if we did a lot of these, we'd want to reuse the client but right now we only run a couple tests + client := newClient(t) + result, _, err := client.Query(ctx, query, time.Now()) + if err != nil { + return err + } + if v, ok := result.(model.Vector); ok { + for _, s := range v { + t.Logf("%s => %v\n", query, s.Value) + if !test(s.Value) { + return errors.New(msg) + } + } + return nil + } + + return fmt.Errorf("unexpected Prometheus result type: %v ", result.Type()) +} + +func newClient(t *testing.T) v1.API { + address := os.Getenv("CANARY_PROMETHEUS_ADDRESS") + require.NotEmpty(t, address, "CANARY_PROMETHEUS_ADDRESS must be set to a valid prometheus address") + + client, err := api.NewClient(api.Config{ + Address: address, + }) + require.NoError(t, err, "Failed to create Loki Canary client") + + return v1.NewAPI(client) +} + +func testResultCanary(t *testing.T, ctx context.Context, metric string, test func(model.SampleValue) bool, msg string) error { + address := os.Getenv("CANARY_SERVICE_ADDRESS") + require.NotEmpty(t, address, "CANARY_SERVICE_ADDRESS must be set to a valid kubernetes service for the Loki canaries") + + // TODO (ewelch): if we did a lot of these, we'd want to reuse the client but right now we only run a couple tests + client, err := promConfig.NewClientFromConfig(promConfig.HTTPClientConfig{}, "canary-test") + require.NoError(t, err, "Failed to create Prometheus client") + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, address, nil) + require.NoError(t, err, "Failed to create request") + + rsp, err := client.Do(req) + if rsp != nil { + defer rsp.Body.Close() + } + require.NoError(t, err, "Failed to scrape metrics") + + body, err := io.ReadAll(rsp.Body) + require.NoError(t, err, "Failed to read response body") + + p, err := textparse.New(body, rsp.Header.Get("Content-Type"), true, nil) + require.NoError(t, err, "Failed to create Prometheus parser") + + for { + e, err := p.Next() + if err == io.EOF { + return errors.New("metric not found") + } + + if e != textparse.EntrySeries { + continue + } + + l := labels.Labels{} + p.Metric(&l) + + // Currently we aren't validating any labels, just the metric name, however this could be extended to do so. + name := l.Get(model.MetricNameLabel) + if name != metric { + continue + } + + _, _, val := p.Series() + t.Logf("%s => %v\n", metric, val) + + // Note: SampleValue has functions for comparing the equality of two floats which is + // why we convert this back to a SampleValue here for easier use intests. + if !test(model.SampleValue(val)) { + return errors.New(msg) + } + + // Returning here will only validate that one series was found matching the label name that met the condition + // it could be possible since we don't validate the rest of the labels that there is mulitple series + // but currently this meets the spirit of the test. + return nil + } +} + +func eventually(t *testing.T, test func() error, timeoutDuration time.Duration, msg string) { + require.Eventually(t, func() bool { + queryError := test() + if queryError != nil { + t.Logf("Query failed\n%+v\n", queryError) + } + return queryError == nil + }, timeoutDuration, 1*time.Second, msg) +} diff --git a/utils/assets/charts/loki/src/helm-test/default.nix b/utils/assets/charts/loki/src/helm-test/default.nix new file mode 100644 index 0000000..a129b23 --- /dev/null +++ b/utils/assets/charts/loki/src/helm-test/default.nix @@ -0,0 +1,27 @@ +{ pkgs, lib, buildGoModule, dockerTools, rev }: +rec { + loki-helm-test = buildGoModule rec { + pname = "loki-helm-test"; + version = "0.1.0"; + + src = ./../../../../..; + vendorHash = null; + + buildPhase = '' + runHook preBuild + go test --tags=helm_test -c -o $out/bin/helm-test ./production/helm/loki/src/helm-test + runHook postBuild + ''; + + doCheck = false; + }; + + # by default, uses the nix hash as the tag, which can be retrieved with: + # basename "$(readlink result)" | cut -d - -f 1 + loki-helm-test-docker = dockerTools.buildImage { + name = "grafana/loki-helm-test"; + config = { + Entrypoint = [ "${loki-helm-test}/bin/helm-test" ]; + }; + }; +} diff --git a/utils/assets/charts/loki/src/rules.yaml.tpl b/utils/assets/charts/loki/src/rules.yaml.tpl new file mode 100644 index 0000000..840401d --- /dev/null +++ b/utils/assets/charts/loki/src/rules.yaml.tpl @@ -0,0 +1,86 @@ +--- +groups: + - name: "loki_rules" + rules: + - expr: histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket[1m])) + by (le, job)) + record: job:loki_request_duration_seconds:99quantile + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: histogram_quantile(0.50, sum(rate(loki_request_duration_seconds_bucket[1m])) + by (le, job)) + record: job:loki_request_duration_seconds:50quantile + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_sum[1m])) by (job) / sum(rate(loki_request_duration_seconds_count[1m])) + by (job) + record: job:loki_request_duration_seconds:avg + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_bucket[1m])) by (le, job) + record: job:loki_request_duration_seconds_bucket:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_sum[1m])) by (job) + record: job:loki_request_duration_seconds_sum:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_count[1m])) by (job) + record: job:loki_request_duration_seconds_count:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket[1m])) + by (le, job, route)) + record: job_route:loki_request_duration_seconds:99quantile + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: histogram_quantile(0.50, sum(rate(loki_request_duration_seconds_bucket[1m])) + by (le, job, route)) + record: job_route:loki_request_duration_seconds:50quantile + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_sum[1m])) by (job, route) / sum(rate(loki_request_duration_seconds_count[1m])) + by (job, route) + record: job_route:loki_request_duration_seconds:avg + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_bucket[1m])) by (le, job, route) + record: job_route:loki_request_duration_seconds_bucket:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_sum[1m])) by (job, route) + record: job_route:loki_request_duration_seconds_sum:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_count[1m])) by (job, route) + record: job_route:loki_request_duration_seconds_count:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket[1m])) + by (le, namespace, job, route)) + record: namespace_job_route:loki_request_duration_seconds:99quantile + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: histogram_quantile(0.50, sum(rate(loki_request_duration_seconds_bucket[1m])) + by (le, namespace, job, route)) + record: namespace_job_route:loki_request_duration_seconds:50quantile + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_sum[1m])) by (namespace, job, route) + / sum(rate(loki_request_duration_seconds_count[1m])) by (namespace, job, route) + record: namespace_job_route:loki_request_duration_seconds:avg + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_bucket[1m])) by (le, namespace, job, + route) + record: namespace_job_route:loki_request_duration_seconds_bucket:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_sum[1m])) by (namespace, job, route) + record: namespace_job_route:loki_request_duration_seconds_sum:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" + - expr: sum(rate(loki_request_duration_seconds_count[1m])) by (namespace, job, route) + record: namespace_job_route:loki_request_duration_seconds_count:sum_rate + labels: + cluster: "{{ include "loki.clusterLabel" $ }}" diff --git a/utils/assets/charts/loki/templates/NOTES.txt b/utils/assets/charts/loki/templates/NOTES.txt new file mode 100644 index 0000000..622b1a8 --- /dev/null +++ b/utils/assets/charts/loki/templates/NOTES.txt @@ -0,0 +1,184 @@ +*********************************************************************** + Welcome to Grafana Loki + Chart version: {{ .Chart.Version }} + Chart Name: {{ .Chart.Name }} + Loki version: {{ .Chart.AppVersion }} +*********************************************************************** + +** Please be patient while the chart is being deployed ** + +Tip: + + Watch the deployment status using the command: kubectl get pods -w --namespace {{ $.Release.Namespace }} + +If pods are taking too long to schedule make sure pod affinity can be fulfilled in the current cluster. + +*********************************************************************** +Installed components: +*********************************************************************** + +{{- if .Values.monitoring.selfMonitoring.enabled }} +* grafana-agent-operator +{{- end }} +{{- if eq (include "loki.deployment.isSingleBinary" .) "true" }} +* loki +{{- else -}} +{{- if .Values.gateway.enabled }} +* gateway +{{- end }} +{{- if .Values.minio.enabled }} +* minio +{{- end }} +{{- if eq (include "loki.deployment.isScalable" .) "true" }} +* read +* write +{{- if not .Values.read.legacyReadTarget }} +* backend +{{- end }} +{{- else }} +* compactor +* index gateway +* query scheduler +* ruler +* distributor +* ingester +* querier +* query frontend +{{- end }} +{{- end }} + + +{{- if eq (include "loki.deployment.isSingleBinary" .) "true" }} + +Loki has been deployed as a single binary. +This means a single pod is handling reads and writes. You can scale that pod vertically by adding more CPU and memory resources. + +{{- end }} + + +*********************************************************************** +Sending logs to Loki +*********************************************************************** + +{{- if .Values.gateway.enabled }} + +Loki has been configured with a gateway (nginx) to support reads and writes from a single component. + +{{- end }} + +You can send logs from inside the cluster using the cluster DNS: + +{{- if .Values.gateway.enabled }} + +http://{{ include "loki.gatewayFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local/loki/api/v1/push + +{{- else }} +{{- if eq (include "loki.deployment.isSingleBinary" .) "true" }} + +http://{{ include "loki.singleBinaryFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local:{{ .Values.loki.server.http_listen_port }}/loki/api/v1/push + +{{- end}} +{{- if eq (include "loki.deployment.isScalable" .) "true" }} + +http://{{ include "loki.writeFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local:{{ .Values.loki.server.http_listen_port }}/loki/api/v1/push + +{{- end }} +{{- if eq (include "loki.deployment.isDistributed" .) "true" }} + +http://{{ include "loki.distributorFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local:3100/loki/api/v1/push + +{{- end }} +{{- end }} + +You can test to send data from outside the cluster by port-forwarding the gateway to your local machine: +{{- if .Values.gateway.enabled }} + + kubectl port-forward --namespace {{ $.Release.Namespace }} svc/{{ include "loki.gatewayFullname" . }} 3100:{{ .Values.gateway.service.port }} & + +{{- else }} +{{- if eq (include "loki.deployment.isSingleBinary" .) "true" }} + + kubectl port-forward --namespace {{ $.Release.Namespace }} svc/{{ include "loki.singleBinaryFullname" . }} 3100:{{ .Values.loki.server.http_listen_port }} & + +{{- end}} +{{- if eq (include "loki.deployment.isScalable" .) "true" }} + + kubectl port-forward --namespace {{ $.Release.Namespace }} svc/{{ include "loki.writeFullname" . }} 3100:{{ .Values.loki.server.http_listen_port }} & + +{{- end }} +{{- if eq (include "loki.deployment.isDistributed" .) "true" }} + + kubectl port-forward --namespace {{ $.Release.Namespace }} svc/{{ include "loki.distributorFullname" . }} 3100:3100 & + +{{- end }} +{{- end }} + +And then using http://127.0.0.1:3100/loki/api/v1/push URL as shown below: + +``` +curl -H "Content-Type: application/json" -XPOST -s "http://127.0.0.1:3100/loki/api/v1/push" \ +--data-raw "{\"streams\": [{\"stream\": {\"job\": \"test\"}, \"values\": [[\"$(date +%s)000000000\", \"fizzbuzz\"]]}]}" +{{- if .Values.loki.auth_enabled }} \ +-H X-Scope-OrgId:foo +{{- end}} +``` + +Then verify that Loki did received the data using the following command: + +``` +curl "http://127.0.0.1:3100/loki/api/v1/query_range" --data-urlencode 'query={job="test"}' {{- if .Values.loki.auth_enabled }} -H X-Scope-OrgId:foo {{- end}} | jq .data.result +``` + +*********************************************************************** +Connecting Grafana to Loki +*********************************************************************** + +If Grafana operates within the cluster, you'll set up a new Loki datasource by utilizing the following URL: + +{{- if .Values.gateway.enabled }} + +http://{{ include "loki.gatewayFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local/ + +{{- else }} +{{- if eq (include "loki.deployment.isSingleBinary" .) "true" }} + +http://{{ include "loki.singleBinaryFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local:{{ .Values.loki.server.http_listen_port }}/ + +{{- end}} +{{- if eq (include "loki.deployment.isScalable" .) "true" }} + +http://{{ include "loki.readFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local:{{ .Values.loki.server.http_listen_port }}/ + +{{- end }} +{{- if eq (include "loki.deployment.isDistributed" .) "true" }} + +http://{{ include "loki.queryFrontendFullname" . }}.{{ $.Release.Namespace }}.svc.cluster.local:3100/ + +{{- end }} +{{- end }} + + + +{{- if .Values.loki.auth_enabled }} + +*********************************************************************** +Multi-tenancy +*********************************************************************** + +Loki is configured with auth enabled (multi-tenancy) and expects tenant headers (`X-Scope-OrgID`) to be set for all API calls. + +You must configure Grafana's Loki datasource using the `HTTP Headers` section with the `X-Scope-OrgID` to target a specific tenant. +For each tenant, you can create a different datasource. + +The agent of your choice must also be configured to propagate this header. +For example, when using Promtail you can use the `tenant` stage. https://grafana.com/docs/loki/latest/send-data/promtail/stages/tenant/ + +When not provided with the `X-Scope-OrgID` while auth is enabled, Loki will reject reads and writes with a 404 status code `no org id`. + +You can also use a reverse proxy, to automatically add the `X-Scope-OrgID` header as suggested by https://grafana.com/docs/loki/latest/operations/authentication/ + +For more information, read our documentation about multi-tenancy: https://grafana.com/docs/loki/latest/operations/multi-tenancy/ + +> When using curl you can pass `X-Scope-OrgId` header using `-H X-Scope-OrgId:foo` option, where foo can be replaced with the tenant of your choice. + +{{- end }} diff --git a/utils/assets/charts/loki/templates/_helpers.tpl b/utils/assets/charts/loki/templates/_helpers.tpl new file mode 100644 index 0000000..acc6690 --- /dev/null +++ b/utils/assets/charts/loki/templates/_helpers.tpl @@ -0,0 +1,1132 @@ +{{/* +Enforce valid label value. +See https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set +*/}} +{{- define "loki.validLabelValue" -}} +{{- (regexReplaceAllLiteral "[^a-zA-Z0-9._-]" . "-") | trunc 63 | trimSuffix "-" | trimSuffix "_" | trimSuffix "." }} +{{- end }} + +{{/* +Expand the name of the chart. +*/}} +{{- define "loki.name" -}} +{{- $default := ternary "enterprise-logs" "loki" .Values.enterprise.enabled }} +{{- coalesce .Values.nameOverride $default | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +singleBinary fullname +*/}} +{{- define "loki.singleBinaryFullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Resource name template +Params: + ctx = . context + component = component name (optional) + rolloutZoneName = rollout zone name (optional) +*/}} +{{- define "loki.resourceName" -}} +{{- $resourceName := include "loki.fullname" .ctx -}} +{{- if .component -}}{{- $resourceName = printf "%s-%s" $resourceName .component -}}{{- end -}} +{{- if and (not .component) .rolloutZoneName -}}{{- printf "Component name cannot be empty if rolloutZoneName (%s) is set" .rolloutZoneName | fail -}}{{- end -}} +{{- if .rolloutZoneName -}}{{- $resourceName = printf "%s-%s" $resourceName .rolloutZoneName -}}{{- end -}} +{{- if gt (len $resourceName) 253 -}}{{- printf "Resource name (%s) exceeds kubernetes limit of 253 character. To fix: shorten release name if this will be a fresh install or shorten zone names (e.g. \"a\" instead of \"zone-a\") if using zone-awareness." $resourceName | fail -}}{{- end -}} +{{- $resourceName -}} +{{- end -}} + +{{/* +Return if deployment mode is simple scalable +*/}} +{{- define "loki.deployment.isScalable" -}} + {{- and (eq (include "loki.isUsingObjectStorage" . ) "true") (or (eq .Values.deploymentMode "SingleBinary<->SimpleScalable") (eq .Values.deploymentMode "SimpleScalable") (eq .Values.deploymentMode "SimpleScalable<->Distributed")) }} +{{- end -}} + +{{/* +Return if deployment mode is single binary +*/}} +{{- define "loki.deployment.isSingleBinary" -}} + {{- or (eq .Values.deploymentMode "SingleBinary") (eq .Values.deploymentMode "SingleBinary<->SimpleScalable") }} +{{- end -}} + +{{/* +Return if deployment mode is distributed +*/}} +{{- define "loki.deployment.isDistributed" -}} + {{- and (eq (include "loki.isUsingObjectStorage" . ) "true") (or (eq .Values.deploymentMode "Distributed") (eq .Values.deploymentMode "SimpleScalable<->Distributed")) }} +{{- end -}} + + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "loki.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := include "loki.name" . }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Cluster label for rules and alerts. +*/}} +{{- define "loki.clusterLabel" -}} +{{- if .Values.clusterLabelOverride }} +{{- .Values.clusterLabelOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := include "loki.name" . }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Create a default storage config that uses filesystem storage +This is required for CI, but Loki will not be queryable with this default +applied, thus it is encouraged that users override this. +*/}} +{{- define "loki.storageConfig" -}} +{{- if .Values.loki.storageConfig -}} +{{- .Values.loki.storageConfig | toYaml | nindent 4 -}} +{{- else }} +{{- .Values.loki.defaultStorageConfig | toYaml | nindent 4 }} +{{- end}} +{{- end}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "loki.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "loki.labels" -}} +helm.sh/chart: {{ include "loki.chart" . }} +{{ include "loki.selectorLabels" . }} +{{- if or (.Chart.AppVersion) (.Values.loki.image.tag) }} +app.kubernetes.io/version: {{ include "loki.validLabelValue" (.Values.loki.image.tag | default .Chart.AppVersion) | quote }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "loki.selectorLabels" -}} +app.kubernetes.io/name: {{ include "loki.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "loki.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "loki.name" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Base template for building docker image reference +*/}} +{{- define "loki.baseImage" }} +{{- $registry := .global.registry | default .service.registry | default "" -}} +{{- $repository := .service.repository | default "" -}} +{{- $ref := ternary (printf ":%s" (.service.tag | default .defaultVersion | toString)) (printf "@%s" .service.digest) (empty .service.digest) -}} +{{- if and $registry $repository -}} + {{- printf "%s/%s%s" $registry $repository $ref -}} +{{- else -}} + {{- printf "%s%s%s" $registry $repository $ref -}} +{{- end -}} +{{- end -}} + +{{/* +Docker image name for Loki +*/}} +{{- define "loki.lokiImage" -}} +{{- $dict := dict "service" .Values.loki.image "global" .Values.global.image "defaultVersion" .Chart.AppVersion -}} +{{- include "loki.baseImage" $dict -}} +{{- end -}} + +{{/* +Docker image name for enterprise logs +*/}} +{{- define "loki.enterpriseImage" -}} +{{- $dict := dict "service" .Values.enterprise.image "global" .Values.global.image "defaultVersion" .Values.enterprise.version -}} +{{- include "loki.baseImage" $dict -}} +{{- end -}} + +{{/* +Docker image name +*/}} +{{- define "loki.image" -}} +{{- if .Values.enterprise.enabled -}}{{- include "loki.enterpriseImage" . -}}{{- else -}}{{- include "loki.lokiImage" . -}}{{- end -}} +{{- end -}} + +{{/* +Docker image name for kubectl container +*/}} +{{- define "loki.kubectlImage" -}} +{{- $dict := dict "service" .Values.kubectlImage "global" .Values.global.image "defaultVersion" "latest" -}} +{{- include "loki.baseImage" $dict -}} +{{- end -}} + +{{/* +Generated storage config for loki common config +*/}} +{{- define "loki.commonStorageConfig" -}} +{{- if .Values.minio.enabled -}} +s3: + endpoint: {{ include "loki.minio" $ }} + bucketnames: chunks + secret_access_key: {{ $.Values.minio.rootPassword }} + access_key_id: {{ $.Values.minio.rootUser }} + s3forcepathstyle: true + insecure: true +{{- else if eq .Values.loki.storage.type "s3" -}} +{{- with .Values.loki.storage.s3 }} +s3: + {{- with .s3 }} + s3: {{ . }} + {{- end }} + {{- with .endpoint }} + endpoint: {{ . }} + {{- end }} + {{- with .region }} + region: {{ . }} + {{- end}} + bucketnames: {{ $.Values.loki.storage.bucketNames.chunks }} + {{- with .secretAccessKey }} + secret_access_key: {{ . }} + {{- end }} + {{- with .accessKeyId }} + access_key_id: {{ . }} + {{- end }} + {{- with .signatureVersion }} + signature_version: {{ . }} + {{- end }} + s3forcepathstyle: {{ .s3ForcePathStyle }} + insecure: {{ .insecure }} + {{- with .disable_dualstack }} + disable_dualstack: {{ . }} + {{- end }} + {{- with .http_config}} + http_config: +{{ toYaml . | indent 4 }} + {{- end }} + {{- with .backoff_config}} + backoff_config: +{{ toYaml . | indent 4 }} + {{- end }} + {{- with .sse }} + sse: +{{ toYaml . | indent 4 }} + {{- end }} +{{- end -}} + +{{- else if eq .Values.loki.storage.type "gcs" -}} +{{- with .Values.loki.storage.gcs }} +gcs: + bucket_name: {{ $.Values.loki.storage.bucketNames.chunks }} + chunk_buffer_size: {{ .chunkBufferSize }} + request_timeout: {{ .requestTimeout }} + enable_http2: {{ .enableHttp2 }} +{{- end -}} +{{- else if eq .Values.loki.storage.type "azure" -}} +{{- with .Values.loki.storage.azure }} +azure: + account_name: {{ .accountName }} + {{- with .accountKey }} + account_key: {{ . }} + {{- end }} + {{- with .connectionString }} + connection_string: {{ . }} + {{- end }} + container_name: {{ $.Values.loki.storage.bucketNames.chunks }} + use_managed_identity: {{ .useManagedIdentity }} + use_federated_token: {{ .useFederatedToken }} + {{- with .userAssignedId }} + user_assigned_id: {{ . }} + {{- end }} + {{- with .requestTimeout }} + request_timeout: {{ . }} + {{- end }} + {{- with .endpointSuffix }} + endpoint_suffix: {{ . }} + {{- end }} + {{- with .chunkDelimiter }} + chunk_delimiter: {{ . }} + {{- end }} +{{- end -}} +{{- else if eq .Values.loki.storage.type "alibabacloud" -}} +{{- with .Values.loki.storage.alibabacloud }} +alibabacloud: + bucket: {{ $.Values.loki.storage.bucketNames.chunks }} + endpoint: {{ .endpoint }} + access_key_id: {{ .accessKeyId }} + secret_access_key: {{ .secretAccessKey }} +{{- end -}} +{{- else if eq .Values.loki.storage.type "swift" -}} +{{- with .Values.loki.storage.swift }} +swift: +{{ toYaml . | indent 2 }} +{{- end -}} +{{- else -}} +{{- with .Values.loki.storage.filesystem }} +filesystem: + chunks_directory: {{ .chunks_directory }} + rules_directory: {{ .rules_directory }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Storage config for ruler +*/}} +{{- define "loki.rulerStorageConfig" -}} +{{- if .Values.minio.enabled -}} +type: "s3" +s3: + bucketnames: ruler +{{- else if eq .Values.loki.storage.type "s3" -}} +{{- with .Values.loki.storage.s3 }} +type: "s3" +s3: + {{- with .s3 }} + s3: {{ . }} + {{- end }} + {{- with .endpoint }} + endpoint: {{ . }} + {{- end }} + {{- with .region }} + region: {{ . }} + {{- end}} + bucketnames: {{ $.Values.loki.storage.bucketNames.ruler }} + {{- with .secretAccessKey }} + secret_access_key: {{ . }} + {{- end }} + {{- with .accessKeyId }} + access_key_id: {{ . }} + {{- end }} + s3forcepathstyle: {{ .s3ForcePathStyle }} + insecure: {{ .insecure }} + {{- with .http_config }} + http_config: {{ toYaml . | nindent 6 }} + {{- end }} +{{- end -}} +{{- else if eq .Values.loki.storage.type "gcs" -}} +{{- with .Values.loki.storage.gcs }} +type: "gcs" +gcs: + bucket_name: {{ $.Values.loki.storage.bucketNames.ruler }} + chunk_buffer_size: {{ .chunkBufferSize }} + request_timeout: {{ .requestTimeout }} + enable_http2: {{ .enableHttp2 }} +{{- end -}} +{{- else if eq .Values.loki.storage.type "azure" -}} +{{- with .Values.loki.storage.azure }} +type: "azure" +azure: + account_name: {{ .accountName }} + {{- with .accountKey }} + account_key: {{ . }} + {{- end }} + {{- with .connectionString }} + connection_string: {{ . }} + {{- end }} + container_name: {{ $.Values.loki.storage.bucketNames.ruler }} + use_managed_identity: {{ .useManagedIdentity }} + use_federated_token: {{ .useFederatedToken }} + {{- with .userAssignedId }} + user_assigned_id: {{ . }} + {{- end }} + {{- with .requestTimeout }} + request_timeout: {{ . }} + {{- end }} + {{- with .endpointSuffix }} + endpoint_suffix: {{ . }} + {{- end }} +{{- end -}} +{{- else if eq .Values.loki.storage.type "swift" -}} +{{- with .Values.loki.storage.swift }} +swift: + {{- with .auth_version }} + auth_version: {{ . }} + {{- end }} + auth_url: {{ .auth_url }} + {{- with .internal }} + internal: {{ . }} + {{- end }} + username: {{ .username }} + user_domain_name: {{ .user_domain_name }} + {{- with .user_domain_id }} + user_domain_id: {{ . }} + {{- end }} + {{- with .user_id }} + user_id: {{ . }} + {{- end }} + password: {{ .password }} + {{- with .domain_id }} + domain_id: {{ . }} + {{- end }} + domain_name: {{ .domain_name }} + project_id: {{ .project_id }} + project_name: {{ .project_name }} + project_domain_id: {{ .project_domain_id }} + project_domain_name: {{ .project_domain_name }} + region_name: {{ .region_name }} + container_name: {{ .container_name }} + max_retries: {{ .max_retries | default 3 }} + connect_timeout: {{ .connect_timeout | default "10s" }} + request_timeout: {{ .request_timeout | default "5s" }} +{{- end -}} +{{- else }} +type: "local" +{{- end -}} +{{- end -}} + +{{/* Loki ruler config */}} +{{- define "loki.rulerConfig" }} +ruler: + storage: + {{- include "loki.rulerStorageConfig" . | nindent 4}} +{{- if (not (empty .Values.loki.rulerConfig)) }} +{{- toYaml .Values.loki.rulerConfig | nindent 2}} +{{- end }} +{{- end }} + +{{/* Enterprise Logs Admin API storage config */}} +{{- define "enterprise-logs.adminAPIStorageConfig" }} +storage: + {{- if .Values.minio.enabled }} + backend: "s3" + s3: + bucket_name: admin + {{- else if eq .Values.loki.storage.type "s3" -}} + {{- with .Values.loki.storage.s3 }} + backend: "s3" + s3: + bucket_name: {{ $.Values.loki.storage.bucketNames.admin }} + {{- end -}} + {{- else if eq .Values.loki.storage.type "gcs" -}} + {{- with .Values.loki.storage.gcs }} + backend: "gcs" + gcs: + bucket_name: {{ $.Values.loki.storage.bucketNames.admin }} + {{- end -}} + {{- else if eq .Values.loki.storage.type "azure" -}} + {{- with .Values.loki.storage.azure }} + backend: "azure" + azure: + account_name: {{ .accountName }} + {{- with .accountKey }} + account_key: {{ . }} + {{- end }} + {{- with .connectionString }} + connection_string: {{ . }} + {{- end }} + container_name: {{ $.Values.loki.storage.bucketNames.admin }} + {{- with .endpointSuffix }} + endpoint_suffix: {{ . }} + {{- end }} + {{- end -}} + {{- else if eq .Values.loki.storage.type "swift" -}} + {{- with .Values.loki.storage.swift }} + backend: "swift" + swift: + {{- with .auth_version }} + auth_version: {{ . }} + {{- end }} + auth_url: {{ .auth_url }} + {{- with .internal }} + internal: {{ . }} + {{- end }} + username: {{ .username }} + user_domain_name: {{ .user_domain_name }} + {{- with .user_domain_id }} + user_domain_id: {{ . }} + {{- end }} + {{- with .user_id }} + user_id: {{ . }} + {{- end }} + password: {{ .password }} + {{- with .domain_id }} + domain_id: {{ . }} + {{- end }} + domain_name: {{ .domain_name }} + project_id: {{ .project_id }} + project_name: {{ .project_name }} + project_domain_id: {{ .project_domain_id }} + project_domain_name: {{ .project_domain_name }} + region_name: {{ .region_name }} + container_name: {{ .container_name }} + max_retries: {{ .max_retries | default 3 }} + connect_timeout: {{ .connect_timeout | default "10s" }} + request_timeout: {{ .request_timeout | default "5s" }} + {{- end -}} + {{- else }} + backend: "filesystem" + filesystem: + dir: {{ .Values.loki.storage.filesystem.admin_api_directory }} + {{- end -}} +{{- end }} + +{{/* +Calculate the config from structured and unstructured text input +*/}} +{{- define "loki.calculatedConfig" -}} +{{ tpl (mergeOverwrite (tpl .Values.loki.config . | fromYaml) .Values.loki.structuredConfig | toYaml) . }} +{{- end }} + +{{/* +The volume to mount for loki configuration +*/}} +{{- define "loki.configVolume" -}} +{{- if eq .Values.loki.configStorageType "Secret" -}} +secret: + secretName: {{ tpl .Values.loki.configObjectName . }} +{{- else -}} +configMap: + name: {{ tpl .Values.loki.configObjectName . }} + items: + - key: "config.yaml" + path: "config.yaml" +{{- end -}} +{{- end -}} + +{{/* +Memcached Docker image +*/}} +{{- define "loki.memcachedImage" -}} +{{- $dict := dict "service" .Values.memcached.image "global" .Values.global.image -}} +{{- include "loki.image" $dict -}} +{{- end }} + +{{/* +Memcached Exporter Docker image +*/}} +{{- define "loki.memcachedExporterImage" -}} +{{- $dict := dict "service" .Values.memcachedExporter.image "global" .Values.global.image -}} +{{- include "loki.image" $dict -}} +{{- end }} + +{{/* Allow KubeVersion to be overridden. */}} +{{- define "loki.kubeVersion" -}} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "loki.ingress.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" (include "loki.kubeVersion" .)) -}} + {{- print "networking.k8s.io/v1" -}} + {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "extensions/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return if ingress is stable. +*/}} +{{- define "loki.ingress.isStable" -}} + {{- eq (include "loki.ingress.apiVersion" .) "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return if ingress supports ingressClassName. +*/}} +{{- define "loki.ingress.supportsIngressClassName" -}} + {{- or (eq (include "loki.ingress.isStable" .) "true") (and (eq (include "loki.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "loki.kubeVersion" .))) -}} +{{- end -}} + +{{/* +Return if ingress supports pathType. +*/}} +{{- define "loki.ingress.supportsPathType" -}} + {{- or (eq (include "loki.ingress.isStable" .) "true") (and (eq (include "loki.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "loki.kubeVersion" .))) -}} +{{- end -}} + +{{/* +Generate list of ingress service paths based on deployment type +*/}} +{{- define "loki.ingress.servicePaths" -}} +{{- if (eq (include "loki.deployment.isSingleBinary" .) "true") -}} +{{- include "loki.ingress.singleBinaryServicePaths" . }} +{{- else if (eq (include "loki.deployment.isDistributed" .) "true") -}} +{{- include "loki.ingress.distributedServicePaths" . }} +{{- else if and (eq (include "loki.deployment.isScalable" .) "true") (not .Values.read.legacyReadTarget ) -}} +{{- include "loki.ingress.scalableServicePaths" . }} +{{- else -}} +{{- include "loki.ingress.legacyScalableServicePaths" . }} +{{- end -}} +{{- end -}} + + +{{/* +Ingress service paths for distributed deployment +*/}} +{{- define "loki.ingress.distributedServicePaths" -}} +{{- $distributorServiceName := include "loki.distributorFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $distributorServiceName "paths" .Values.ingress.paths.distributor )}} +{{- $queryFrontendServiceName := include "loki.queryFrontendFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $queryFrontendServiceName "paths" .Values.ingress.paths.queryFrontend )}} +{{- $rulerServiceName := include "loki.rulerFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $rulerServiceName "paths" .Values.ingress.paths.ruler)}} +{{- end -}} + +{{/* +Ingress service paths for legacy simple scalable deployment when backend components were part of read component. +*/}} +{{- define "loki.ingress.scalableServicePaths" -}} +{{- $readServiceName := include "loki.readFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $readServiceName "paths" .Values.ingress.paths.queryFrontend )}} +{{- $writeServiceName := include "loki.writeFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $writeServiceName "paths" .Values.ingress.paths.distributor )}} +{{- $backendServiceName := include "loki.backendFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $backendServiceName "paths" .Values.ingress.paths.ruler )}} +{{- end -}} + +{{/* +Ingress service paths for legacy simple scalable deployment +*/}} +{{- define "loki.ingress.legacyScalableServicePaths" -}} +{{- $readServiceName := include "loki.readFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $readServiceName "paths" .Values.ingress.paths.queryFrontend )}} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $readServiceName "paths" .Values.ingress.paths.ruler )}} +{{- $writeServiceName := include "loki.writeFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $writeServiceName "paths" .Values.ingress.paths.distributor )}} +{{- end -}} + +{{/* +Ingress service paths for single binary deployment +*/}} +{{- define "loki.ingress.singleBinaryServicePaths" -}} +{{- $serviceName := include "loki.singleBinaryFullname" . }} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $serviceName "paths" .Values.ingress.paths.distributor )}} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $serviceName "paths" .Values.ingress.paths.queryFrontend )}} +{{- include "loki.ingress.servicePath" (dict "ctx" . "serviceName" $serviceName "paths" .Values.ingress.paths.ruler )}} +{{- end -}} + +{{/* +Ingress service path helper function +Params: + ctx = . context + serviceName = fully qualified k8s service name + paths = list of url paths to allow ingress for +*/}} +{{- define "loki.ingress.servicePath" -}} +{{- $ingressApiIsStable := eq (include "loki.ingress.isStable" .ctx) "true" -}} +{{- $ingressSupportsPathType := eq (include "loki.ingress.supportsPathType" .ctx) "true" -}} +{{- range .paths }} +- path: {{ . }} + {{- if $ingressSupportsPathType }} + pathType: Prefix + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $.serviceName }} + port: + number: {{ $.ctx.Values.loki.server.http_listen_port }} + {{- else }} + serviceName: {{ $.serviceName }} + servicePort: {{ $.ctx.Values.loki.server.http_listen_port }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the service endpoint including port for MinIO. +*/}} +{{- define "loki.minio" -}} +{{- if .Values.minio.enabled -}} +{{- .Values.minio.address | default (printf "%s-%s.%s.svc:%s" .Release.Name "minio" .Release.Namespace (.Values.minio.service.port | toString)) -}} +{{- end -}} +{{- end -}} + +{{/* Determine if deployment is using object storage */}} +{{- define "loki.isUsingObjectStorage" -}} +{{- or (eq .Values.loki.storage.type "gcs") (eq .Values.loki.storage.type "s3") (eq .Values.loki.storage.type "azure") (eq .Values.loki.storage.type "swift") (eq .Values.loki.storage.type "alibabacloud") -}} +{{- end -}} + +{{/* Configure the correct name for the memberlist service */}} +{{- define "loki.memberlist" -}} +{{ include "loki.name" . }}-memberlist +{{- end -}} + +{{/* Determine the public host for the Loki cluster */}} +{{- define "loki.host" -}} +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- $url := printf "%s.%s.svc.%s.:%s" (include "loki.gatewayFullname" .) .Release.Namespace .Values.global.clusterDomain (.Values.gateway.service.port | toString) }} +{{- if and $isSingleBinary (not .Values.gateway.enabled) }} + {{- $url = printf "%s.%s.svc.%s.:%s" (include "loki.singleBinaryFullname" .) .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} +{{- end }} +{{- printf "%s" $url -}} +{{- end -}} + +{{/* Determine the public endpoint for the Loki cluster */}} +{{- define "loki.address" -}} +{{- printf "http://%s" (include "loki.host" . ) -}} +{{- end -}} + +{{/* Name of the cluster */}} +{{- define "loki.clusterName" -}} +{{- $name := .Values.enterprise.cluster_name | default .Release.Name }} +{{- printf "%s" $name -}} +{{- end -}} + +{{/* Name of kubernetes secret to persist GEL admin token to */}} +{{- define "enterprise-logs.adminTokenSecret" }} +{{- .Values.enterprise.adminToken.secret | default (printf "%s-admin-token" (include "loki.name" . )) -}} +{{- end -}} + +{{/* Prefix for provisioned secrets created for each provisioned tenant */}} +{{- define "enterprise-logs.provisionedSecretPrefix" }} +{{- .Values.enterprise.provisioner.provisionedSecretPrefix | default (printf "%s-provisioned" (include "loki.name" . )) -}} +{{- end -}} + +{{/* Name of kubernetes secret to persist canary credentials in */}} +{{- define "enterprise-logs.selfMonitoringTenantSecret" }} +{{- .Values.enterprise.canarySecret | default (printf "%s-%s" (include "enterprise-logs.provisionedSecretPrefix" . ) .Values.monitoring.selfMonitoring.tenant.name) -}} +{{- end -}} + +{{/* Snippet for the nginx file used by gateway */}} +{{- define "loki.nginxFile" }} +worker_processes 5; ## Default: 1 +error_log /dev/stderr; +pid /tmp/nginx.pid; +worker_rlimit_nofile 8192; + +events { + worker_connections 4096; ## Default: 1024 +} + +http { + client_body_temp_path /tmp/client_temp; + proxy_temp_path /tmp/proxy_temp_path; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + client_max_body_size {{ .Values.gateway.nginxConfig.clientMaxBodySize }}; + + proxy_read_timeout 600; ## 10 minutes + proxy_send_timeout 600; + proxy_connect_timeout 600; + + proxy_http_version 1.1; + + default_type application/octet-stream; + log_format {{ .Values.gateway.nginxConfig.logFormat }} + + {{- if .Values.gateway.verboseLogging }} + access_log /dev/stderr main; + {{- else }} + + map $status $loggable { + ~^[23] 0; + default 1; + } + access_log /dev/stderr main if=$loggable; + {{- end }} + + sendfile on; + tcp_nopush on; + {{- if .Values.gateway.nginxConfig.resolver }} + resolver {{ .Values.gateway.nginxConfig.resolver }}; + {{- else }} + resolver {{ .Values.global.dnsService }}.{{ .Values.global.dnsNamespace }}.svc.{{ .Values.global.clusterDomain }}.; + {{- end }} + + {{- with .Values.gateway.nginxConfig.httpSnippet }} + {{- tpl . $ | nindent 2 }} + {{- end }} + + server { + {{- if (.Values.gateway.nginxConfig.ssl) }} + listen 8080 ssl; + {{- if .Values.gateway.nginxConfig.enableIPv6 }} + listen [::]:8080 ssl; + {{- end }} + {{- else }} + listen 8080; + {{- if .Values.gateway.nginxConfig.enableIPv6 }} + listen [::]:8080; + {{- end }} + {{- end }} + + {{- if .Values.gateway.basicAuth.enabled }} + auth_basic "Loki"; + auth_basic_user_file /etc/nginx/secrets/.htpasswd; + {{- end }} + + location = / { + return 200 'OK'; + auth_basic off; + } + + ######################################################## + # Configure backend targets + + {{- $backendHost := include "loki.backendFullname" .}} + {{- $readHost := include "loki.readFullname" .}} + {{- $writeHost := include "loki.writeFullname" .}} + + {{- if .Values.read.legacyReadTarget }} + {{- $backendHost = include "loki.readFullname" . }} + {{- end }} + + {{- $httpSchema := .Values.gateway.nginxConfig.schema }} + + {{- $writeUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $writeHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + {{- $readUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $readHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + {{- $backendUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $backendHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + + {{- if .Values.gateway.nginxConfig.customWriteUrl }} + {{- $writeUrl = .Values.gateway.nginxConfig.customWriteUrl }} + {{- end }} + {{- if .Values.gateway.nginxConfig.customReadUrl }} + {{- $readUrl = .Values.gateway.nginxConfig.customReadUrl }} + {{- end }} + {{- if .Values.gateway.nginxConfig.customBackendUrl }} + {{- $backendUrl = .Values.gateway.nginxConfig.customBackendUrl }} + {{- end }} + + {{- $singleBinaryHost := include "loki.singleBinaryFullname" . }} + {{- $singleBinaryUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $singleBinaryHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + + {{- $distributorHost := include "loki.distributorFullname" .}} + {{- $ingesterHost := include "loki.ingesterFullname" .}} + {{- $queryFrontendHost := include "loki.queryFrontendFullname" .}} + {{- $indexGatewayHost := include "loki.indexGatewayFullname" .}} + {{- $rulerHost := include "loki.rulerFullname" .}} + {{- $compactorHost := include "loki.compactorFullname" .}} + {{- $schedulerHost := include "loki.querySchedulerFullname" .}} + + + {{- $distributorUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $distributorHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) -}} + {{- $ingesterUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $ingesterHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + {{- $queryFrontendUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $queryFrontendHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + {{- $indexGatewayUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $indexGatewayHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + {{- $rulerUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $rulerHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + {{- $compactorUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $compactorHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + {{- $schedulerUrl := printf "%s://%s.%s.svc.%s:%s" $httpSchema $schedulerHost .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.http_listen_port | toString) }} + + {{- if eq (include "loki.deployment.isSingleBinary" .) "true"}} + {{- $distributorUrl = $singleBinaryUrl }} + {{- $ingesterUrl = $singleBinaryUrl }} + {{- $queryFrontendUrl = $singleBinaryUrl }} + {{- $indexGatewayUrl = $singleBinaryUrl }} + {{- $rulerUrl = $singleBinaryUrl }} + {{- $compactorUrl = $singleBinaryUrl }} + {{- $schedulerUrl = $singleBinaryUrl }} + {{- else if eq (include "loki.deployment.isScalable" .) "true"}} + {{- $distributorUrl = $writeUrl }} + {{- $ingesterUrl = $writeUrl }} + {{- $queryFrontendUrl = $readUrl }} + {{- $indexGatewayUrl = $backendUrl }} + {{- $rulerUrl = $backendUrl }} + {{- $compactorUrl = $backendUrl }} + {{- $schedulerUrl = $backendUrl }} + {{- end -}} + + # Distributor + location = /api/prom/push { + proxy_pass {{ $distributorUrl }}$request_uri; + } + location = /loki/api/v1/push { + proxy_pass {{ $distributorUrl }}$request_uri; + } + location = /distributor/ring { + proxy_pass {{ $distributorUrl }}$request_uri; + } + location = /otlp/v1/logs { + proxy_pass {{ $distributorUrl }}$request_uri; + } + + # Ingester + location = /flush { + proxy_pass {{ $ingesterUrl }}$request_uri; + } + location ^~ /ingester/ { + proxy_pass {{ $ingesterUrl }}$request_uri; + } + location = /ingester { + internal; # to suppress 301 + } + + # Ring + location = /ring { + proxy_pass {{ $ingesterUrl }}$request_uri; + } + + # MemberListKV + location = /memberlist { + proxy_pass {{ $ingesterUrl }}$request_uri; + } + + # Ruler + location = /ruler/ring { + proxy_pass {{ $rulerUrl }}$request_uri; + } + location = /api/prom/rules { + proxy_pass {{ $rulerUrl }}$request_uri; + } + location ^~ /api/prom/rules/ { + proxy_pass {{ $rulerUrl }}$request_uri; + } + location = /loki/api/v1/rules { + proxy_pass {{ $rulerUrl }}$request_uri; + } + location ^~ /loki/api/v1/rules/ { + proxy_pass {{ $rulerUrl }}$request_uri; + } + location = /prometheus/api/v1/alerts { + proxy_pass {{ $rulerUrl }}$request_uri; + } + location = /prometheus/api/v1/rules { + proxy_pass {{ $rulerUrl }}$request_uri; + } + + # Compactor + location = /compactor/ring { + proxy_pass {{ $compactorUrl }}$request_uri; + } + location = /loki/api/v1/delete { + proxy_pass {{ $compactorUrl }}$request_uri; + } + location = /loki/api/v1/cache/generation_numbers { + proxy_pass {{ $compactorUrl }}$request_uri; + } + + # IndexGateway + location = /indexgateway/ring { + proxy_pass {{ $indexGatewayUrl }}$request_uri; + } + + # QueryScheduler + location = /scheduler/ring { + proxy_pass {{ $schedulerUrl }}$request_uri; + } + + # Config + location = /config { + proxy_pass {{ $ingesterUrl }}$request_uri; + } + + {{- if and .Values.enterprise.enabled .Values.enterprise.adminApi.enabled }} + # Admin API + location ^~ /admin/api/ { + proxy_pass {{ $backendUrl }}$request_uri; + } + location = /admin/api { + internal; # to suppress 301 + } + {{- end }} + + + # QueryFrontend, Querier + location = /api/prom/tail { + proxy_pass {{ $queryFrontendUrl }}$request_uri; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + location = /loki/api/v1/tail { + proxy_pass {{ $queryFrontendUrl }}$request_uri; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + location ^~ /api/prom/ { + proxy_pass {{ $queryFrontendUrl }}$request_uri; + } + location = /api/prom { + internal; # to suppress 301 + } + location ^~ /loki/api/v1/ { + proxy_pass {{ $queryFrontendUrl }}$request_uri; + } + location = /loki/api/v1 { + internal; # to suppress 301 + } + + {{- with .Values.gateway.nginxConfig.serverSnippet }} + {{ . | nindent 4 }} + {{- end }} + } +} +{{- end }} + +{{/* Configure enableServiceLinks in pod */}} +{{- define "loki.enableServiceLinks" -}} +{{- if semverCompare ">=1.13-0" (include "loki.kubeVersion" .) -}} +{{- if or (.Values.loki.enableServiceLinks) (ne .Values.loki.enableServiceLinks false) -}} +enableServiceLinks: true +{{- else -}} +enableServiceLinks: false +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* Determine compactor address based on target configuration */}} +{{- define "loki.compactorAddress" -}} +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- $compactorAddress := include "loki.backendFullname" . -}} +{{- if and $isSimpleScalable .Values.read.legacyReadTarget -}} +{{/* 2 target configuration */}} +{{- $compactorAddress = include "loki.readFullname" . -}} +{{- else if $isSingleBinary -}} +{{/* single binary */}} +{{- $compactorAddress = include "loki.singleBinaryFullname" . -}} +{{/* distributed */}} +{{- else if $isDistributed -}} +{{- $compactorAddress = include "loki.compactorFullname" . -}} +{{- end -}} +{{- printf "http://%s:%s" $compactorAddress (.Values.loki.server.http_listen_port | toString) }} +{{- end }} + +{{/* Determine query-scheduler address */}} +{{- define "loki.querySchedulerAddress" -}} +{{- $schedulerAddress := ""}} +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +{{- $schedulerAddress = printf "%s.%s.svc.%s:%s" (include "loki.querySchedulerFullname" .) .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.grpc_listen_port | toString) -}} +{{- end -}} +{{- printf "%s" $schedulerAddress }} +{{- end }} + +{{/* Determine querier address */}} +{{- define "loki.querierAddress" -}} +{{- $querierAddress := "" }} +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +{{- $querierHost := include "loki.querierFullname" .}} +{{- $querierUrl := printf "http://%s.%s.svc.%s:3100" $querierHost .Release.Namespace .Values.global.clusterDomain }} +{{- $querierAddress = $querierUrl }} +{{- end -}} +{{- printf "%s" $querierAddress }} +{{- end }} + +{{/* Determine index-gateway address */}} +{{- define "loki.indexGatewayAddress" -}} +{{- $idxGatewayAddress := ""}} +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- $isScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if $isDistributed -}} +{{- $idxGatewayAddress = printf "dns+%s-headless.%s.svc.%s:%s" (include "loki.indexGatewayFullname" .) .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.grpc_listen_port | toString) -}} +{{- end -}} +{{- if $isScalable -}} +{{- $idxGatewayAddress = printf "dns+%s-headless.%s.svc.%s:%s" (include "loki.backendFullname" .) .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.grpc_listen_port | toString) -}} +{{- end -}} +{{- printf "%s" $idxGatewayAddress }} +{{- end }} + +{{/* Determine bloom-planner address */}} +{{- define "loki.bloomPlannerAddress" -}} +{{- $bloomPlannerAddress := ""}} +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- $isScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if $isDistributed -}} +{{- $bloomPlannerAddress = printf "%s-headless.%s.svc.%s:%s" (include "loki.bloomPlannerFullname" .) .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.grpc_listen_port | toString) -}} +{{- end -}} +{{- if $isScalable -}} +{{- $bloomPlannerAddress = printf "%s-headless.%s.svc.%s:%s" (include "loki.backendFullname" .) .Release.Namespace .Values.global.clusterDomain (.Values.loki.server.grpc_listen_port | toString) -}} +{{- end -}} +{{- printf "%s" $bloomPlannerAddress}} +{{- end }} + +{{/* Determine bloom-gateway address */}} +{{- define "loki.bloomGatewayAddresses" -}} +{{- $bloomGatewayAddresses := ""}} +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- $isScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if $isDistributed -}} +{{- $bloomGatewayAddresses = printf "dnssrvnoa+_grpc._tcp.%s-headless.%s.svc.%s" (include "loki.bloomGatewayFullname" .) .Release.Namespace .Values.global.clusterDomain -}} +{{- end -}} +{{- if $isScalable -}} +{{- $bloomGatewayAddresses = printf "dnssrvnoa+_grpc._tcp.%s-headless.%s.svc.%s" (include "loki.backendFullname" .) .Release.Namespace .Values.global.clusterDomain -}} +{{- end -}} +{{- printf "%s" $bloomGatewayAddresses}} +{{- end }} + +{{- define "loki.config.checksum" -}} +checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodDisruptionBudget. +*/}} +{{- define "loki.pdb.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">=1.21-0" (include "loki.kubeVersion" .)) -}} + {{- print "policy/v1" -}} + {{- else -}} + {{- print "policy/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the object store type for use with the test schema. +*/}} +{{- define "loki.testSchemaObjectStore" -}} + {{- if .Values.minio.enabled -}} + s3 + {{- else -}} + filesystem + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for HorizontalPodAutoscaler. +*/}} +{{- define "loki.hpa.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "autoscaling/v2") (semverCompare ">= 1.19-0" (include "loki.kubeVersion" .)) -}} + {{- print "autoscaling/v2" -}} + {{- else if .Capabilities.APIVersions.Has "autoscaling/v2beta2" -}} + {{- print "autoscaling/v2beta2" -}} + {{- else -}} + {{- print "autoscaling/v2beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +compute a ConfigMap or Secret checksum only based on its .data content. +This function needs to be called with a context object containing the following keys: +- ctx: the current Helm context (what '.' is at the call site) +- name: the file name of the ConfigMap or Secret +*/}} +{{- define "loki.configMapOrSecretContentHash" -}} +{{ get (include (print .ctx.Template.BasePath .name) .ctx | fromYaml) "data" | toYaml | sha256sum }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/admin-api/_helpers.yaml b/utils/assets/charts/loki/templates/admin-api/_helpers.yaml new file mode 100644 index 0000000..e13ff8a --- /dev/null +++ b/utils/assets/charts/loki/templates/admin-api/_helpers.yaml @@ -0,0 +1,24 @@ +{{/* +adminApi fullname +*/}} +{{- define "enterprise-logs.adminApiFullname" -}} +{{ include "loki.fullname" . }}-admin-api +{{- end }} + +{{/* +adminApi common labels +*/}} +{{- define "enterprise-logs.adminApiLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: admin-api +target: admin-api +{{- end }} + +{{/* +adminApi selector labels +*/}} +{{- define "enterprise-logs.adminApiSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: admin-api +target: admin-api +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/loki/templates/admin-api/deployment-admin-api.yaml b/utils/assets/charts/loki/templates/admin-api/deployment-admin-api.yaml new file mode 100644 index 0000000..c5e97dd --- /dev/null +++ b/utils/assets/charts/loki/templates/admin-api/deployment-admin-api.yaml @@ -0,0 +1,176 @@ +{{- if .Values.enterprise.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "enterprise-logs.adminApiFullname" . }} + labels: + {{- include "enterprise-logs.adminApiLabels" . | nindent 4 }} + {{- with .Values.adminApi.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + app.kubernetes.io/part-of: memberlist + annotations: + {{- with .Values.adminApi.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.adminApi.replicas }} + selector: + matchLabels: + {{- include "enterprise-logs.adminApiSelectorLabels" . | nindent 6 }} + strategy: + {{- toYaml .Values.adminApi.strategy | nindent 4 }} + template: + metadata: + labels: + {{- include "enterprise-logs.adminApiSelectorLabels" . | nindent 8 }} + {{- with .Values.adminApi.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + app.kubernetes.io/part-of: memberlist + annotations: + {{- if .Values.useExternalConfig }} + checksum/config: {{ .Values.externalConfigVersion }} + {{- else }} + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- end}} + {{- with .Values.adminApi.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.adminApi.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ template "loki.serviceAccountName" . }} + {{- if .Values.adminApi.priorityClassName }} + priorityClassName: {{ .Values.adminApi.priorityClassName }} + {{- end }} + securityContext: + {{- toYaml .Values.adminApi.podSecurityContext | nindent 8 }} + initContainers: + # Taken from + # https://github.com/minio/charts/blob/a5c84bcbad884728bff5c9c23541f936d57a13b3/minio/templates/post-install-create-bucket-job.yaml + {{- if .Values.minio.enabled }} + - name: minio-mc + image: "{{ .Values.minio.mcImage.repository }}:{{ .Values.minio.mcImage.tag }}" + imagePullPolicy: {{ .Values.minio.mcImage.pullPolicy }} + command: ["/bin/sh", "/config/initialize"] + env: + - name: MINIO_ENDPOINT + value: {{ .Release.Name }}-minio + - name: MINIO_PORT + value: {{ .Values.minio.service.port | quote }} + volumeMounts: + - name: minio-configuration + mountPath: /config + {{- if .Values.minio.tls.enabled }} + - name: cert-secret-volume-mc + mountPath: {{ .Values.minio.configPathmc }}certs + {{ end }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.adminApi.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: admin-api + image: "{{ template "loki.image" . }}" + imagePullPolicy: {{ .Values.enterprise.image.pullPolicy }} + args: + - -target=admin-api + - -config.file=/etc/loki/config/config.yaml + {{- if .Values.minio.enabled }} + - -admin.client.backend-type=s3 + - -admin.client.s3.endpoint={{ template "loki.minio" . }} + - -admin.client.s3.bucket-name=enterprise-logs-admin + - -admin.client.s3.access-key-id={{ .Values.minio.accessKey }} + - -admin.client.s3.secret-access-key={{ .Values.minio.secretKey }} + - -admin.client.s3.insecure=true + {{- end }} + {{- range $key, $value := .Values.adminApi.extraArgs }} + - "-{{ $key }}={{ $value }}" + {{- end }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: license + mountPath: /etc/loki/license + - name: storage + mountPath: /data + {{- if .Values.adminApi.extraVolumeMounts }} + {{ toYaml .Values.adminApi.extraVolumeMounts | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + readinessProbe: + {{- toYaml .Values.adminApi.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.adminApi.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.adminApi.containerSecurityContext | nindent 12 }} + env: + {{- if .Values.adminApi.env }} + {{ toYaml .Values.adminApi.env | nindent 12 }} + {{- end }} + {{- with .Values.adminApi.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.adminApi.extraContainers }} + {{ toYaml . | nindent 8 }} + {{- end }} + nodeSelector: + {{- toYaml .Values.adminApi.nodeSelector | nindent 8 }} + affinity: + {{- toYaml .Values.adminApi.affinity | nindent 8 }} + tolerations: + {{- toYaml .Values.adminApi.tolerations | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.adminApi.terminationGracePeriodSeconds }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + - name: storage + emptyDir: {} + {{- if .Values.adminApi.extraVolumes }} + {{ toYaml .Values.adminApi.extraVolumes | nindent 8 }} + {{- end }} + {{- if .Values.minio.enabled }} + - name: minio-configuration + projected: + sources: + - configMap: + name: {{ .Release.Name }}-minio + - secret: + name: {{ .Release.Name }}-minio + {{- if .Values.minio.tls.enabled }} + - name: cert-secret-volume-mc + secret: + secretName: {{ .Values.minio.tls.certSecret }} + items: + - key: {{ .Values.minio.tls.publicCrt }} + path: CAs/public.crt + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/admin-api/service-admin-api.yaml b/utils/assets/charts/loki/templates/admin-api/service-admin-api.yaml new file mode 100644 index 0000000..c7daa27 --- /dev/null +++ b/utils/assets/charts/loki/templates/admin-api/service-admin-api.yaml @@ -0,0 +1,28 @@ +{{- if .Values.enterprise.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "enterprise-logs.adminApiFullname" . }} + labels: + {{- include "enterprise-logs.adminApiLabels" . | nindent 4 }} + {{- with .Values.adminApi.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.adminApi.service.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: 3100 + protocol: TCP + targetPort: http-metrics + - name: grpc + port: 9095 + protocol: TCP + targetPort: grpc + selector: + {{- include "enterprise-logs.adminApiSelectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/loki/templates/backend/_helpers-backend.tpl b/utils/assets/charts/loki/templates/backend/_helpers-backend.tpl new file mode 100644 index 0000000..08f5f8f --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/_helpers-backend.tpl @@ -0,0 +1,32 @@ +{{/* +backend fullname +*/}} +{{- define "loki.backendFullname" -}} +{{ include "loki.name" . }}-backend +{{- end }} + +{{/* +backend common labels +*/}} +{{- define "loki.backendLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: backend +{{- end }} + +{{/* +backend selector labels +*/}} +{{- define "loki.backendSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: backend +{{- end }} + +{{/* +backend priority class name +*/}} +{{- define "loki.backendPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.backend.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/backend/clusterrole.yaml b/utils/assets/charts/loki/templates/backend/clusterrole.yaml new file mode 100644 index 0000000..36c8a0f --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/clusterrole.yaml @@ -0,0 +1,20 @@ +{{- if and (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + {{- include "loki.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "loki.fullname" . }}-clusterrole +{{- if .Values.sidecar.rules.enabled }} +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +{{- else }} +rules: [] +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/backend/clusterrolebinding.yaml b/utils/assets/charts/loki/templates/backend/clusterrolebinding.yaml new file mode 100644 index 0000000..92f86a4 --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/clusterrolebinding.yaml @@ -0,0 +1,25 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if (not .Values.rbac.namespaced) }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "loki.fullname" . }}-clusterrolebinding + labels: + {{- include "loki.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: + - kind: ServiceAccount + name: {{ template "loki.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole +{{- if (not .Values.rbac.useExistingRole) }} + name: {{ template "loki.fullname" . }}-clusterrole +{{- else }} + name: {{ .Values.rbac.useExistingRole }} +{{- end }} + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/utils/assets/charts/loki/templates/backend/hpa.yaml b/utils/assets/charts/loki/templates/backend/hpa.yaml new file mode 100644 index 0000000..ea834d6 --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/hpa.yaml @@ -0,0 +1,50 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- $autoscalingv2 := .Capabilities.APIVersions.Has "autoscaling/v2" -}} +{{- if and $isSimpleScalable (not .Values.read.legacyReadTarget ) ( .Values.backend.autoscaling.enabled ) }} +{{- if $autoscalingv2 }} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta1 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.backendFullname" . }} + labels: + {{- include "loki.backendLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "loki.backendFullname" . }} + minReplicas: {{ .Values.backend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.backend.autoscaling.maxReplicas }} + {{- with .Values.backend.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} + metrics: + {{- with .Values.backend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.backend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/backend/poddisruptionbudget-backend.yaml b/utils/assets/charts/loki/templates/backend/poddisruptionbudget-backend.yaml new file mode 100644 index 0000000..d8ce5b0 --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/poddisruptionbudget-backend.yaml @@ -0,0 +1,15 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (gt (int .Values.backend.replicas) 1) (not .Values.read.legacyReadTarget ) }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.backendFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.backendLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.backendSelectorLabels" . | nindent 6 }} + maxUnavailable: 1 +{{- end }} diff --git a/utils/assets/charts/loki/templates/backend/query-scheduler-discovery.yaml b/utils/assets/charts/loki/templates/backend/query-scheduler-discovery.yaml new file mode 100644 index 0000000..4c357e5 --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/query-scheduler-discovery.yaml @@ -0,0 +1,34 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (not .Values.read.legacyReadTarget ) }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.querySchedulerFullname" . }}-discovery + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.backendSelectorLabels" . | nindent 4 }} + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.backend.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + selector: + {{- include "loki.backendSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/backend/service-backend-headless.yaml b/utils/assets/charts/loki/templates/backend/service-backend-headless.yaml new file mode 100644 index 0000000..0755be6 --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/service-backend-headless.yaml @@ -0,0 +1,40 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (not .Values.read.legacyReadTarget ) }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.backendFullname" . }}-headless + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.backendSelectorLabels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.backend.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + variant: headless + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.backend.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + selector: + {{- include "loki.backendSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/backend/service-backend.yaml b/utils/assets/charts/loki/templates/backend/service-backend.yaml new file mode 100644 index 0000000..cd1bd3b --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/service-backend.yaml @@ -0,0 +1,37 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (not .Values.read.legacyReadTarget ) }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.backendFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.backendLabels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.backend.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.backend.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + selector: + {{- include "loki.backendSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/backend/statefulset-backend.yaml b/utils/assets/charts/loki/templates/backend/statefulset-backend.yaml new file mode 100644 index 0000000..bf2e18d --- /dev/null +++ b/utils/assets/charts/loki/templates/backend/statefulset-backend.yaml @@ -0,0 +1,287 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (not .Values.read.legacyReadTarget ) }} +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.backendFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.backendLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- if or (not (empty .Values.loki.annotations)) (not (empty .Values.backend.annotations))}} + annotations: + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.backend.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: +{{- if not .Values.backend.autoscaling.enabled }} + {{- if eq .Values.deploymentMode "SingleBinary" }} + replicas: 0 + {{- else }} + replicas: {{ .Values.backend.replicas }} + {{- end }} +{{- end }} + podManagementPolicy: {{ .Values.backend.podManagementPolicy }} + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ include "loki.backendFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.backend.persistence.enableStatefulSetAutoDeletePVC) (.Values.backend.persistence.volumeClaimsEnabled) }} + {{/* + Data on the backend nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: Delete + whenScaled: Delete + {{- end }} + selector: + matchLabels: + {{- include "loki.backendSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.backend.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.backendSelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.backend.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.backend.selectorLabels }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + app.kubernetes.io/part-of: memberlist + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.backendPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.backend.terminationGracePeriodSeconds }} + {{- if .Values.backend.initContainers }} + initContainers: + {{- with .Values.backend.initContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + containers: + {{- if .Values.sidecar.rules.enabled }} + - name: loki-sc-rules + {{- if .Values.sidecar.image.sha }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.image.pullPolicy }} + env: + - name: METHOD + value: {{ .Values.sidecar.rules.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.rules.label }}" + {{- if .Values.sidecar.rules.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.rules.labelValue }} + {{- end }} + - name: FOLDER + value: "{{ .Values.sidecar.rules.folder }}" + - name: RESOURCE + value: {{ quote .Values.sidecar.rules.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- if .Values.sidecar.rules.searchNamespace }} + - name: NAMESPACE + value: "{{ .Values.sidecar.rules.searchNamespace | join "," }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.rules.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.rules.script }}" + {{- end }} + {{- if .Values.sidecar.rules.watchServerTimeout }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.rules.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.rules.watchClientTimeout }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.rules.watchClientTimeout }}" + {{- end }} + {{- if .Values.sidecar.rules.logLevel }} + - name: LOG_LEVEL + value: "{{ .Values.sidecar.rules.logLevel }}" + {{- end }} + {{- if .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml .Values.sidecar.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml .Values.sidecar.readinessProbe | nindent 12 }} + {{- end }} + {{- if .Values.sidecar.resources }} + resources: + {{- toYaml .Values.sidecar.resources | nindent 12 }} + {{- end }} + {{- if .Values.sidecar.securityContext }} + securityContext: + {{- toYaml .Values.sidecar.securityContext | nindent 12 }} + {{- end }} + volumeMounts: + - name: sc-rules-volume + mountPath: {{ .Values.sidecar.rules.folder | quote }} + {{- end}} + - name: loki + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target={{ .Values.backend.targetModule }} + - -legacy-read-mode=false + {{- with .Values.backend.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.loki.server.http_listen_port }} + protocol: TCP + - name: grpc + containerPort: {{ .Values.loki.server.grpc_listen_port }} + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.backend.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.backend.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: tmp + mountPath: /tmp + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end}} + {{- if .Values.sidecar.rules.enabled }} + - name: sc-rules-volume + mountPath: {{ .Values.sidecar.rules.folder | quote }} + {{- end}} + {{- with .Values.backend.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.backend.resources | nindent 12 }} + {{- with .Values.backend.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.backend.dnsConfig }} + dnsConfig: + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.backend.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.backend.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.backend.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: tmp + emptyDir: {} + {{- if not .Values.backend.persistence.volumeClaimsEnabled }} + - name: data + {{- toYaml .Values.backend.persistence.dataVolumeParameters | nindent 10 }} + {{- end}} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- if .Values.sidecar.rules.enabled }} + - name: sc-rules-volume + {{- if .Values.sidecar.rules.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.rules.sizeLimit }} + {{- else }} + emptyDir: {} + {{- end -}} + {{- end -}} + {{- with .Values.backend.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.backend.persistence.volumeClaimsEnabled }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + {{- with .Values.backend.persistence.annotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .Values.backend.persistence.storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .Values.backend.persistence.size | quote }} + {{- with .Values.backend.persistence.selector }} + selector: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/bloom-builder/_helpers-bloom-builder.tpl b/utils/assets/charts/loki/templates/bloom-builder/_helpers-bloom-builder.tpl new file mode 100644 index 0000000..46359df --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-builder/_helpers-bloom-builder.tpl @@ -0,0 +1,32 @@ +{{/* +bloom-builder fullname +*/}} +{{- define "loki.bloomBuilderFullname" -}} +{{ include "loki.fullname" . }}-bloom-builder +{{- end }} + +{{/* +bloom-builder common labels +*/}} +{{- define "loki.bloomBuilderLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: bloom-builder +{{- end }} + +{{/* +bloom-builder selector labels +*/}} +{{- define "loki.bloomBuilderSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: bloom-builder +{{- end }} + +{{/* +bloom-builder priority class name +*/}} +{{- define "loki.bloomBuilderPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.bloomBuilder.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/bloom-builder/deployment-bloom-builder.yaml b/utils/assets/charts/loki/templates/bloom-builder/deployment-bloom-builder.yaml new file mode 100644 index 0000000..c04b3ae --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-builder/deployment-bloom-builder.yaml @@ -0,0 +1,150 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if (and $isDistributed (gt (int .Values.bloomPlanner.replicas) 0)) -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.bloomBuilderFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomBuilderLabels" . | nindent 4 }} + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.bloomBuilder.autoscaling.enabled }} + replicas: {{ .Values.bloomBuilder.replicas }} +{{- end }} + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.bloomBuilderSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomBuilder.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.bloomBuilderSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomBuilder.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomBuilder.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.bloomBuilderPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.bloomBuilder.terminationGracePeriodSeconds }} + containers: + - name: bloom-builder + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.bloomBuilder.command }} + command: + - {{ coalesce .Values.bloomBuilder.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=bloom-builder + {{- with .Values.bloomBuilder.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.bloomBuilder.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.bloomBuilder.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + - name: temp + mountPath: /tmp + - name: data + mountPath: /var/loki + {{- with .Values.bloomBuilder.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.bloomBuilder.resources | nindent 12 }} + {{- if .Values.bloomBuilder.extraContainers }} + {{- toYaml .Values.bloomBuilder.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.bloomBuilder.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomBuilder.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomBuilder.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + - name: temp + emptyDir: {} + - name: data + emptyDir: {} + {{- with .Values.bloomBuilder.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-builder/hpa.yaml b/utils/assets/charts/loki/templates/bloom-builder/hpa.yaml new file mode 100644 index 0000000..2b04647 --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-builder/hpa.yaml @@ -0,0 +1,55 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.bloomBuilder.autoscaling.enabled }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.bloomBuilderFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomBuilderLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "loki.bloomBuilderFullname" . }} + minReplicas: {{ .Values.bloomBuilder.autoscaling.minReplicas }} + maxReplicas: {{ .Values.bloomBuilder.autoscaling.maxReplicas }} + metrics: + {{- with .Values.bloomBuilder.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.bloomBuilder.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.bloomBuilder.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.bloomBuilder.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.bloomBuilder.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.bloomBuilder.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/bloom-builder/poddisruptionbudget-bloom-builder.yaml b/utils/assets/charts/loki/templates/bloom-builder/poddisruptionbudget-bloom-builder.yaml new file mode 100644 index 0000000..e66d762 --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-builder/poddisruptionbudget-bloom-builder.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.bloomBuilder.replicas) 1) }} +{{- if kindIs "invalid" .Values.bloomBuilder.maxUnavailable }} +{{- fail "`.Values.bloomBuilder.maxUnavailable` must be set when `.Values.bloomBuilder.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.bloomBuilderFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomBuilderLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.bloomBuilderSelectorLabels" . | nindent 6 }} + {{- with .Values.bloomBuilder.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/bloom-builder/service-bloom-builder-headless.yaml b/utils/assets/charts/loki/templates/bloom-builder/service-bloom-builder-headless.yaml new file mode 100644 index 0000000..9389252 --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-builder/service-bloom-builder-headless.yaml @@ -0,0 +1,46 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if (and $isDistributed (or (gt (int .Values.bloomBuilder.replicas) 0)) .Values.bloomBuilder.autoscaling.enabled) -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.bloomBuilderFullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomBuilderLabels" . | nindent 4 }} + {{- with .Values.bloomBuilder.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.bloomBuilder.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + clusterIP: None + type: ClusterIP + publishNotReadyAddresses: true + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.bloomBuilder.appProtocol.grpc }} + appProtocol: {{ .Values.bloomBuilder.appProtocol.grpc }} + {{- end }} + - name: grpclb + port: 9096 + targetPort: grpc + protocol: TCP + {{- if .Values.bloomBuilder.appProtocol.grpc }} + appProtocol: {{ .Values.bloomBuilder.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.bloomBuilderSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-builder/service-bloom-builder.yaml b/utils/assets/charts/loki/templates/bloom-builder/service-bloom-builder.yaml new file mode 100644 index 0000000..b3debb0 --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-builder/service-bloom-builder.yaml @@ -0,0 +1,44 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if (and $isDistributed (gt (int .Values.bloomBuilder.replicas) 0)) -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.bloomBuilderFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomBuilderLabels" . | nindent 4 }} + {{- with .Values.bloomBuilder.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.bloomBuilder.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + publishNotReadyAddresses: true + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.bloomBuilder.appProtocol.grpc }} + appProtocol: {{ .Values.bloomBuilder.appProtocol.grpc }} + {{- end }} + - name: grpclb + port: 9096 + targetPort: grpc + protocol: TCP + {{- if .Values.bloomBuilder.appProtocol.grpc }} + appProtocol: {{ .Values.bloomBuilder.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.bloomBuilderSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-gateway/_helpers-bloom-gateway.tpl b/utils/assets/charts/loki/templates/bloom-gateway/_helpers-bloom-gateway.tpl new file mode 100644 index 0000000..f0cef4f --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-gateway/_helpers-bloom-gateway.tpl @@ -0,0 +1,58 @@ +{{/* +bloom gateway fullname +*/}} +{{- define "loki.bloomGatewayFullname" -}} +{{ include "loki.fullname" . }}-bloom-gateway +{{- end }} + +{{/* +bloom gateway common labels +*/}} +{{- define "loki.bloomGatewayLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: bloom-gateway +{{- end }} + +{{/* +bloom gateway selector labels +*/}} +{{- define "loki.bloomGatewaySelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: bloom-gateway +{{- end }} + +{{/* +bloom gateway readinessProbe +*/}} +{{- define "loki.bloomGateway.readinessProbe" -}} +{{- with .Values.bloomGateway.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- else }} +{{- with .Values.loki.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +bloom gateway priority class name +*/}} +{{- define "loki.bloomGatewayPriorityClassName" }} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.bloomGateway.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} + +{{/* +Create the name of the bloom gateway service account +*/}} +{{- define "loki.bloomGatewayServiceAccountName" -}} +{{- if .Values.bloomGateway.serviceAccount.create -}} + {{ default (print (include "loki.serviceAccountName" .) "-bloom-gateway") .Values.bloomGateway.serviceAccount.name }} +{{- else -}} + {{ default (include "loki.serviceAccountName" .) .Values.bloomGateway.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-gateway/service-bloom-gateway-headless.yaml b/utils/assets/charts/loki/templates/bloom-gateway/service-bloom-gateway-headless.yaml new file mode 100644 index 0000000..852e4cb --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-gateway/service-bloom-gateway-headless.yaml @@ -0,0 +1,39 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +{{- if (gt (int .Values.bloomGateway.replicas) 0) -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.bloomGatewayFullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomGatewaySelectorLabels" . | nindent 4 }} + {{- with .Values.bloomGateway.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.bloomGateway.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.bloomGateway.appProtocol.grpc }} + appProtocol: {{ .Values.bloomGateway.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.bloomGatewaySelectorLabels" . | nindent 4 }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-gateway/statefulset-bloom-gateway.yaml b/utils/assets/charts/loki/templates/bloom-gateway/statefulset-bloom-gateway.yaml new file mode 100644 index 0000000..747642b --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-gateway/statefulset-bloom-gateway.yaml @@ -0,0 +1,181 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if (and $isDistributed (gt (int .Values.bloomGateway.replicas) 0)) -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.bloomGatewayFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomGatewayLabels" . | nindent 4 }} + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.bloomGateway.replicas }} + podManagementPolicy: Parallel + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ include "loki.bloomGatewayFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.bloomGateway.persistence.enableStatefulSetAutoDeletePVC) }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.bloomGateway.persistence.whenDeleted }} + whenScaled: {{ .Values.bloomGateway.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.bloomGatewaySelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomGateway.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.bloomGatewaySelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomGateway.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomGateway.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.bloomGatewayPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.bloomGateway.terminationGracePeriodSeconds }} + {{- with .Values.bloomGateway.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: bloom-gateway + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.bloomGateway.command }} + command: + - {{ coalesce .Values.bloomGateway.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=bloom-gateway + {{- with .Values.bloomGateway.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.bloomGateway.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.bloomGateway.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.bloomGateway.readinessProbe" . | nindent 10 }} + volumeMounts: + - name: temp + mountPath: /tmp + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.bloomGateway.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.bloomGateway.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.bloomGateway.extraContainers }} + {{- toYaml .Values.bloomGateway.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.bloomGateway.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomGateway.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomGateway.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: temp + emptyDir: {} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- if not .Values.bloomGateway.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- with .Values.bloomGateway.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.bloomGateway.persistence.enabled }} + volumeClaimTemplates: + {{- range .Values.bloomGateway.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-planner/_helpers-bloom-planner.tpl b/utils/assets/charts/loki/templates/bloom-planner/_helpers-bloom-planner.tpl new file mode 100644 index 0000000..a4a8c6e --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-planner/_helpers-bloom-planner.tpl @@ -0,0 +1,58 @@ +{{/* +bloom planner fullname +*/}} +{{- define "loki.bloomPlannerFullname" -}} +{{ include "loki.fullname" . }}-bloom-planner +{{- end }} + +{{/* +bloom planner common labels +*/}} +{{- define "loki.bloomPlannerLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: bloom-planner +{{- end }} + +{{/* +bloom planner selector labels +*/}} +{{- define "loki.bloomPlannerSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: bloom-planner +{{- end }} + +{{/* +bloom planner readinessProbe +*/}} +{{- define "loki.bloomPlanner.readinessProbe" -}} +{{- with .Values.bloomPlanner.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- else }} +{{- with .Values.loki.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +bloom planner priority class name +*/}} +{{- define "loki.bloomPlannerPriorityClassName" }} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.bloomPlanner.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} + +{{/* +Create the name of the bloom planner service account +*/}} +{{- define "loki.bloomPlannerServiceAccountName" -}} +{{- if .Values.bloomPlanner.serviceAccount.create -}} + {{ default (print (include "loki.serviceAccountName" .) "-bloom-planner") .Values.bloomPlanner.serviceAccount.name }} +{{- else -}} + {{ default (include "loki.serviceAccountName" .) .Values.bloomPlanner.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-planner/service-bloom-planner-headless.yaml b/utils/assets/charts/loki/templates/bloom-planner/service-bloom-planner-headless.yaml new file mode 100644 index 0000000..78e2633 --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-planner/service-bloom-planner-headless.yaml @@ -0,0 +1,37 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if (and $isDistributed (gt (int .Values.bloomPlanner.replicas) 0)) -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.bloomPlannerFullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomPlannerSelectorLabels" . | nindent 4 }} + {{- with .Values.bloomPlanner.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.bloomPlanner.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.bloomPlanner.appProtocol.grpc }} + appProtocol: {{ .Values.bloomPlanner.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.bloomPlannerSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/bloom-planner/statefulset-bloom-planner.yaml b/utils/assets/charts/loki/templates/bloom-planner/statefulset-bloom-planner.yaml new file mode 100644 index 0000000..d134af3 --- /dev/null +++ b/utils/assets/charts/loki/templates/bloom-planner/statefulset-bloom-planner.yaml @@ -0,0 +1,181 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if (and $isDistributed (gt (int .Values.bloomPlanner.replicas) 0)) -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.bloomPlannerFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.bloomPlannerLabels" . | nindent 4 }} + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.bloomPlanner.replicas }} + podManagementPolicy: Parallel + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ include "loki.bloomPlannerFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.bloomPlanner.persistence.enableStatefulSetAutoDeletePVC) }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.bloomPlanner.persistence.whenDeleted }} + whenScaled: {{ .Values.bloomPlanner.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.bloomPlannerSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomPlanner.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.bloomPlannerSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomPlanner.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomPlanner.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.bloomPlannerPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.bloomPlanner.terminationGracePeriodSeconds }} + {{- with .Values.bloomPlanner.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: bloom-planner + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.bloomPlanner.command }} + command: + - {{ coalesce .Values.bloomPlanner.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=bloom-planner + {{- with .Values.bloomPlanner.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.bloomPlanner.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.bloomPlanner.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.bloomPlanner.readinessProbe" . | nindent 10 }} + volumeMounts: + - name: temp + mountPath: /tmp + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.bloomPlanner.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.bloomPlanner.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.bloomPlanner.extraContainers }} + {{- toYaml .Values.bloomPlanner.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.bloomPlanner.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomPlanner.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bloomPlanner.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: temp + emptyDir: {} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- if not .Values.bloomPlanner.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- with .Values.bloomPlanner.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.bloomPlanner.persistence.enabled }} + volumeClaimTemplates: + {{- range .Values.bloomPlanner.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/chunks-cache/poddisruptionbudget-chunks-cache.yaml b/utils/assets/charts/loki/templates/chunks-cache/poddisruptionbudget-chunks-cache.yaml new file mode 100644 index 0000000..da95adf --- /dev/null +++ b/utils/assets/charts/loki/templates/chunks-cache/poddisruptionbudget-chunks-cache.yaml @@ -0,0 +1,16 @@ +{{- if .Values.chunksCache.enabled }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.fullname" . }}-memcached-chunks-cache + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: memcached-chunks-cache +spec: + selector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: memcached-chunks-cache + maxUnavailable: 1 +{{- end -}} diff --git a/utils/assets/charts/loki/templates/chunks-cache/service-chunks-cache-headless.yaml b/utils/assets/charts/loki/templates/chunks-cache/service-chunks-cache-headless.yaml new file mode 100644 index 0000000..dc2ccd4 --- /dev/null +++ b/utils/assets/charts/loki/templates/chunks-cache/service-chunks-cache-headless.yaml @@ -0,0 +1 @@ +{{- include "loki.memcached.service" (dict "ctx" $ "valuesSection" "chunksCache" "component" "chunks-cache" ) }} diff --git a/utils/assets/charts/loki/templates/chunks-cache/statefulset-chunks-cache.yaml b/utils/assets/charts/loki/templates/chunks-cache/statefulset-chunks-cache.yaml new file mode 100644 index 0000000..6a54c57 --- /dev/null +++ b/utils/assets/charts/loki/templates/chunks-cache/statefulset-chunks-cache.yaml @@ -0,0 +1 @@ +{{- include "loki.memcached.statefulSet" (dict "ctx" $ "valuesSection" "chunksCache" "component" "chunks-cache" ) }} diff --git a/utils/assets/charts/loki/templates/ciliumnetworkpolicy.yaml b/utils/assets/charts/loki/templates/ciliumnetworkpolicy.yaml new file mode 100644 index 0000000..fbd2619 --- /dev/null +++ b/utils/assets/charts/loki/templates/ciliumnetworkpolicy.yaml @@ -0,0 +1,238 @@ +{{- if and (.Values.networkPolicy.enabled) (eq .Values.networkPolicy.flavor "cilium") }} +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-namespace-only + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + endpointSelector: {} + egress: + - toEndpoints: + - {} + ingress: + - fromEndpoints: + - {} + +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-dns + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + endpointSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + egress: + - toPorts: + - ports: + - port: dns + protocol: UDP + toEndpoints: + - namespaceSelector: {} + +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-ingress + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + endpointSelector: + matchExpressions: + - key: app.kubernetes.io/component + operator: In + values: + {{- if .Values.gateway.enabled }} + - gateway + {{- else }} + - read + - write + {{- end }} + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + ingress: + - toPorts: + - ports: + - port: http + protocol: TCP + {{- if .Values.networkPolicy.ingress.namespaceSelector }} + fromEndpoints: + - matchLabels: + {{- toYaml .Values.networkPolicy.ingress.namespaceSelector | nindent 8 }} + {{- if .Values.networkPolicy.ingress.podSelector }} + {{- toYaml .Values.networkPolicy.ingress.podSelector | nindent 8 }} + {{- end }} + {{- end }} + +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-ingress-metrics + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + endpointSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + ingress: + - toPorts: + - ports: + - port: http-metrics + protocol: TCP + {{- if .Values.networkPolicy.metrics.cidrs }} + {{- range $cidr := .Values.networkPolicy.metrics.cidrs }} + toCIDR: + - {{ $cidr }} + {{- end }} + {{- if .Values.networkPolicy.metrics.namespaceSelector }} + fromEndpoints: + - matchLabels: + {{- toYaml .Values.networkPolicy.metrics.namespaceSelector | nindent 8 }} + {{- if .Values.networkPolicy.metrics.podSelector }} + {{- toYaml .Values.networkPolicy.metrics.podSelector | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-alertmanager + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + endpointSelector: + matchLabels: + {{- include "loki.backendSelectorLabels" . | nindent 6 }} + egress: + - toPorts: + - ports: + - port: "{{ .Values.networkPolicy.alertmanager.port }}" + protocol: TCP + {{- if .Values.networkPolicy.alertmanager.namespaceSelector }} + toEndpoints: + - matchLabels: + {{- toYaml .Values.networkPolicy.alertmanager.namespaceSelector | nindent 8 }} + {{- if .Values.networkPolicy.alertmanager.podSelector }} + {{- toYaml .Values.networkPolicy.alertmanager.podSelector | nindent 8 }} + {{- end }} + {{- end }} + +{{- if .Values.networkPolicy.externalStorage.ports }} +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-external-storage + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + endpointSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + egress: + - toPorts: + - ports: + {{- range $port := .Values.networkPolicy.externalStorage.ports }} + - port: "{{ $port }}" + protocol: TCP + {{- end }} + {{- if .Values.networkPolicy.externalStorage.cidrs }} + {{- range $cidr := .Values.networkPolicy.externalStorage.cidrs }} + toCIDR: + - {{ $cidr }} + {{- end }} + {{- end }} +{{- end }} + +{{- if .Values.networkPolicy.egressWorld.enabled }} +{{- $global := . }} +{{- $componentsList := list "read" "write" "backend" }} +{{- if .Values.tableManager.enabled }} +{{- $componentsList = append $componentsList "table-manager" }} +{{- end }} +{{- range $component := $componentsList }} +{{- with $global }} +--- +apiVersion: "cilium.io/v2" +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-{{ $component }}-world-egress + namespace: {{ .Release.Namespace }} +spec: + endpointSelector: + matchLabels: + {{- if eq $component "read" }} + {{- include "loki.readSelectorLabels" . | nindent 6 }} + {{- else if eq $component "write" }} + {{- include "loki.writeSelectorLabels" . | nindent 6 }} + {{- else if eq $component "table-manager" }} + {{- include "loki.tableManagerSelectorLabels" . | nindent 6 }} + {{- else }} + {{- include "loki.backendSelectorLabels" . | nindent 6 }} + {{- end }} + egress: + - toEntities: + - world +{{- end }} +{{- end }} +{{- end }} + +{{- if .Values.networkPolicy.egressKubeApiserver.enabled }} +--- +apiVersion: "cilium.io/v2" +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-backend-kubeapiserver-egress + namespace: {{ .Release.Namespace }} +spec: + endpointSelector: + matchLabels: + {{- include "loki.backendSelectorLabels" . | nindent 6 }} + egress: + - toEntities: + - kube-apiserver +{{- end }} + +{{- end }} + +{{- if and .Values.networkPolicy.discovery.port (eq .Values.networkPolicy.flavor "cilium") }} +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-discovery + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + endpointSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + egress: + - toPorts: + - ports: + - port: "{{ .Values.networkPolicy.discovery.port }}" + protocol: TCP + {{- if .Values.networkPolicy.discovery.namespaceSelector }} + toEndpoints: + - matchLabels: + {{- toYaml .Values.networkPolicy.discovery.namespaceSelector | nindent 8 }} + {{- if .Values.networkPolicy.discovery.podSelector }} + {{- toYaml .Values.networkPolicy.discovery.podSelector | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/compactor/_helpers-compactor.tpl b/utils/assets/charts/loki/templates/compactor/_helpers-compactor.tpl new file mode 100644 index 0000000..75c21db --- /dev/null +++ b/utils/assets/charts/loki/templates/compactor/_helpers-compactor.tpl @@ -0,0 +1,81 @@ +{{/* +compactor fullname +*/}} +{{- define "loki.compactorFullname" -}} +{{ include "loki.fullname" . }}-compactor +{{- end }} + +{{/* +compactor common labels +*/}} +{{- define "loki.compactorLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: compactor +{{- end }} + +{{/* +compactor selector labels +*/}} +{{- define "loki.compactorSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: compactor +{{- end }} + +{{/* +compactor image +*/}} +{{- define "loki.compactorImage" -}} +{{- $dict := dict "loki" .Values.loki.image "service" .Values.compactor.image "global" .Values.global.image "defaultVersion" .Chart.AppVersion -}} +{{- include "loki.lokiImage" $dict -}} +{{- end }} + +{{/* +compactor readinessProbe +*/}} +{{- define "loki.compactor.readinessProbe" -}} +{{- with .Values.compactor.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- else }} +{{- with .Values.loki.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +compactor livenessProbe +*/}} +{{- define "loki.compactor.livenessProbe" -}} +{{- with .Values.compactor.livenessProbe }} +livenessProbe: + {{- toYaml . | nindent 2 }} +{{- else }} +{{- with .Values.loki.livenessProbe }} +livenessProbe: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +compactor priority class name +*/}} +{{- define "loki.compactorPriorityClassName" }} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.compactor.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} + +{{/* +Create the name of the compactor service account +*/}} +{{- define "loki.compactorServiceAccountName" -}} +{{- if .Values.compactor.serviceAccount.create -}} + {{ default (print (include "loki.serviceAccountName" .) "-compactor") .Values.compactor.serviceAccount.name }} +{{- else -}} + {{ default (include "loki.serviceAccountName" .) .Values.compactor.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/compactor/service-compactor.yaml b/utils/assets/charts/loki/templates/compactor/service-compactor.yaml new file mode 100644 index 0000000..f118b6c --- /dev/null +++ b/utils/assets/charts/loki/templates/compactor/service-compactor.yaml @@ -0,0 +1,38 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.compactorFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.compactor.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + app.kubernetes.io/component: compactor + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.compactor.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.compactor.appProtocol.grpc }} + appProtocol: {{ .Values.compactor.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: compactor +{{- end }} diff --git a/utils/assets/charts/loki/templates/compactor/statefulset-compactor.yaml b/utils/assets/charts/loki/templates/compactor/statefulset-compactor.yaml new file mode 100644 index 0000000..ded01be --- /dev/null +++ b/utils/assets/charts/loki/templates/compactor/statefulset-compactor.yaml @@ -0,0 +1,193 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.compactorFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.compactorLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.compactor.replicas }} + podManagementPolicy: Parallel + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ include "loki.compactorFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.compactor.persistence.enableStatefulSetAutoDeletePVC) }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.compactor.persistence.whenDeleted }} + whenScaled: {{ .Values.compactor.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.compactorSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compactor.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.compactorSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compactor.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.compactor.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compactor.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.compactorPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.compactor.terminationGracePeriodSeconds }} + {{- with .Values.compactor.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: compactor + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.compactor.command }} + command: + - {{ coalesce .Values.compactor.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=compactor + {{- with .Values.compactor.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.compactor.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.compactor.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.compactor.readinessProbe" . | nindent 10 }} + {{- include "loki.compactor.livenessProbe" . | nindent 10 }} + volumeMounts: + - name: temp + mountPath: /tmp + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.compactor.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.compactor.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.compactor.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.compactor.extraContainers }} + {{- toYaml .Values.compactor.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.compactor.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compactor.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compactor.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: temp + emptyDir: {} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- if not .Values.compactor.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- with .Values.compactor.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.compactor.persistence.enabled }} + volumeClaimTemplates: + {{- range .Values.compactor.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/config.yaml b/utils/assets/charts/loki/templates/config.yaml new file mode 100644 index 0000000..fe47590 --- /dev/null +++ b/utils/assets/charts/loki/templates/config.yaml @@ -0,0 +1,21 @@ +{{- if .Values.loki.generatedConfigObjectName -}} +apiVersion: v1 +{{- if eq .Values.loki.configStorageType "Secret" }} +kind: Secret +{{- else }} +kind: ConfigMap +{{- end }} +metadata: + name: {{ tpl .Values.loki.generatedConfigObjectName . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +{{- if eq .Values.loki.configStorageType "Secret" }} +data: + config.yaml: {{ include "loki.calculatedConfig" . | b64enc }} +{{- else }} +data: + config.yaml: | + {{ include "loki.calculatedConfig" . | nindent 4 }} +{{- end -}} +{{- end }} diff --git a/utils/assets/charts/loki/templates/distributor/_helpers-distributor.tpl b/utils/assets/charts/loki/templates/distributor/_helpers-distributor.tpl new file mode 100644 index 0000000..c23179e --- /dev/null +++ b/utils/assets/charts/loki/templates/distributor/_helpers-distributor.tpl @@ -0,0 +1,32 @@ +{{/* +distributor fullname +*/}} +{{- define "loki.distributorFullname" -}} +{{ include "loki.fullname" . }}-distributor +{{- end }} + +{{/* +distributor common labels +*/}} +{{- define "loki.distributorLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: distributor +{{- end }} + +{{/* +distributor selector labels +*/}} +{{- define "loki.distributorSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: distributor +{{- end }} + +{{/* +distributor priority class name +*/}} +{{- define "loki.distributorPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.distributor.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/distributor/deployment-distributor.yaml b/utils/assets/charts/loki/templates/distributor/deployment-distributor.yaml new file mode 100644 index 0000000..556a053 --- /dev/null +++ b/utils/assets/charts/loki/templates/distributor/deployment-distributor.yaml @@ -0,0 +1,158 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.distributorFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.distributorLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.distributor.autoscaling.enabled }} + replicas: {{ .Values.distributor.replicas }} +{{- end }} + strategy: + rollingUpdate: + maxSurge: {{ .Values.distributor.maxSurge }} + maxUnavailable: 1 + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.distributorSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.distributor.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.distributorSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.distributor.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.distributor.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.distributor.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.distributorPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.distributor.terminationGracePeriodSeconds }} + containers: + - name: distributor + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.distributor.command }} + command: + - {{ coalesce .Values.distributor.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=distributor + {{- if .Values.ingester.zoneAwareReplication.enabled }} + {{- if and (.Values.ingester.zoneAwareReplication.migration.enabled) (not .Values.ingester.zoneAwareReplication.migration.writePath) }} + - -distributor.zone-awareness-enabled=false + {{- else }} + - -distributor.zone-awareness-enabled=true + {{- end }} + {{- end }} + {{- with .Values.distributor.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.distributor.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.distributor.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + livenessProbe: + {{- toYaml .Values.loki.livenessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.distributor.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.distributor.resources | nindent 12 }} + {{- if .Values.distributor.extraContainers }} + {{- toYaml .Values.distributor.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.distributor.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.distributor.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.distributor.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.distributor.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/distributor/hpa.yaml b/utils/assets/charts/loki/templates/distributor/hpa.yaml new file mode 100644 index 0000000..838a310 --- /dev/null +++ b/utils/assets/charts/loki/templates/distributor/hpa.yaml @@ -0,0 +1,54 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.distributor.autoscaling.enabled }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.distributorFullname" . }} + labels: + {{- include "loki.distributorLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "loki.distributorFullname" . }} + minReplicas: {{ .Values.distributor.autoscaling.minReplicas }} + maxReplicas: {{ .Values.distributor.autoscaling.maxReplicas }} + metrics: + {{- with .Values.distributor.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.distributor.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.distributor.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.distributor.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.distributor.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.distributor.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/distributor/poddisruptionbudget-distributor.yaml b/utils/assets/charts/loki/templates/distributor/poddisruptionbudget-distributor.yaml new file mode 100644 index 0000000..806a447 --- /dev/null +++ b/utils/assets/charts/loki/templates/distributor/poddisruptionbudget-distributor.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.distributor.replicas) 1) }} +{{- if kindIs "invalid" .Values.distributor.maxUnavailable }} +{{- fail "`.Values.distributor.maxUnavailable` must be set when `.Values.distributor.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.distributorFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.distributorLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.distributorSelectorLabels" . | nindent 6 }} + {{- with .Values.distributor.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/distributor/service-distributor-headless.yaml b/utils/assets/charts/loki/templates/distributor/service-distributor-headless.yaml new file mode 100644 index 0000000..650b629 --- /dev/null +++ b/utils/assets/charts/loki/templates/distributor/service-distributor-headless.yaml @@ -0,0 +1,39 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.distributorFullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.distributorSelectorLabels" . | nindent 4 }} + {{- with .Values.distributor.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + variant: headless + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.distributor.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.distributor.appProtocol.grpc }} + appProtocol: {{ .Values.distributor.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.distributorSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/distributor/service-distributor.yaml b/utils/assets/charts/loki/templates/distributor/service-distributor.yaml new file mode 100644 index 0000000..6a89956 --- /dev/null +++ b/utils/assets/charts/loki/templates/distributor/service-distributor.yaml @@ -0,0 +1,36 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.distributorFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.distributorLabels" . | nindent 4 }} + {{- with .Values.distributor.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.distributor.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.distributor.appProtocol.grpc }} + appProtocol: {{ .Values.distributor.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.distributorSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/extra-manifests.yaml b/utils/assets/charts/loki/templates/extra-manifests.yaml new file mode 100644 index 0000000..7b69423 --- /dev/null +++ b/utils/assets/charts/loki/templates/extra-manifests.yaml @@ -0,0 +1,8 @@ +{{- range .Values.extraObjects }} +--- +{{- if kindIs "map" . }} +{{ tpl (toYaml .) $ }} +{{- else }} +{{ tpl . $ }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/_helpers-gateway.tpl b/utils/assets/charts/loki/templates/gateway/_helpers-gateway.tpl new file mode 100644 index 0000000..39890b1 --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/_helpers-gateway.tpl @@ -0,0 +1,47 @@ +{{/* +gateway fullname +*/}} +{{- define "loki.gatewayFullname" -}} +{{ include "loki.fullname" . }}-gateway +{{- end }} + +{{/* +gateway common labels +*/}} +{{- define "loki.gatewayLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: gateway +{{- end }} + +{{/* +gateway selector labels +*/}} +{{- define "loki.gatewaySelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: gateway +{{- end }} + +{{/* +gateway auth secret name +*/}} +{{- define "loki.gatewayAuthSecret" -}} +{{ .Values.gateway.basicAuth.existingSecret | default (include "loki.gatewayFullname" . ) }} +{{- end }} + +{{/* +gateway Docker image +*/}} +{{- define "loki.gatewayImage" -}} +{{- $dict := dict "service" .Values.gateway.image "global" .Values.global.image -}} +{{- include "loki.baseImage" $dict -}} +{{- end }} + +{{/* +gateway priority class name +*/}} +{{- define "loki.gatewayPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.gateway.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/configmap-gateway.yaml b/utils/assets/charts/loki/templates/gateway/configmap-gateway.yaml new file mode 100644 index 0000000..1c981a7 --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/configmap-gateway.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.gateway.enabled (not (and .Values.enterprise.enabled .Values.enterprise.gelGateway)) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} +data: + nginx.conf: | + {{- tpl .Values.gateway.nginxConfig.file . | indent 2 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/deployment-gateway-enterprise.yaml b/utils/assets/charts/loki/templates/gateway/deployment-gateway-enterprise.yaml new file mode 100644 index 0000000..22bf5c1 --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/deployment-gateway-enterprise.yaml @@ -0,0 +1,152 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and .Values.gateway.enabled .Values.enterprise.enabled .Values.enterprise.gelGateway }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "loki.gatewayFullname" . }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} + {{- with .Values.enterpriseGateway.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterpriseGateway.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.enterpriseGateway.replicas }} + selector: + matchLabels: + {{- include "loki.gatewaySelectorLabels" . | nindent 6 }} + strategy: + {{- toYaml .Values.enterpriseGateway.strategy | nindent 4 }} + template: + metadata: + labels: + {{- include "loki.gatewaySelectorLabels" . | nindent 8 }} + {{- with .Values.enterpriseGateway.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- if .Values.useExternalConfig }} + checksum/config: {{ .Values.externalConfigVersion }} + {{- else }} + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- end}} + {{- with .Values.enterpriseGateway.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.enterpriseGateway.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ template "loki.serviceAccountName" . }} + {{- if .Values.enterpriseGateway.priorityClassName }} + priorityClassName: {{ .Values.enterpriseGateway.priorityClassName }} + {{- end }} + securityContext: + {{- toYaml .Values.enterpriseGateway.podSecurityContext | nindent 8 }} + initContainers: + {{- toYaml .Values.enterpriseGateway.initContainers | nindent 8 }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.enterpriseGateway.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: gateway + image: "{{ template "loki.image" . }}" + imagePullPolicy: {{ .Values.enterprise.image.pullPolicy }} + args: + - -target=gateway + - -config.file=/etc/loki/config/config.yaml + {{- if .Values.minio.enabled }} + - -admin.client.backend-type=s3 + - -admin.client.s3.endpoint={{ template "loki.minio" . }} + - -admin.client.s3.bucket-name=enterprise-logs-admin + - -admin.client.s3.access-key-id={{ .Values.minio.accessKey }} + - -admin.client.s3.secret-access-key={{ .Values.minio.secretKey }} + - -admin.client.s3.insecure=true + {{- end }} + {{- if and $isDistributed .Values.enterpriseGateway.useDefaultProxyURLs }} + - -gateway.proxy.default.url=http://{{ template "loki.fullname" . }}-admin-api.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.admin-api.url=http://{{ template "loki.fullname" . }}-admin-api.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.distributor.url=dns:///{{ template "loki.fullname" . }}-distributor-headless.{{ .Release.Namespace }}.svc:9095 + - -gateway.proxy.ingester.url=http://{{ template "loki.fullname" . }}-ingester.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.query-frontend.url=http://{{ template "loki.fullname" . }}-query-frontend.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.ruler.url=http://{{ template "loki.fullname" . }}-ruler.{{ .Release.Namespace }}.svc:3100 + {{- end }} + {{- if and $isSimpleScalable .Values.enterpriseGateway.useDefaultProxyURLs }} + - -gateway.proxy.default.url=http://{{ template "enterprise-logs.adminApiFullname" . }}.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.admin-api.url=http://{{ template "enterprise-logs.adminApiFullname" . }}.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.compactor.url=http://{{ template "loki.backendFullname" . }}-headless.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.distributor.url=dns:///{{ template "loki.writeFullname" . }}-headless.{{ .Release.Namespace }}.svc:9095 + - -gateway.proxy.ingester.url=http://{{ template "loki.writeFullname" . }}.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.query-frontend.url=http://{{ template "loki.readFullname" . }}.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.ruler.url=http://{{ template "loki.backendFullname" . }}-headless.{{ .Release.Namespace }}.svc:3100 + - -gateway.proxy.query-scheduler.url=http://{{ template "loki.backendFullname" . }}-headless.{{ .Release.Namespace }}.svc:3100 + {{- end }} + {{- range $key, $value := .Values.enterpriseGateway.extraArgs }} + - "-{{ $key }}={{ $value }}" + {{- end }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: license + mountPath: /etc/loki/license + - name: storage + mountPath: /data + {{- if .Values.enterpriseGateway.extraVolumeMounts }} + {{ toYaml .Values.enterpriseGateway.extraVolumeMounts | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + readinessProbe: + {{- toYaml .Values.enterpriseGateway.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.enterpriseGateway.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.enterpriseGateway.containerSecurityContext | nindent 12 }} + env: + {{- if .Values.enterpriseGateway.env }} + {{ toYaml .Values.enterpriseGateway.env | nindent 12 }} + {{- end }} + {{- with .Values.enterpriseGateway.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.enterpriseGateway.extraContainers }} + {{ toYaml . | nindent 8 }} + {{- end }} + nodeSelector: + {{- toYaml .Values.enterpriseGateway.nodeSelector | nindent 8 }} + affinity: + {{- toYaml .Values.enterpriseGateway.affinity | nindent 8 }} + tolerations: + {{- toYaml .Values.enterpriseGateway.tolerations | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.enterpriseGateway.terminationGracePeriodSeconds }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + - name: storage + emptyDir: {} + {{- if .Values.enterpriseGateway.extraVolumes }} + {{ toYaml .Values.enterpriseGateway.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/deployment-gateway-nginx.yaml b/utils/assets/charts/loki/templates/gateway/deployment-gateway-nginx.yaml new file mode 100644 index 0000000..94562ad --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/deployment-gateway-nginx.yaml @@ -0,0 +1,138 @@ +{{- if and .Values.gateway.enabled (not (and .Values.enterprise.enabled .Values.enterprise.gelGateway)) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} + {{- if or (not (empty .Values.loki.annotations)) (not (empty .Values.backend.annotations))}} + annotations: + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.gateway.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: +{{- if not .Values.gateway.autoscaling.enabled }} + replicas: {{ .Values.gateway.replicas }} +{{- end }} +{{- with .Values.gateway.deploymentStrategy }} + strategy: +{{ toYaml . | trim | indent 4 }} +{{- end }} + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.gatewaySelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/gateway/configmap-gateway.yaml") }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gateway.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gateway.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.gatewaySelectorLabels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{ include "loki.enableServiceLinks" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end -}} + {{- include "loki.gatewayPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.gateway.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.gateway.terminationGracePeriodSeconds }} + containers: + - name: nginx + image: {{ include "loki.gatewayImage" . }} + imagePullPolicy: {{ .Values.gateway.image.pullPolicy }} + ports: + - name: http-metrics + containerPort: {{ .Values.gateway.containerPort }} + protocol: TCP + {{- with .Values.gateway.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.gateway.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + readinessProbe: + {{- toYaml .Values.gateway.readinessProbe | nindent 12 }} + securityContext: + {{- toYaml .Values.gateway.containerSecurityContext | nindent 12 }} + {{- with .Values.gateway.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /etc/nginx + {{- if .Values.gateway.basicAuth.enabled }} + - name: auth + mountPath: /etc/nginx/secrets + {{- end }} + - name: tmp + mountPath: /tmp + - name: docker-entrypoint-d-override + mountPath: /docker-entrypoint.d + {{- if .Values.gateway.extraVolumeMounts }} + {{- toYaml .Values.gateway.extraVolumeMounts | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.gateway.resources | nindent 12 }} + {{- if .Values.gateway.extraContainers }} + {{- toYaml .Values.gateway.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.gateway.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gateway.dnsConfig }} + dnsConfig: + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.gateway.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gateway.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gateway.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ include "loki.gatewayFullname" . }} + {{- if .Values.gateway.basicAuth.enabled }} + - name: auth + secret: + secretName: {{ include "loki.gatewayAuthSecret" . }} + {{- end }} + - name: tmp + emptyDir: {} + - name: docker-entrypoint-d-override + emptyDir: {} + {{- if .Values.gateway.extraVolumes }} + {{- toYaml .Values.gateway.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/hpa.yaml b/utils/assets/charts/loki/templates/gateway/hpa.yaml new file mode 100644 index 0000000..3541ec6 --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/hpa.yaml @@ -0,0 +1,50 @@ +{{- $autoscalingv2 := .Capabilities.APIVersions.Has "autoscaling/v2" -}} +{{- if .Values.gateway.autoscaling.enabled }} +{{- if $autoscalingv2 }} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta1 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "loki.gatewayFullname" . }} + minReplicas: {{ .Values.gateway.autoscaling.minReplicas }} + maxReplicas: {{ .Values.gateway.autoscaling.maxReplicas }} + {{- with .Values.gateway.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} + metrics: + {{- with .Values.gateway.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.gateway.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/ingress-gateway.yaml b/utils/assets/charts/loki/templates/gateway/ingress-gateway.yaml new file mode 100644 index 0000000..6f18e33 --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/ingress-gateway.yaml @@ -0,0 +1,59 @@ +{{- if and .Values.gateway.enabled -}} +{{- if .Values.gateway.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "loki.ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "loki.ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "loki.ingress.supportsPathType" .) "true" -}} +apiVersion: {{ include "loki.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} + {{- range $labelKey, $labelValue := .Values.gateway.ingress.labels }} + {{ $labelKey }}: {{ $labelValue | toYaml }} + {{- end }} + {{- with .Values.gateway.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.gateway.ingress.ingressClassName }} + ingressClassName: {{ .Values.gateway.ingress.ingressClassName }} + {{- end -}} + {{- if .Values.gateway.ingress.tls }} + tls: + {{- range .Values.gateway.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ tpl . $ | quote }} + {{- end }} + {{- with .secretName }} + secretName: {{ . }} + {{- end }} + {{- end }} + {{- end }} + rules: + {{- range .Values.gateway.ingress.hosts }} + - host: {{ tpl .host $ | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if $ingressSupportsPathType }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ include "loki.gatewayFullname" $ }} + port: + number: {{ $.Values.gateway.service.port }} + {{- else }} + serviceName: {{ include "loki.gatewayFullname" $ }} + servicePort: {{ $.Values.gateway.service.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/poddisruptionbudget-gateway.yaml b/utils/assets/charts/loki/templates/gateway/poddisruptionbudget-gateway.yaml new file mode 100644 index 0000000..0057c56 --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/poddisruptionbudget-gateway.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.gateway.enabled }} +{{- if or + (and (not .Values.gateway.autoscaling.enabled) (gt (int .Values.gateway.replicas) 1)) + (and .Values.gateway.autoscaling.enabled (gt (int .Values.gateway.autoscaling.minReplicas) 1)) +}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.gatewaySelectorLabels" . | nindent 6 }} + maxUnavailable: 1 +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/secret-gateway.yaml b/utils/assets/charts/loki/templates/gateway/secret-gateway.yaml new file mode 100644 index 0000000..c3c5e9a --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/secret-gateway.yaml @@ -0,0 +1,14 @@ +{{- with .Values.gateway }} +{{- if and .enabled .basicAuth.enabled (not .basicAuth.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "loki.gatewayFullname" $ }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.gatewayLabels" $ | nindent 4 }} +stringData: + .htpasswd: | + {{- tpl .basicAuth.htpasswd $ | nindent 4 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/gateway/service-gateway.yaml b/utils/assets/charts/loki/templates/gateway/service-gateway.yaml new file mode 100644 index 0000000..8c71026 --- /dev/null +++ b/utils/assets/charts/loki/templates/gateway/service-gateway.yaml @@ -0,0 +1,40 @@ +{{- if .Values.gateway.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.gateway.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.gateway.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: {{ .Values.gateway.service.type }} + {{- with .Values.gateway.service.clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- if and (eq "LoadBalancer" .Values.gateway.service.type) .Values.gateway.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.gateway.service.loadBalancerIP }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.gateway.service.port }} + targetPort: http-metrics + {{- if and (eq "NodePort" .Values.gateway.service.type) .Values.gateway.service.nodePort }} + nodePort: {{ .Values.gateway.service.nodePort }} + {{- end }} + protocol: TCP + selector: + {{- include "loki.gatewaySelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/index-gateway/_helpers-index-gateway.tpl b/utils/assets/charts/loki/templates/index-gateway/_helpers-index-gateway.tpl new file mode 100644 index 0000000..f42dff3 --- /dev/null +++ b/utils/assets/charts/loki/templates/index-gateway/_helpers-index-gateway.tpl @@ -0,0 +1,40 @@ +{{/* +index-gateway fullname +*/}} +{{- define "loki.indexGatewayFullname" -}} +{{ include "loki.fullname" . }}-index-gateway +{{- end }} + +{{/* +index-gateway common labels +*/}} +{{- define "loki.indexGatewayLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: index-gateway +{{- end }} + +{{/* +index-gateway selector labels +*/}} +{{- define "loki.indexGatewaySelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: index-gateway +{{- end }} + +{{/* +index-gateway image +*/}} +{{- define "loki.indexGatewayImage" -}} +{{- $dict := dict "loki" .Values.loki.image "service" .Values.indexGateway.image "global" .Values.global.image "defaultVersion" .Chart.AppVersion -}} +{{- include "loki.lokiImage" $dict -}} +{{- end }} + +{{/* +index-gateway priority class name +*/}} +{{- define "loki.indexGatewayPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.indexGateway.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/index-gateway/poddisruptionbudget-index-gateway.yaml b/utils/assets/charts/loki/templates/index-gateway/poddisruptionbudget-index-gateway.yaml new file mode 100644 index 0000000..cc230c2 --- /dev/null +++ b/utils/assets/charts/loki/templates/index-gateway/poddisruptionbudget-index-gateway.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.indexGateway.replicas) 1) }} +{{- if kindIs "invalid" .Values.indexGateway.maxUnavailable }} +{{- fail "`.Values.indexGateway.maxUnavailable` must be set when `.Values.indexGateway.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.indexGatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.indexGatewayLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.indexGatewaySelectorLabels" . | nindent 6 }} + {{- with .Values.indexGateway.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/index-gateway/service-index-gateway-headless.yaml b/utils/assets/charts/loki/templates/index-gateway/service-index-gateway-headless.yaml new file mode 100644 index 0000000..731a984 --- /dev/null +++ b/utils/assets/charts/loki/templates/index-gateway/service-index-gateway-headless.yaml @@ -0,0 +1,35 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.indexGatewayFullname" . }}-headless + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.indexGatewaySelectorLabels" . | nindent 4 }} + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.indexGateway.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- with .Values.indexGateway.appProtocol.grpc }} + appProtocol: {{ . }} + {{- end }} + selector: + {{- include "loki.indexGatewaySelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/index-gateway/service-index-gateway.yaml b/utils/assets/charts/loki/templates/index-gateway/service-index-gateway.yaml new file mode 100644 index 0000000..b1a3523 --- /dev/null +++ b/utils/assets/charts/loki/templates/index-gateway/service-index-gateway.yaml @@ -0,0 +1,36 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.indexGatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.indexGatewayLabels" . | nindent 4 }} + {{- with .Values.indexGateway.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.indexGateway.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- with .Values.indexGateway.appProtocol.grpc }} + appProtocol: {{ . }} + {{- end }} + selector: + {{- include "loki.indexGatewaySelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/index-gateway/statefulset-index-gateway.yaml b/utils/assets/charts/loki/templates/index-gateway/statefulset-index-gateway.yaml new file mode 100644 index 0000000..e249859 --- /dev/null +++ b/utils/assets/charts/loki/templates/index-gateway/statefulset-index-gateway.yaml @@ -0,0 +1,192 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.indexGatewayFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.indexGatewayLabels" . | nindent 4 }} + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.indexGateway.replicas }} +{{- with .Values.indexGateway.updateStrategy }} + updateStrategy: + {{- tpl (. | toYaml) $ | nindent 4 }} +{{- end }} + serviceName: {{ include "loki.indexGatewayFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.indexGateway.persistence.enableStatefulSetAutoDeletePVC) }} + {{/* + Data on the read nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.indexGateway.persistence.whenDeleted }} + whenScaled: {{ .Values.indexGateway.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.indexGatewaySelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.indexGateway.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.indexGatewaySelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.indexGateway.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.indexGateway.joinMemberlist }} + app.kubernetes.io/part-of: memberlist + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.indexGateway.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.indexGatewayPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.indexGateway.terminationGracePeriodSeconds }} + {{- with .Values.indexGateway.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: index-gateway + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=index-gateway + {{- with .Values.indexGateway.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + {{- if .Values.indexGateway.joinMemberlist }} + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- end }} + {{- with .Values.indexGateway.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.indexGateway.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + livenessProbe: + {{- toYaml .Values.loki.livenessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.indexGateway.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.indexGateway.resources | nindent 12 }} + {{- if .Values.indexGateway.extraContainers }} + {{- toYaml .Values.indexGateway.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.indexGateway.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.indexGateway.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.indexGateway.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.indexGateway.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.indexGateway.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.indexGateway.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if .Values.indexGateway.persistence.inMemory }} + - name: data + {{- if .Values.indexGateway.persistence.inMemory }} + emptyDir: + medium: Memory + {{- end }} + {{- if .Values.indexGateway.persistence.size }} + sizeLimit: {{ .Values.indexGateway.persistence.size }} + {{- end }} + {{- else }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.indexGateway.persistence.annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .Values.indexGateway.persistence.storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .Values.indexGateway.persistence.size | quote }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/_helpers-ingester.tpl b/utils/assets/charts/loki/templates/ingester/_helpers-ingester.tpl new file mode 100644 index 0000000..418d409 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/_helpers-ingester.tpl @@ -0,0 +1,74 @@ +{{/* +ingester fullname +*/}} +{{- define "loki.ingesterFullname" -}} +{{ include "loki.fullname" . }}-ingester +{{- end }} + +{{/* +ingester common labels +*/}} +{{- define "loki.ingesterLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: ingester +{{- end }} + +{{/* +ingester selector labels +*/}} +{{- define "loki.ingesterSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: ingester +{{- end }} + +{{/* +ingester priority class name +*/}} +{{- define "loki.ingesterPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.ingester.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} + +{{- define "loki.ingester.readinessProbe" -}} +{{- with .Values.ingester.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- else }} +{{- with .Values.loki.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{- define "loki.ingester.livenessProbe" -}} +{{- with .Values.ingester.livenessProbe }} +livenessProbe: + {{- toYaml . | nindent 2 }} +{{- else }} +{{- with .Values.loki.livenessProbe }} +livenessProbe: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +expects global context +*/}} +{{- define "loki.ingester.replicaCount" -}} +{{- ceil (divf .Values.ingester.replicas 3) -}} +{{- end -}} + +{{/* +expects a dict +{ + "replicas": replicas in a zone, + "ctx": global context +} +*/}} +{{- define "loki.ingester.maxUnavailable" -}} +{{- ceil (mulf .replicas (divf (int .ctx.Values.ingester.zoneAwareReplication.maxUnavailablePct) 100)) -}} +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/loki/templates/ingester/hpa-zone-a.yaml b/utils/assets/charts/loki/templates/ingester/hpa-zone-a.yaml new file mode 100644 index 0000000..5ede187 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/hpa-zone-a.yaml @@ -0,0 +1,55 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.autoscaling.enabled .Values.ingester.zoneAwareReplication.enabled }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-a + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "loki.ingesterFullname" . }}-zone-a + minReplicas: {{ .Values.ingester.autoscaling.minReplicas }} + maxReplicas: {{ .Values.ingester.autoscaling.maxReplicas }} + metrics: + {{- with .Values.ingester.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.ingester.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.ingester.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.ingester.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/hpa-zone-b.yaml b/utils/assets/charts/loki/templates/ingester/hpa-zone-b.yaml new file mode 100644 index 0000000..b001a6a --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/hpa-zone-b.yaml @@ -0,0 +1,55 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.autoscaling.enabled .Values.ingester.zoneAwareReplication.enabled }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-b + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "loki.ingesterFullname" . }}-zone-b + minReplicas: {{ .Values.ingester.autoscaling.minReplicas }} + maxReplicas: {{ .Values.ingester.autoscaling.maxReplicas }} + metrics: + {{- with .Values.ingester.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.ingester.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.ingester.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.ingester.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/hpa-zone-c.yaml b/utils/assets/charts/loki/templates/ingester/hpa-zone-c.yaml new file mode 100644 index 0000000..82f229c --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/hpa-zone-c.yaml @@ -0,0 +1,55 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.autoscaling.enabled .Values.ingester.zoneAwareReplication.enabled }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-c + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "loki.ingesterFullname" . }}-zone-c + minReplicas: {{ .Values.ingester.autoscaling.minReplicas }} + maxReplicas: {{ .Values.ingester.autoscaling.maxReplicas }} + metrics: + {{- with .Values.ingester.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.ingester.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.ingester.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.ingester.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/hpa.yaml b/utils/assets/charts/loki/templates/ingester/hpa.yaml new file mode 100644 index 0000000..de35d67 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/hpa.yaml @@ -0,0 +1,55 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.autoscaling.enabled (or (not .Values.ingester.zoneAwareReplication.enabled) .Values.ingester.zoneAwareReplication.migration.enabled) }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.ingesterFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "loki.ingesterFullname" . }} + minReplicas: {{ .Values.ingester.autoscaling.minReplicas }} + maxReplicas: {{ .Values.ingester.autoscaling.maxReplicas }} + metrics: + {{- with .Values.ingester.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.ingester.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.ingester.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.ingester.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.ingester.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/poddisruptionbudget-ingester-rollout.yaml b/utils/assets/charts/loki/templates/ingester/poddisruptionbudget-ingester-rollout.yaml new file mode 100644 index 0000000..000ab85 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/poddisruptionbudget-ingester-rollout.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.ingester.replicas) 1) (.Values.ingester.zoneAwareReplication.enabled) }} +{{- if kindIs "invalid" .Values.ingester.maxUnavailable }} +{{- fail "`.Values.ingester.maxUnavailable` must be set when `.Values.ingester.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.ingesterFullname" . }}-rollout + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + rollout-group: ingester + {{- with .Values.ingester.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/poddisruptionbudget-ingester.yaml b/utils/assets/charts/loki/templates/ingester/poddisruptionbudget-ingester.yaml new file mode 100644 index 0000000..1142c01 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/poddisruptionbudget-ingester.yaml @@ -0,0 +1,27 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.ingester.replicas) 1) (or (not .Values.ingester.zoneAwareReplication.enabled) .Values.ingester.zoneAwareReplication.migration.enabled) }} +{{- if kindIs "invalid" .Values.ingester.maxUnavailable }} +{{- fail "`.Values.ingester.maxUnavailable` must be set when `.Values.ingester.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.ingesterFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.ingesterSelectorLabels" . | nindent 6 }} + {{/* zone aware ingesters get their own pod disruption budget, ignore them here */}} + matchExpressions: + - key: rollout-group + operator: NotIn + values: + - "ingester" + {{- with .Values.ingester.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/service-ingester-headless.yaml b/utils/assets/charts/loki/templates/ingester/service-ingester-headless.yaml new file mode 100644 index 0000000..8a8b92f --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/service-ingester-headless.yaml @@ -0,0 +1,35 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (or (not .Values.ingester.zoneAwareReplication.enabled) .Values.ingester.zoneAwareReplication.migration.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.ingesterFullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterSelectorLabels" . | nindent 4 }} + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.ingester.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.ingester.appProtocol.grpc }} + appProtocol: {{ .Values.ingester.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.ingesterSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/ingester/service-ingester-zone-a-headless.yaml b/utils/assets/charts/loki/templates/ingester/service-ingester-zone-a-headless.yaml new file mode 100644 index 0000000..03add3b --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/service-ingester-zone-a-headless.yaml @@ -0,0 +1,38 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.zoneAwareReplication.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-a-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + {{- with .Values.ingester.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.ingester.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.ingester.appProtocol.grpc }} + appProtocol: {{ .Values.ingester.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.ingesterSelectorLabels" . | nindent 4 }} + name: ingester-zone-a + rollout-group: ingester +{{- end -}} diff --git a/utils/assets/charts/loki/templates/ingester/service-ingester-zone-b-headless.yaml b/utils/assets/charts/loki/templates/ingester/service-ingester-zone-b-headless.yaml new file mode 100644 index 0000000..6072219 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/service-ingester-zone-b-headless.yaml @@ -0,0 +1,38 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.zoneAwareReplication.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-b-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + {{- with .Values.ingester.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.ingester.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.ingester.appProtocol.grpc }} + appProtocol: {{ .Values.ingester.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.ingesterSelectorLabels" . | nindent 4 }} + name: ingester-zone-b + rollout-group: ingester +{{- end -}} diff --git a/utils/assets/charts/loki/templates/ingester/service-ingester-zone-c-headless.yaml b/utils/assets/charts/loki/templates/ingester/service-ingester-zone-c-headless.yaml new file mode 100644 index 0000000..5541447 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/service-ingester-zone-c-headless.yaml @@ -0,0 +1,38 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.zoneAwareReplication.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-c-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + {{- with .Values.ingester.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.ingester.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.ingester.appProtocol.grpc }} + appProtocol: {{ .Values.ingester.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.ingesterSelectorLabels" . | nindent 4 }} + name: ingester-zone-c + rollout-group: ingester +{{- end -}} diff --git a/utils/assets/charts/loki/templates/ingester/service-ingester.yaml b/utils/assets/charts/loki/templates/ingester/service-ingester.yaml new file mode 100644 index 0000000..94d6f83 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/service-ingester.yaml @@ -0,0 +1,36 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (or (not .Values.ingester.zoneAwareReplication.enabled) .Values.ingester.zoneAwareReplication.migration.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.ingesterFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + {{- with .Values.ingester.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.ingester.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.ingester.appProtocol.grpc }} + appProtocol: {{ .Values.ingester.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.ingesterSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-a.yaml b/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-a.yaml new file mode 100644 index 0000000..a731661 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-a.yaml @@ -0,0 +1,234 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.zoneAwareReplication.enabled }} +{{- $replicas := (include "loki.ingester.replicaCount" .) -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-a + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + rollout-group: ingester + name: ingester-zone-a + annotations: + rollout-max-unavailable: "{{ include "loki.ingester.maxUnavailable" (dict "ctx" . "replicas" $replicas)}}" + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneA.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.ingester.autoscaling.enabled }} + replicas: {{ $replicas }} +{{- end }} + podManagementPolicy: Parallel + serviceName: {{ include "loki.ingesterFullname" . }}-zone-a + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.ingester.persistence.enableStatefulSetAutoDeletePVC) }} + {{/* + Data on the read nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.ingester.persistence.whenDeleted }} + whenScaled: {{ .Values.ingester.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.ingesterSelectorLabels" . | nindent 6 }} + name: ingester-zone-a + rollout-group: ingester +{{- with .Values.ingester.updateStrategy }} + updateStrategy: + {{- tpl (. | toYaml) $ | nindent 4 }} +{{- end }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneA.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.ingesterSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + name: ingester-zone-a + rollout-group: ingester + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.ingester.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.ingesterPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.ingester.terminationGracePeriodSeconds }} + {{- with .Values.ingester.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ingester + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.ingester.command }} + command: + - {{ coalesce .Values.ingester.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -ingester.availability-zone=zone-a + - -ingester.unregister-on-shutdown=false + - -ingester.tokens-file-path=/var/loki/ring-tokens + - -target=ingester + {{- with .Values.ingester.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.ingester.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.ingester.readinessProbe" . | nindent 10 }} + {{- include "loki.ingester.livenessProbe" . | nindent 10 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.ingester.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.ingester.extraContainers }} + {{- toYaml .Values.ingester.extraContainers | nindent 8}} + {{- end }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: rollout-group + operator: In + values: + - ingester + - key: name + operator: NotIn + values: + - ingester-zone-a + topologyKey: kubernetes.io/hostname + {{- with .Values.ingester.zoneAwareReplication.zoneA.extraAffinity }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneA.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.ingester.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.ingester.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if .Values.ingester.persistence.inMemory }} + - name: data + {{- if .Values.ingester.persistence.inMemory }} + emptyDir: + medium: Memory + {{- end }} + {{- if .Values.ingester.persistence.size }} + sizeLimit: {{ .Values.ingester.persistence.size }} + {{- end }} + {{- else }} + volumeClaimTemplates: + {{- range .Values.ingester.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-b.yaml b/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-b.yaml new file mode 100644 index 0000000..7512454 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-b.yaml @@ -0,0 +1,234 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.zoneAwareReplication.enabled }} +{{- $replicas := (include "loki.ingester.replicaCount" .) -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-b + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + rollout-group: ingester + name: ingester-zone-b + annotations: + rollout-max-unavailable: "{{ include "loki.ingester.maxUnavailable" (dict "ctx" . "replicas" $replicas)}}" + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneB.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.ingester.autoscaling.enabled }} + replicas: {{ $replicas }} +{{- end }} + podManagementPolicy: Parallel + serviceName: {{ include "loki.ingesterFullname" . }}-zone-b + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.ingester.persistence.enableStatefulSetAutoDeletePVC) }} + {{/* + Data on the read nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.ingester.persistence.whenDeleted }} + whenScaled: {{ .Values.ingester.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.ingesterSelectorLabels" . | nindent 6 }} + name: ingester-zone-b + rollout-group: ingester +{{- with .Values.ingester.updateStrategy }} + updateStrategy: + {{- tpl (. | toYaml) $ | nindent 4 }} +{{- end }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneB.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.ingesterSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + name: ingester-zone-b + rollout-group: ingester + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.ingester.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.ingesterPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.ingester.terminationGracePeriodSeconds }} + {{- with .Values.ingester.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ingester + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.ingester.command }} + command: + - {{ coalesce .Values.ingester.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -ingester.availability-zone=zone-b + - -ingester.unregister-on-shutdown=false + - -ingester.tokens-file-path=/var/loki/ring-tokens + - -target=ingester + {{- with .Values.ingester.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.ingester.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.ingester.readinessProbe" . | nindent 10 }} + {{- include "loki.ingester.livenessProbe" . | nindent 10 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.ingester.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.ingester.extraContainers }} + {{- toYaml .Values.ingester.extraContainers | nindent 8}} + {{- end }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: rollout-group + operator: In + values: + - ingester + - key: name + operator: NotIn + values: + - ingester-zone-b + topologyKey: kubernetes.io/hostname + {{- with .Values.ingester.zoneAwareReplication.zoneB.extraAffinity }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneB.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.ingester.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.ingester.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if .Values.ingester.persistence.inMemory }} + - name: data + {{- if .Values.ingester.persistence.inMemory }} + emptyDir: + medium: Memory + {{- end }} + {{- if .Values.ingester.persistence.size }} + sizeLimit: {{ .Values.ingester.persistence.size }} + {{- end }} + {{- else }} + volumeClaimTemplates: + {{- range .Values.ingester.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-c.yaml b/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-c.yaml new file mode 100644 index 0000000..657d6a5 --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/statefulset-ingester-zone-c.yaml @@ -0,0 +1,234 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ingester.zoneAwareReplication.enabled }} +{{- $replicas := (include "loki.ingester.replicaCount" .) -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.ingesterFullname" . }}-zone-c + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + rollout-group: ingester + name: ingester-zone-c + annotations: + rollout-max-unavailable: "{{ include "loki.ingester.maxUnavailable" (dict "ctx" . "replicas" $replicas)}}" + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneC.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.ingester.autoscaling.enabled }} + replicas: {{ $replicas }} +{{- end }} + podManagementPolicy: Parallel + serviceName: {{ include "loki.ingesterFullname" . }}-zone-c + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.ingester.persistence.enableStatefulSetAutoDeletePVC) }} + {{/* + Data on the read nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.ingester.persistence.whenDeleted }} + whenScaled: {{ .Values.ingester.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.ingesterSelectorLabels" . | nindent 6 }} + name: ingester-zone-c + rollout-group: ingester +{{- with .Values.ingester.updateStrategy }} + updateStrategy: + {{- tpl (. | toYaml) $ | nindent 4 }} +{{- end }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneC.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.ingesterSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + name: ingester-zone-c + rollout-group: ingester + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.ingester.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.ingesterPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.ingester.terminationGracePeriodSeconds }} + {{- with .Values.ingester.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ingester + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.ingester.command }} + command: + - {{ coalesce .Values.ingester.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -ingester.availability-zone=zone-c + - -ingester.unregister-on-shutdown=false + - -ingester.tokens-file-path=/var/loki/ring-tokens + - -target=ingester + {{- with .Values.ingester.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.ingester.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.ingester.readinessProbe" . | nindent 10 }} + {{- include "loki.ingester.livenessProbe" . | nindent 10 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.ingester.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.ingester.extraContainers }} + {{- toYaml .Values.ingester.extraContainers | nindent 8}} + {{- end }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: rollout-group + operator: In + values: + - ingester + - key: name + operator: NotIn + values: + - ingester-zone-c + topologyKey: kubernetes.io/hostname + {{- with .Values.ingester.zoneAwareReplication.zoneC.extraAffinity }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.zoneAwareReplication.zoneC.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.ingester.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.ingester.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if .Values.ingester.persistence.inMemory }} + - name: data + {{- if .Values.ingester.persistence.inMemory }} + emptyDir: + medium: Memory + {{- end }} + {{- if .Values.ingester.persistence.size }} + sizeLimit: {{ .Values.ingester.persistence.size }} + {{- end }} + {{- else }} + volumeClaimTemplates: + {{- range .Values.ingester.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingester/statefulset-ingester.yaml b/utils/assets/charts/loki/templates/ingester/statefulset-ingester.yaml new file mode 100644 index 0000000..217196a --- /dev/null +++ b/utils/assets/charts/loki/templates/ingester/statefulset-ingester.yaml @@ -0,0 +1,205 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (or (not .Values.ingester.zoneAwareReplication.enabled) .Values.ingester.zoneAwareReplication.migration.enabled) }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.ingesterFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.ingesterLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.ingester.autoscaling.enabled }} + replicas: {{ .Values.ingester.replicas }} +{{- end }} + podManagementPolicy: Parallel +{{- with .Values.ingester.updateStrategy }} + updateStrategy: + {{- tpl (. | toYaml) $ | nindent 4 }} +{{- end }} + serviceName: {{ include "loki.ingesterFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.ingester.persistence.enableStatefulSetAutoDeletePVC) }} + {{/* + Data on the read nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.ingester.persistence.whenDeleted }} + whenScaled: {{ .Values.ingester.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.ingesterSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.ingesterSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.ingester.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.ingesterPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.ingester.terminationGracePeriodSeconds }} + {{- with .Values.ingester.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ingester + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.ingester.command }} + command: + - {{ coalesce .Values.ingester.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -ingester.availability-zone=zone-default + - -target=ingester + {{- with .Values.ingester.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.ingester.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.ingester.readinessProbe" . | nindent 10 }} + {{- include "loki.ingester.livenessProbe" . | nindent 10 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.ingester.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ingester.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.ingester.extraContainers }} + {{- toYaml .Values.ingester.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.ingester.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ingester.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.ingester.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.ingester.persistence.enabled }} + - name: data + emptyDir: { } + {{- else if .Values.ingester.persistence.inMemory }} + - name: data + {{- if .Values.ingester.persistence.inMemory }} + emptyDir: + medium: Memory + {{- end }} + {{- if .Values.ingester.persistence.size }} + sizeLimit: {{ .Values.ingester.persistence.size }} + {{- end }} + {{- else }} + volumeClaimTemplates: + {{- range .Values.ingester.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ingress.yaml b/utils/assets/charts/loki/templates/ingress.yaml new file mode 100644 index 0000000..ddbcf7f --- /dev/null +++ b/utils/assets/charts/loki/templates/ingress.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ingress.enabled }} +{{- $ingressSupportsIngressClassName := eq (include "loki.ingress.supportsIngressClassName" .) "true" -}} +apiVersion: {{ include "loki.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "loki.fullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} + ingressClassName: {{ .Values.ingress.ingressClassName }} + {{- end -}} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ tpl . $ | quote }} + {{- end }} + {{- with .secretName }} + secretName: {{ . }} + {{- end }} + {{- end }} + {{- end }} + rules: + {{- range $.Values.ingress.hosts }} + - host: {{ tpl . $ | quote }} + http: + paths: + {{- include "loki.ingress.servicePaths" $ | indent 10}} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/loki-canary/_helpers.tpl b/utils/assets/charts/loki/templates/loki-canary/_helpers.tpl new file mode 100644 index 0000000..01e588c --- /dev/null +++ b/utils/assets/charts/loki/templates/loki-canary/_helpers.tpl @@ -0,0 +1,40 @@ +{{/* +canary fullname +*/}} +{{- define "loki-canary.fullname" -}} +{{ include "loki.name" . }}-canary +{{- end }} + +{{/* +canary common labels +*/}} +{{- define "loki-canary.labels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: canary +{{- end }} + +{{/* +canary selector labels +*/}} +{{- define "loki-canary.selectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: canary +{{- end }} + +{{/* +Docker image name for loki-canary +*/}} +{{- define "loki-canary.image" -}} +{{- $dict := dict "service" .Values.lokiCanary.image "global" .Values.global.image "defaultVersion" .Chart.AppVersion -}} +{{- include "loki.baseImage" $dict -}} +{{- end -}} + +{{/* +canary priority class name +*/}} +{{- define "loki-canary.priorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.lokiCanary.priorityClassName .Values.read.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/loki-canary/daemonset.yaml b/utils/assets/charts/loki/templates/loki-canary/daemonset.yaml new file mode 100644 index 0000000..dc5c629 --- /dev/null +++ b/utils/assets/charts/loki/templates/loki-canary/daemonset.yaml @@ -0,0 +1,123 @@ +{{- with .Values.lokiCanary -}} +{{- if .enabled -}} +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "loki-canary.fullname" $ }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki-canary.labels" $ | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki-canary.selectorLabels" $ | nindent 6 }} + {{- with .updateStrategy }} + updateStrategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki-canary.selectorLabels" $ | nindent 8 }} + {{- with .podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki-canary.fullname" $ }} + {{- with $.Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki-canary.priorityClassName" $ | nindent 6 }} + securityContext: + {{- toYaml $.Values.loki.podSecurityContext | nindent 8 }} + containers: + - name: loki-canary + image: {{ include "loki-canary.image" $ }} + imagePullPolicy: {{ $.Values.loki.image.pullPolicy }} + args: + - -addr={{- include "loki.host" $ }} + - -labelname={{ .labelname }} + - -labelvalue=$(POD_NAME) + {{- if $.Values.enterprise.enabled }} + - -user=$(USER) + - -tenant-id=$(USER) + - -pass=$(PASS) + {{- else if $.Values.loki.auth_enabled }} + - -user={{ $.Values.monitoring.selfMonitoring.tenant.name }} + - -tenant-id={{ $.Values.monitoring.selfMonitoring.tenant.name }} + - -pass={{ $.Values.monitoring.selfMonitoring.tenant.password }} + {{- end }} + {{- if .push }} + - -push=true + {{- end }} + {{- with .extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml $.Values.loki.containerSecurityContext | nindent 12 }} + volumeMounts: + {{- with $.Values.lokiCanary.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3500 + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{ if $.Values.enterprise.enabled }} + - name: USER + valueFrom: + secretKeyRef: + name: {{ include "enterprise-logs.selfMonitoringTenantSecret" $ }} + key: username + - name: PASS + valueFrom: + secretKeyRef: + name: {{ include "enterprise-logs.selfMonitoringTenantSecret" $ }} + key: password + {{- end -}} + {{- with .extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + readinessProbe: + httpGet: + path: /metrics + port: http-metrics + initialDelaySeconds: 15 + timeoutSeconds: 1 + {{- with .resources}} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- with $.Values.lokiCanary.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/loki-canary/service.yaml b/utils/assets/charts/loki/templates/loki-canary/service.yaml new file mode 100644 index 0000000..38022a3 --- /dev/null +++ b/utils/assets/charts/loki/templates/loki-canary/service.yaml @@ -0,0 +1,34 @@ +{{- with .Values.lokiCanary -}} +{{- if .enabled -}} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-canary.fullname" $ }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki-canary.labels" $ | nindent 4 }} + {{- with $.Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + annotations: + {{- with $.Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: 3500 + targetPort: http-metrics + protocol: TCP + selector: + {{- include "loki-canary.selectorLabels" $ | nindent 4 }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/loki-canary/serviceaccount.yaml b/utils/assets/charts/loki/templates/loki-canary/serviceaccount.yaml new file mode 100644 index 0000000..2c1f79a --- /dev/null +++ b/utils/assets/charts/loki/templates/loki-canary/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{- with .Values.lokiCanary -}} +{{- if .enabled -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "loki-canary.fullname" $ }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki-canary.labels" $ | nindent 4 }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ $.Values.serviceAccount.automountServiceAccountToken }} +{{- with $.Values.serviceAccount.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/memcached/_memcached-statefulset.tpl b/utils/assets/charts/loki/templates/memcached/_memcached-statefulset.tpl new file mode 100644 index 0000000..0664ba4 --- /dev/null +++ b/utils/assets/charts/loki/templates/memcached/_memcached-statefulset.tpl @@ -0,0 +1,178 @@ +{{/* +memcached StatefulSet +Params: + ctx = . context + valuesSection = name of the section in values.yaml + component = name of the component +valuesSection and component are specified separately because helm prefers camelcase for naming convetion and k8s components are named with snake case. +*/}} +{{- define "loki.memcached.statefulSet" -}} +{{ with (index $.ctx.Values $.valuesSection) }} +{{- if .enabled -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.resourceName" (dict "ctx" $.ctx "component" $.component) }} + labels: + {{- include "loki.labels" $.ctx | nindent 4 }} + app.kubernetes.io/component: "memcached-{{ $.component }}" + name: "memcached-{{ $.component }}" + annotations: + {{- toYaml .annotations | nindent 4 }} + namespace: {{ $.ctx.Release.Namespace | quote }} +spec: + podManagementPolicy: {{ .podManagementPolicy }} + replicas: {{ .replicas }} + selector: + matchLabels: + {{- include "loki.selectorLabels" $.ctx | nindent 6 }} + app.kubernetes.io/component: "memcached-{{ $.component }}" + name: "memcached-{{ $.component }}" + updateStrategy: + {{- toYaml .statefulStrategy | nindent 4 }} + serviceName: {{ template "loki.fullname" $.ctx }}-{{ $.component }} + + template: + metadata: + labels: + {{- include "loki.selectorLabels" $.ctx | nindent 8 }} + app.kubernetes.io/component: "memcached-{{ $.component }}" + name: "memcached-{{ $.component }}" + {{- with $.ctx.Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- with $.ctx.Values.global.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + + spec: + serviceAccountName: {{ template "loki.serviceAccountName" $.ctx }} + {{- if .priorityClassName }} + priorityClassName: {{ .priorityClassName }} + {{- end }} + securityContext: + {{- toYaml $.ctx.Values.memcached.podSecurityContext | nindent 8 }} + initContainers: + {{- toYaml .initContainers | nindent 8 }} + nodeSelector: + {{- toYaml .nodeSelector | nindent 8 }} + affinity: + {{- toYaml .affinity | nindent 8 }} + topologySpreadConstraints: + {{- toYaml .topologySpreadConstraints | nindent 8 }} + tolerations: + {{- toYaml .tolerations | nindent 8 }} + terminationGracePeriodSeconds: {{ .terminationGracePeriodSeconds }} + {{- with $.ctx.Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .extraVolumes }} + volumes: + {{- toYaml .extraVolumes | nindent 8 }} + {{- end }} + containers: + {{- if .extraContainers }} + {{ toYaml .extraContainers | nindent 8 }} + {{- end }} + - name: memcached + {{- with $.ctx.Values.memcached.image }} + image: {{ .repository }}:{{ .tag }} + imagePullPolicy: {{ .pullPolicy }} + {{- end }} + resources: + {{- if .resources }} + {{- toYaml .resources | nindent 12 }} + {{- else }} + {{- /* Calculate requested memory as round(allocatedMemory * 1.2). But with integer built-in operators. */}} + {{- $requestMemory := div (add (mul .allocatedMemory 12) 5) 10 }} + limits: + memory: {{ $requestMemory }}Mi + requests: + cpu: 500m + memory: {{ $requestMemory }}Mi + {{- end }} + ports: + - containerPort: {{ .port }} + name: client + {{- /* Calculate storage size as round(.persistence.storageSize * 0.9). But with integer built-in operators. */}} + {{- $persistenceSize := (div (mul (trimSuffix "Gi" .persistence.storageSize | trimSuffix "G") 9) 10 ) }} + args: + - -m {{ .allocatedMemory }} + - --extended=modern,track_sizes{{ if .persistence.enabled }},ext_path={{ .persistence.mountPath }}/file:{{ $persistenceSize }}G,ext_wbuf_size=16{{ end }}{{ with .extraExtendedOptions }},{{ . }}{{ end }} + - -I {{ .maxItemMemory }}m + - -c {{ .connectionLimit }} + - -v + - -u {{ .port }} + {{- range $key, $value := .extraArgs }} + - "-{{ $key }}{{ if $value }} {{ $value }}{{ end }}" + {{- end }} + env: + {{- with $.ctx.Values.global.extraEnv }} + {{ toYaml . | nindent 12 }} + {{- end }} + envFrom: + {{- with $.ctx.Values.global.extraEnvFrom }} + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml $.ctx.Values.memcached.containerSecurityContext | nindent 12 }} + {{- if or .persistence.enabled .extraVolumeMounts }} + volumeMounts: + {{- if .persistence.enabled }} + - name: data + mountPath: {{ .persistence.mountPath }} + {{- end }} + {{- if .extraVolumeMounts }} + {{- toYaml .extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + + {{- if $.ctx.Values.memcachedExporter.enabled }} + - name: exporter + {{- with $.ctx.Values.memcachedExporter.image }} + image: {{ .repository}}:{{ .tag }} + imagePullPolicy: {{ .pullPolicy }} + {{- end }} + ports: + - containerPort: 9150 + name: http-metrics + args: + - "--memcached.address=localhost:{{ .port }}" + - "--web.listen-address=0.0.0.0:9150" + {{- range $key, $value := $.ctx.Values.memcachedExporter.extraArgs }} + - "--{{ $key }}{{ if $value }}={{ $value }}{{ end }}" + {{- end }} + resources: + {{- toYaml $.ctx.Values.memcachedExporter.resources | nindent 12 }} + securityContext: + {{- toYaml $.ctx.Values.memcachedExporter.containerSecurityContext | nindent 12 }} + {{- if .extraVolumeMounts }} + volumeMounts: + {{- toYaml .extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- if .persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: [ "ReadWriteOnce" ] + {{- with .persistence.storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .persistence.storageSize | quote }} + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} + diff --git a/utils/assets/charts/loki/templates/memcached/_memcached-svc.tpl b/utils/assets/charts/loki/templates/memcached/_memcached-svc.tpl new file mode 100644 index 0000000..8574151 --- /dev/null +++ b/utils/assets/charts/loki/templates/memcached/_memcached-svc.tpl @@ -0,0 +1,42 @@ +{{/* +memcached Service +Params: + ctx = . context + valuesSection = name of the section in values.yaml + component = name of the component +valuesSection and component are specified separately because helm prefers camelcase for naming convetion and k8s components are named with snake case. +*/}} +{{- define "loki.memcached.service" -}} +{{ with (index $.ctx.Values $.valuesSection) }} +{{- if .enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.resourceName" (dict "ctx" $.ctx "component" $.component) }} + labels: + {{- include "loki.labels" $.ctx | nindent 4 }} + app.kubernetes.io/component: "memcached-{{ $.component }}" + {{- with .service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- toYaml .service.annotations | nindent 4 }} + namespace: {{ $.ctx.Release.Namespace | quote }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: memcached-client + port: {{ .port }} + targetPort: {{ .port }} + {{ if $.ctx.Values.memcachedExporter.enabled -}} + - name: http-metrics + port: 9150 + targetPort: 9150 + {{ end }} + selector: + {{- include "loki.selectorLabels" $.ctx | nindent 4 }} + app.kubernetes.io/component: "memcached-{{ $.component }}" +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/monitoring/_helpers-monitoring.tpl b/utils/assets/charts/loki/templates/monitoring/_helpers-monitoring.tpl new file mode 100644 index 0000000..cb693e4 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/_helpers-monitoring.tpl @@ -0,0 +1,47 @@ +{{/* +Client definition for LogsInstance +*/}} +{{- define "loki.logsInstanceClient" -}} +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- $url := printf "http://%s.%s.svc.%s:%s/loki/api/v1/push" (include "loki.writeFullname" .) .Release.Namespace .Values.global.clusterDomain ( .Values.loki.server.http_listen_port | toString ) }} +{{- if $isSingleBinary }} + {{- $url = printf "http://%s.%s.svc.%s:%s/loki/api/v1/push" (include "loki.singleBinaryFullname" .) .Release.Namespace .Values.global.clusterDomain ( .Values.loki.server.http_listen_port | toString ) }} +{{- else if .Values.gateway.enabled -}} + {{- $url = printf "http://%s.%s.svc.%s/loki/api/v1/push" (include "loki.gatewayFullname" .) .Release.Namespace .Values.global.clusterDomain }} +{{- end -}} +- url: {{ $url }} + externalLabels: + cluster: {{ include "loki.clusterLabel" . }} + {{- if .Values.enterprise.enabled }} + basicAuth: + username: + name: {{ include "enterprise-logs.selfMonitoringTenantSecret" . }} + key: username + password: + name: {{ include "enterprise-logs.selfMonitoringTenantSecret" . }} + key: password + {{- else if .Values.loki.auth_enabled }} + tenantId: {{ .Values.monitoring.selfMonitoring.tenant.name | quote }} + {{- end }} +{{- end -}} + +{{/* +Convert a recording rule group to yaml +*/}} +{{- define "loki.ruleGroupToYaml" -}} +{{- range . }} +- name: {{ .name }} + rules: + {{- toYaml .rules | nindent 4 }} +{{- end }} +{{- end }} + +{{/* +GrafanaAgent priority class name +*/}} +{{- define "grafana-agent.priorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.monitoring.selfMonitoring.grafanaAgent.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/monitoring/dashboards/_helpers-dashboards.tpl b/utils/assets/charts/loki/templates/monitoring/dashboards/_helpers-dashboards.tpl new file mode 100644 index 0000000..00fd722 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/dashboards/_helpers-dashboards.tpl @@ -0,0 +1,6 @@ +{{/* +dashboards name +*/}} +{{- define "loki.dashboardsName" -}} +{{ include "loki.name" . }}-dashboards +{{- end }} diff --git a/utils/assets/charts/loki/templates/monitoring/dashboards/configmap-1.yaml b/utils/assets/charts/loki/templates/monitoring/dashboards/configmap-1.yaml new file mode 100644 index 0000000..6352f25 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/dashboards/configmap-1.yaml @@ -0,0 +1,30 @@ +{{- with .Values.monitoring.dashboards }} +{{- if .enabled }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki.dashboardsName" $ }}-1 + namespace: {{ .namespace | default $.Release.Namespace }} + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + "loki-chunks.json": | + {{ $.Files.Get "src/dashboards/loki-chunks.json" | fromJson | toJson }} + "loki-deletion.json": | + {{ $.Files.Get "src/dashboards/loki-deletion.json" | fromJson | toJson }} + "loki-logs.json": | + {{ $.Files.Get "src/dashboards/loki-logs.json" | fromJson | toJson }} + "loki-mixin-recording-rules.json": | + {{ $.Files.Get "src/dashboards/loki-mixin-recording-rules.json" | fromJson | toJson }} + "loki-operational.json": | + {{ $.Files.Get "src/dashboards/loki-operational.json" | fromJson | toJson }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/monitoring/dashboards/configmap-2.yaml b/utils/assets/charts/loki/templates/monitoring/dashboards/configmap-2.yaml new file mode 100644 index 0000000..67d3cf4 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/dashboards/configmap-2.yaml @@ -0,0 +1,30 @@ +{{- with .Values.monitoring.dashboards }} +{{- if .enabled }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki.dashboardsName" $ }}-2 + namespace: {{ .namespace | default $.Release.Namespace }} + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +data: + "loki-reads-resources.json": | + {{ $.Files.Get "src/dashboards/loki-reads-resources.json" | fromJson | toJson }} + "loki-reads.json": | + {{ $.Files.Get "src/dashboards/loki-reads.json" | fromJson | toJson }} + "loki-retention.json": | + {{ $.Files.Get "src/dashboards/loki-retention.json" | fromJson | toJson }} + "loki-writes-resources.json": | + {{ $.Files.Get "src/dashboards/loki-writes-resources.json" | fromJson | toJson }} + "loki-writes.json": | + {{ $.Files.Get "src/dashboards/loki-writes.json" | fromJson | toJson }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/monitoring/grafana-agent.yaml b/utils/assets/charts/loki/templates/monitoring/grafana-agent.yaml new file mode 100644 index 0000000..a047e5f --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/grafana-agent.yaml @@ -0,0 +1,100 @@ +{{- if .Values.monitoring.selfMonitoring.enabled }} +{{- with .Values.monitoring.selfMonitoring.grafanaAgent }} +apiVersion: monitoring.grafana.com/v1alpha1 +kind: GrafanaAgent +metadata: + name: {{ include "loki.fullname" $ }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + serviceAccountName: {{ include "loki.fullname" $ }}-grafana-agent + enableConfigReadAPI: {{ .enableConfigReadAPI }} + {{- include "grafana-agent.priorityClassName" $ | nindent 2 }} + logs: + instanceSelector: + matchLabels: + {{- include "loki.selectorLabels" $ | nindent 8 }} + {{- with $.Values.monitoring.serviceMonitor}} + {{- if .metricsInstance.remoteWrite}} + metrics: + instanceSelector: + matchLabels: + {{- include "loki.selectorLabels" $ | nindent 8 }} + {{- end }} + {{- end }} + {{- with .resources }} + resources: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .tolerations }} + tolerations: + {{- toYaml . | nindent 4 }} + {{- end }} + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "loki.fullname" $ }}-grafana-agent + namespace: {{ .namespace | default $.Release.Namespace }} + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "loki.fullname" $ }}-grafana-agent +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - nodes/metrics + - services + - endpoints + - pods + - events + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch +- nonResourceURLs: + - /metrics + - /metrics/cadvisor + verbs: + - get + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "loki.fullname" $ }}-grafana-agent +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "loki.fullname" $ }}-grafana-agent +subjects: +- kind: ServiceAccount + name: {{ include "loki.fullname" $ }}-grafana-agent + namespace: {{ .namespace | default $.Release.Namespace }} +{{- end}} +{{- end}} diff --git a/utils/assets/charts/loki/templates/monitoring/logs-instance.yaml b/utils/assets/charts/loki/templates/monitoring/logs-instance.yaml new file mode 100644 index 0000000..5ae1917 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/logs-instance.yaml @@ -0,0 +1,30 @@ +{{- if .Values.monitoring.selfMonitoring.enabled }} +{{- with .Values.monitoring.selfMonitoring.logsInstance }} +apiVersion: monitoring.grafana.com/v1alpha1 +kind: LogsInstance +metadata: + name: {{ include "loki.fullname" $ }} + namespace: {{ $.Release.Namespace }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + clients: + {{- include "loki.logsInstanceClient" $ | nindent 4}} + {{- with .clients}} + {{- toYaml . | nindent 4 }} + {{- end }} + + podLogsNamespaceSelector: {} + + podLogsSelector: + matchLabels: + {{- include "loki.selectorLabels" $ | nindent 6 }} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/loki/templates/monitoring/loki-alerts.yaml b/utils/assets/charts/loki/templates/monitoring/loki-alerts.yaml new file mode 100644 index 0000000..f3333df --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/loki-alerts.yaml @@ -0,0 +1,22 @@ +{{- with .Values.monitoring.rules }} +{{- if and ($.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/PrometheusRule") .enabled .alerting }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "loki.fullname" $ }}-loki-alerts + namespace: {{ .namespace | default $.Release.Namespace }} +spec: + groups: + {{- include "loki.ruleGroupToYaml" (tpl ($.Files.Get "src/alerts.yaml.tpl") $ | fromYaml).groups | indent 4 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/monitoring/loki-rules.yaml b/utils/assets/charts/loki/templates/monitoring/loki-rules.yaml new file mode 100644 index 0000000..f9eb392 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/loki-rules.yaml @@ -0,0 +1,23 @@ +{{- with .Values.monitoring.rules }} +{{- if and ($.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/PrometheusRule") .enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "loki.fullname" $ }}-loki-rules + namespace: {{ .namespace | default $.Release.Namespace }} +spec: + groups: + {{- include "loki.ruleGroupToYaml" (tpl ($.Files.Get "src/rules.yaml.tpl") $ | fromYaml).groups | indent 4 }} + {{- include "loki.ruleGroupToYaml" .additionalGroups | indent 4 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/monitoring/metrics-instance.yaml b/utils/assets/charts/loki/templates/monitoring/metrics-instance.yaml new file mode 100644 index 0000000..82102c0 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/metrics-instance.yaml @@ -0,0 +1,30 @@ +{{- if .Values.monitoring.serviceMonitor.enabled }} +{{- with .Values.monitoring.serviceMonitor.metricsInstance }} +{{- if and ($.Capabilities.APIVersions.Has "monitoring.grafana.com/v1alpha1/MetricsInstance") .enabled }} +apiVersion: monitoring.grafana.com/v1alpha1 +kind: MetricsInstance +metadata: + name: {{ include "loki.fullname" $ }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .remoteWrite}} + remoteWrite: + {{- toYaml . | nindent 4 }} + {{- end }} + + serviceMonitorNamespaceSelector: {} + + serviceMonitorSelector: + matchLabels: + {{- include "loki.selectorLabels" $ | nindent 6 }} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/monitoring/pod-logs.yaml b/utils/assets/charts/loki/templates/monitoring/pod-logs.yaml new file mode 100644 index 0000000..317339d --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/pod-logs.yaml @@ -0,0 +1,62 @@ +--- +{{- if .Values.monitoring.selfMonitoring.enabled }} +{{- with .Values.monitoring.selfMonitoring.podLogs }} +apiVersion: {{ .apiVersion }} +kind: PodLogs +metadata: + name: {{ include "loki.fullname" $ }} + namespace: {{ $.Release.Namespace }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + pipelineStages: + - cri: { } + {{- with .additionalPipelineStages }} + {{- toYaml . | nindent 4 }} + {{- end }} + relabelings: + - action: replace + sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: __host__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + replacement: "$1" + separator: "-" + sourceLabels: + - __meta_kubernetes_pod_label_app_kubernetes_io_name + - __meta_kubernetes_pod_label_app_kubernetes_io_component + targetLabel: __service__ + - action: replace + replacement: "$1" + separator: "/" + sourceLabels: + - __meta_kubernetes_namespace + - __service__ + targetLabel: job + - action: replace + sourceLabels: + - __meta_kubernetes_pod_container_name + targetLabel: container + - action: replace + replacement: "{{ include "loki.clusterLabel" $ }}" + targetLabel: cluster + {{- with .relabelings }} + {{- toYaml . | nindent 4 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ $.Release.Namespace }} + selector: + matchLabels: + {{- include "loki.selectorLabels" $ | nindent 6 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/monitoring/servicemonitor.yaml b/utils/assets/charts/loki/templates/monitoring/servicemonitor.yaml new file mode 100644 index 0000000..856cee8 --- /dev/null +++ b/utils/assets/charts/loki/templates/monitoring/servicemonitor.yaml @@ -0,0 +1,63 @@ +{{- with .Values.monitoring.serviceMonitor }} +{{- if and ($.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/ServiceMonitor") .enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "loki.fullname" $ }} + namespace: {{ $.Release.Namespace }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "loki.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "loki.selectorLabels" $ | nindent 6 }} + matchExpressions: + - key: prometheus.io/service-monitor + operator: NotIn + values: + - "false" + endpoints: + - port: http-metrics + path: /metrics + {{- with .interval }} + interval: {{ . }} + {{- end }} + {{- with .scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + relabelings: + - sourceLabels: [job] + action: replace + replacement: "{{ $.Release.Namespace }}/$1" + targetLabel: job + - action: replace + replacement: "{{ include "loki.clusterLabel" $ }}" + targetLabel: cluster + {{- with .relabelings }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .scheme }} + scheme: {{ . }} + {{- end }} + {{- with .tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/networkpolicy.yaml b/utils/assets/charts/loki/templates/networkpolicy.yaml new file mode 100644 index 0000000..9286edb --- /dev/null +++ b/utils/assets/charts/loki/templates/networkpolicy.yaml @@ -0,0 +1,203 @@ +{{- if and (.Values.networkPolicy.enabled) (eq .Values.networkPolicy.flavor "kubernetes") }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki.name" . }}-namespace-only + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + policyTypes: + - Ingress + - Egress + podSelector: {} + egress: + - to: + - podSelector: {} + ingress: + - from: + - podSelector: {} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-dns + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + policyTypes: + - Egress + podSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + egress: + - ports: + - port: dns + protocol: UDP + to: + - namespaceSelector: {} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki.name" . }}-ingress + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + policyTypes: + - Ingress + podSelector: + matchExpressions: + - key: app.kubernetes.io/component + operator: In + values: + {{- if .Values.gateway.enabled }} + - gateway + {{- else }} + - read + - write + {{- end }} + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + ingress: + - ports: + - port: http-metrics + protocol: TCP + {{- if .Values.networkPolicy.ingress.namespaceSelector }} + from: + - namespaceSelector: + {{- toYaml .Values.networkPolicy.ingress.namespaceSelector | nindent 12 }} + {{- if .Values.networkPolicy.ingress.podSelector }} + podSelector: + {{- toYaml .Values.networkPolicy.ingress.podSelector | nindent 12 }} + {{- end }} + {{- end }} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki.name" . }}-ingress-metrics + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + policyTypes: + - Ingress + podSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + ingress: + - ports: + - port: http-metrics + protocol: TCP + {{- if .Values.networkPolicy.metrics.cidrs }} + from: + {{- range $cidr := .Values.networkPolicy.metrics.cidrs }} + - ipBlock: + cidr: {{ $cidr }} + {{- end }} + {{- if .Values.networkPolicy.metrics.namespaceSelector }} + - namespaceSelector: + {{- toYaml .Values.networkPolicy.metrics.namespaceSelector | nindent 12 }} + {{- if .Values.networkPolicy.metrics.podSelector }} + podSelector: + {{- toYaml .Values.networkPolicy.metrics.podSelector | nindent 12 }} + {{- end }} + {{- end }} + {{- end }} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-alertmanager + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + policyTypes: + - Egress + podSelector: + matchLabels: + {{- include "loki.backendSelectorLabels" . | nindent 6 }} + egress: + - ports: + - port: {{ .Values.networkPolicy.alertmanager.port }} + protocol: TCP + {{- if .Values.networkPolicy.alertmanager.namespaceSelector }} + to: + - namespaceSelector: + {{- toYaml .Values.networkPolicy.alertmanager.namespaceSelector | nindent 12 }} + {{- if .Values.networkPolicy.alertmanager.podSelector }} + podSelector: + {{- toYaml .Values.networkPolicy.alertmanager.podSelector | nindent 12 }} + {{- end }} + {{- end }} + +{{- if .Values.networkPolicy.externalStorage.ports }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-external-storage + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + policyTypes: + - Egress + podSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + egress: + - ports: + {{- range $port := .Values.networkPolicy.externalStorage.ports }} + - port: {{ $port }} + protocol: TCP + {{- end }} + {{- if .Values.networkPolicy.externalStorage.cidrs }} + to: + {{- range $cidr := .Values.networkPolicy.externalStorage.cidrs }} + - ipBlock: + cidr: {{ $cidr }} + {{- end }} + {{- end }} +{{- end }} + +{{- end }} + +{{- if and .Values.networkPolicy.discovery.port (eq .Values.networkPolicy.flavor "kubernetes") }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki.name" . }}-egress-discovery + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + policyTypes: + - Egress + podSelector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + egress: + - ports: + - port: {{ .Values.networkPolicy.discovery.port }} + protocol: TCP + {{- if .Values.networkPolicy.discovery.namespaceSelector }} + to: + - namespaceSelector: + {{- toYaml .Values.networkPolicy.discovery.namespaceSelector | nindent 12 }} + {{- if .Values.networkPolicy.discovery.podSelector }} + podSelector: + {{- toYaml .Values.networkPolicy.discovery.podSelector | nindent 12 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/pattern-ingester/_helpers-pattern-ingester.tpl b/utils/assets/charts/loki/templates/pattern-ingester/_helpers-pattern-ingester.tpl new file mode 100644 index 0000000..5477214 --- /dev/null +++ b/utils/assets/charts/loki/templates/pattern-ingester/_helpers-pattern-ingester.tpl @@ -0,0 +1,58 @@ +{{/* +pattern ingester fullname +*/}} +{{- define "loki.patternIngesterFullname" -}} +{{ include "loki.fullname" . }}-pattern-ingester +{{- end }} + +{{/* +pattern ingester common labels +*/}} +{{- define "loki.patternIngesterLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: pattern-ingester +{{- end }} + +{{/* +pattern ingester selector labels +*/}} +{{- define "loki.patternIngesterSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: pattern-ingester +{{- end }} + +{{/* +pattern ingester readinessProbe +*/}} +{{- define "loki.patternIngester.readinessProbe" -}} +{{- with .Values.patternIngester.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- else }} +{{- with .Values.loki.readinessProbe }} +readinessProbe: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +pattern ingester priority class name +*/}} +{{- define "loki.patternIngesterPriorityClassName" }} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.patternIngester.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} + +{{/* +Create the name of the pattern ingester service account +*/}} +{{- define "loki.patternIngesterServiceAccountName" -}} +{{- if .Values.patternIngester.serviceAccount.create -}} + {{ default (print (include "loki.serviceAccountName" .) "-pattern-ingester") .Values.patternIngester.serviceAccount.name }} +{{- else -}} + {{ default (include "loki.serviceAccountName" .) .Values.patternIngester.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/pattern-ingester/statefulset-pattern-ingester.yaml b/utils/assets/charts/loki/templates/pattern-ingester/statefulset-pattern-ingester.yaml new file mode 100644 index 0000000..fdd2a74 --- /dev/null +++ b/utils/assets/charts/loki/templates/pattern-ingester/statefulset-pattern-ingester.yaml @@ -0,0 +1,187 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +{{- if (gt (int .Values.patternIngester.replicas) 0) -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.patternIngesterFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.patternIngesterLabels" . | nindent 4 }} + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.patternIngester.replicas }} + podManagementPolicy: Parallel + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ include "loki.patternIngesterFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.patternIngester.persistence.enableStatefulSetAutoDeletePVC) }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.patternIngester.persistence.whenDeleted }} + whenScaled: {{ .Values.patternIngester.persistence.whenScaled }} + {{- end }} + selector: + matchLabels: + {{- include "loki.patternIngesterSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.patternIngester.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.patternIngesterSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.patternIngester.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.patternIngester.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.patternIngesterPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.patternIngester.terminationGracePeriodSeconds }} + {{- with .Values.patternIngester.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: pattern-ingester + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.patternIngester.command }} + command: + - {{ coalesce .Values.patternIngester.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=pattern-ingester + {{- with .Values.patternIngester.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.patternIngester.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.patternIngester.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + {{- include "loki.patternIngester.readinessProbe" . | nindent 10 }} + volumeMounts: + - name: temp + mountPath: /tmp + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.patternIngester.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.patternIngester.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.patternIngester.extraContainers }} + {{- toYaml .Values.patternIngester.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.patternIngester.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.patternIngester.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.patternIngester.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.patternIngester.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: temp + emptyDir: {} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- if not .Values.patternIngester.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- with .Values.patternIngester.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.patternIngester.persistence.enabled }} + volumeClaimTemplates: + {{- range .Values.patternIngester.persistence.claims }} + - metadata: + name: {{ .name }} + {{- with .annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- end }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/podsecuritypolicy.yaml b/utils/assets/charts/loki/templates/podsecuritypolicy.yaml new file mode 100644 index 0000000..05470d9 --- /dev/null +++ b/utils/assets/charts/loki/templates/podsecuritypolicy.yaml @@ -0,0 +1,41 @@ +{{- if .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "loki.name" . }} + labels: + {{- include "loki.labels" . | nindent 4 }} +{{- if .Values.rbac.pspAnnotations }} + annotations: +{{ toYaml .Values.rbac.pspAnnotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'persistentVolumeClaim' + - 'secret' + - 'projected' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: true + requiredDropCapabilities: + - ALL +{{- end }} diff --git a/utils/assets/charts/loki/templates/provisioner/_helpers.yaml b/utils/assets/charts/loki/templates/provisioner/_helpers.yaml new file mode 100644 index 0000000..8b04b07 --- /dev/null +++ b/utils/assets/charts/loki/templates/provisioner/_helpers.yaml @@ -0,0 +1,32 @@ +{{/* +provisioner fullname +*/}} +{{- define "enterprise-logs.provisionerFullname" -}} +{{ include "loki.name" . }}-provisioner +{{- end }} + +{{/* +provisioner common labels +*/}} +{{- define "enterprise-logs.provisionerLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: provisioner +{{- end }} + +{{/* +provisioner selector labels +*/}} +{{- define "enterprise-logs.provisionerSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: provisioner +{{- end }} + +{{/* +provisioner image name +*/}} +{{- define "enterprise-logs.provisionerImage" -}} +{{- $dict := dict "service" .Values.enterprise.provisioner.image "global" .Values.global.image "defaultVersion" "latest" -}} +{{- include "loki.baseImage" $dict -}} +{{- end -}} + + diff --git a/utils/assets/charts/loki/templates/provisioner/job-provisioner.yaml b/utils/assets/charts/loki/templates/provisioner/job-provisioner.yaml new file mode 100644 index 0000000..5a6bc06 --- /dev/null +++ b/utils/assets/charts/loki/templates/provisioner/job-provisioner.yaml @@ -0,0 +1,147 @@ +{{ if and .Values.enterprise.provisioner.enabled .Values.enterprise.enabled }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "enterprise-logs.provisionerFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "enterprise-logs.provisionerLabels" . | nindent 4 }} + {{- with .Values.enterprise.provisioner.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.provisioner.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install + "helm.sh/hook-weight": "15" +spec: + backoffLimit: 6 + completions: 1 + parallelism: 1 + template: + metadata: + labels: + {{- include "enterprise-logs.provisionerSelectorLabels" . | nindent 8 }} + {{- with .Values.enterprise.provisioner.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.enterprise.provisioner.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.enterprise.provisioner.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + securityContext: + {{- toYaml .Values.enterprise.provisioner.securityContext | nindent 8 }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: + - name: provisioner + image: {{ template "enterprise-logs.provisionerImage" . }} + imagePullPolicy: {{ .Values.enterprise.provisioner.image.pullPolicy }} + command: + - /bin/sh + - -exuc + - | + {{- range .Values.enterprise.provisioner.additionalTenants }} + /usr/bin/enterprise-logs-provisioner \ + -bootstrap-path=/bootstrap \ + -cluster-name={{ include "loki.clusterName" $ }} \ + -gel-url={{ include "loki.address" $ }} \ + -instance={{ .name }} \ + -access-policy=write-{{ .name }}:{{ .name }}:logs:write \ + -access-policy=read-{{ .name }}:{{ .name }}:logs:read \ + -token=write-{{ .name }} \ + -token=read-{{ .name }} + {{- end -}} + + {{- with .Values.monitoring.selfMonitoring.tenant }} + /usr/bin/enterprise-logs-provisioner \ + -bootstrap-path=/bootstrap \ + -cluster-name={{ include "loki.clusterName" $ }} \ + -gel-url={{ include "loki.address" $ }} \ + -instance={{ .name }} \ + -access-policy=self-monitoring:{{ .name }}:logs:write,logs:read \ + -token=self-monitoring + {{- end }} + volumeMounts: + {{- with .Values.enterprise.provisioner.extraVolumeMounts }} + {{ toYaml . | nindent 12 }} + {{- end }} + - name: bootstrap + mountPath: /bootstrap + - name: admin-token + mountPath: /bootstrap/token + subPath: token + {{- with .Values.enterprise.provisioner.env }} + env: + {{ toYaml . | nindent 12 }} + {{- end }} + containers: + - name: create-secret + image: {{ include "loki.kubectlImage" . }} + imagePullPolicy: {{ .Values.kubectlImage.pullPolicy }} + command: + - /bin/bash + - -exuc + - | + # In case, the admin resources have already been created, the provisioner job + # does not write the token files to the bootstrap mount. + # Therefore, secrets are only created if the respective token files exist. + # Note: the following bash commands should always return a success status code. + # Therefore, in case the token file does not exist, the first clause of the + # or-operation is successful. + {{- range .Values.enterprise.provisioner.additionalTenants }} + ! test -s /bootstrap/token-write-{{ .name }} || \ + kubectl --namespace "{{ .secretNamespace }}" create secret generic "{{ include "enterprise-logs.provisionedSecretPrefix" $ }}-{{ .name }}" \ + --from-literal=token-write="$(cat /bootstrap/token-write-{{ .name }})" \ + --from-literal=token-read="$(cat /bootstrap/token-read-{{ .name }})" + {{- end }} + {{- $namespace := $.Release.Namespace }} + {{- with .Values.monitoring.selfMonitoring.tenant }} + {{- $secretNamespace := tpl .secretNamespace $ }} + ! test -s /bootstrap/token-self-monitoring || \ + kubectl --namespace "{{ $namespace }}" create secret generic "{{ include "enterprise-logs.selfMonitoringTenantSecret" $ }}" \ + --from-literal=username="{{ .name }}" \ + --from-literal=password="$(cat /bootstrap/token-self-monitoring)" + {{- if not (eq $secretNamespace $namespace) }} + ! test -s /bootstrap/token-self-monitoring || \ + kubectl --namespace "{{ $secretNamespace }}" create secret generic "{{ include "enterprise-logs.selfMonitoringTenantSecret" $ }}" \ + --from-literal=username="{{ .name }}" \ + --from-literal=password="$(cat /bootstrap/token-self-monitoring)" + {{- end }} + {{- end }} + volumeMounts: + {{- with .Values.enterprise.provisioner.extraVolumeMounts }} + {{ toYaml . | nindent 12 }} + {{- end }} + - name: bootstrap + mountPath: /bootstrap + {{- with .Values.enterprise.provisioner.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.enterprise.provisioner.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.enterprise.provisioner.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + restartPolicy: OnFailure + serviceAccount: {{ include "enterprise-logs.provisionerFullname" . }} + serviceAccountName: {{ include "enterprise-logs.provisionerFullname" . }} + volumes: + - name: admin-token + secret: + secretName: "{{ include "enterprise-logs.adminTokenSecret" . }}" + - name: bootstrap + emptyDir: {} +{{- end }} diff --git a/utils/assets/charts/loki/templates/provisioner/role-provisioner.yaml b/utils/assets/charts/loki/templates/provisioner/role-provisioner.yaml new file mode 100644 index 0000000..1335b0f --- /dev/null +++ b/utils/assets/charts/loki/templates/provisioner/role-provisioner.yaml @@ -0,0 +1,21 @@ +{{ if and (and .Values.enterprise.provisioner.enabled .Values.enterprise.enabled) (not .Values.rbac.namespaced)}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "enterprise-logs.provisionerFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "enterprise-logs.provisionerLabels" . | nindent 4 }} + {{- with .Values.enterprise.provisioner.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.provisioner.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create"] +{{- end }} diff --git a/utils/assets/charts/loki/templates/provisioner/rolebinding-provisioner.yaml b/utils/assets/charts/loki/templates/provisioner/rolebinding-provisioner.yaml new file mode 100644 index 0000000..d87874d --- /dev/null +++ b/utils/assets/charts/loki/templates/provisioner/rolebinding-provisioner.yaml @@ -0,0 +1,26 @@ +{{ if and (and .Values.enterprise.provisioner.enabled .Values.enterprise.enabled) (not .Values.rbac.namespaced)}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "enterprise-logs.provisionerFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "enterprise-logs.provisionerLabels" . | nindent 4 }} + {{- with .Values.enterprise.provisioner.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.provisioner.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "enterprise-logs.provisionerFullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "enterprise-logs.provisionerFullname" . }} + namespace: {{ $.Release.Namespace }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/provisioner/serviceaccount-provisioner.yaml b/utils/assets/charts/loki/templates/provisioner/serviceaccount-provisioner.yaml new file mode 100644 index 0000000..81e92e9 --- /dev/null +++ b/utils/assets/charts/loki/templates/provisioner/serviceaccount-provisioner.yaml @@ -0,0 +1,18 @@ +{{ if and .Values.enterprise.provisioner.enabled .Values.enterprise.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "enterprise-logs.provisionerFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "enterprise-logs.provisionerLabels" . | nindent 4 }} + {{- with .Values.enterprise.provisioner.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.provisioner.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install +{{- end }} diff --git a/utils/assets/charts/loki/templates/querier/_helpers-querier.tpl b/utils/assets/charts/loki/templates/querier/_helpers-querier.tpl new file mode 100644 index 0000000..aa557c5 --- /dev/null +++ b/utils/assets/charts/loki/templates/querier/_helpers-querier.tpl @@ -0,0 +1,32 @@ +{{/* +querier fullname +*/}} +{{- define "loki.querierFullname" -}} +{{ include "loki.fullname" . }}-querier +{{- end }} + +{{/* +querier common labels +*/}} +{{- define "loki.querierLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: querier +{{- end }} + +{{/* +querier selector labels +*/}} +{{- define "loki.querierSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: querier +{{- end }} + +{{/* +querier priority class name +*/}} +{{- define "loki.querierPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.querier.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/querier/deployment-querier.yaml b/utils/assets/charts/loki/templates/querier/deployment-querier.yaml new file mode 100644 index 0000000..3165d0d --- /dev/null +++ b/utils/assets/charts/loki/templates/querier/deployment-querier.yaml @@ -0,0 +1,166 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.querierFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.querierLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.querier.autoscaling.enabled }} + replicas: {{ .Values.querier.replicas }} +{{- end }} + strategy: + rollingUpdate: + maxSurge: {{ .Values.querier.maxSurge }} + maxUnavailable: 1 + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.querierSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.querier.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.querierSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.querier.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.querier.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.querier.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.querierPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.querier.terminationGracePeriodSeconds }} + {{- with .Values.querier.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: querier + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=querier + {{- if .Values.ingester.zoneAwareReplication.enabled }} + {{- if and (.Values.ingester.zoneAwareReplication.migration.enabled) (not .Values.ingester.zoneAwareReplication.migration.readPath) }} + - -distributor.zone-awareness-enabled=false + {{- else }} + - -distributor.zone-awareness-enabled=true + {{- end }} + {{- end }} + {{- with .Values.querier.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.querier.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.querier.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + livenessProbe: + {{- toYaml .Values.loki.livenessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.querier.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.querier.resources | nindent 12 }} + {{- if .Values.querier.extraContainers }} + {{- toYaml .Values.querier.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.querier.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.querier.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.querier.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.querier.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + - name: data + emptyDir: {} + {{- with .Values.querier.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/querier/hpa.yaml b/utils/assets/charts/loki/templates/querier/hpa.yaml new file mode 100644 index 0000000..08d81cb --- /dev/null +++ b/utils/assets/charts/loki/templates/querier/hpa.yaml @@ -0,0 +1,55 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.querier.autoscaling.enabled }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.querierFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.querierLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "loki.querierFullname" . }} + minReplicas: {{ .Values.querier.autoscaling.minReplicas }} + maxReplicas: {{ .Values.querier.autoscaling.maxReplicas }} + metrics: + {{- with .Values.querier.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.querier.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.querier.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.querier.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.querier.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.querier.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/querier/poddisruptionbudget-querier.yaml b/utils/assets/charts/loki/templates/querier/poddisruptionbudget-querier.yaml new file mode 100644 index 0000000..9dff3cd --- /dev/null +++ b/utils/assets/charts/loki/templates/querier/poddisruptionbudget-querier.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.querier.replicas) 1) }} +{{- if kindIs "invalid" .Values.querier.maxUnavailable }} +{{- fail "`.Values.querier.maxUnavailable` must be set when `.Values.querier.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.querierFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.querierLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.querierSelectorLabels" . | nindent 6 }} + {{- with .Values.querier.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/querier/service-querier.yaml b/utils/assets/charts/loki/templates/querier/service-querier.yaml new file mode 100644 index 0000000..15c9c6a --- /dev/null +++ b/utils/assets/charts/loki/templates/querier/service-querier.yaml @@ -0,0 +1,36 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.querierFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.querierLabels" . | nindent 4 }} + {{- with .Values.querier.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.querier.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.querier.appProtocol.grpc }} + appProtocol: {{ .Values.querier.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.querierSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/query-frontend/_helpers-query-frontend.tpl b/utils/assets/charts/loki/templates/query-frontend/_helpers-query-frontend.tpl new file mode 100644 index 0000000..5aebde7 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-frontend/_helpers-query-frontend.tpl @@ -0,0 +1,32 @@ +{{/* +query-frontend fullname +*/}} +{{- define "loki.queryFrontendFullname" -}} +{{ include "loki.fullname" . }}-query-frontend +{{- end }} + +{{/* +query-frontend common labels +*/}} +{{- define "loki.queryFrontendLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: query-frontend +{{- end }} + +{{/* +query-frontend selector labels +*/}} +{{- define "loki.queryFrontendSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: query-frontend +{{- end }} + +{{/* +query-frontend priority class name +*/}} +{{- define "loki.queryFrontendPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.queryFrontend.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/query-frontend/deployment-query-frontend.yaml b/utils/assets/charts/loki/templates/query-frontend/deployment-query-frontend.yaml new file mode 100644 index 0000000..0b73fe8 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-frontend/deployment-query-frontend.yaml @@ -0,0 +1,148 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.queryFrontendFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.queryFrontendLabels" . | nindent 4 }} + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.queryFrontend.autoscaling.enabled }} + replicas: {{ .Values.queryFrontend.replicas }} +{{- end }} + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.queryFrontendSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.queryFrontendSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.queryFrontend.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.queryFrontendPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.queryFrontend.terminationGracePeriodSeconds }} + containers: + - name: query-frontend + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + {{- if or .Values.loki.command .Values.queryFrontend.command }} + command: + - {{ coalesce .Values.queryFrontend.command .Values.loki.command | quote }} + {{- end }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=query-frontend + {{- with .Values.queryFrontend.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.queryFrontend.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.queryFrontend.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.queryFrontend.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.queryFrontend.resources | nindent 12 }} + {{- if .Values.queryFrontend.extraContainers }} + {{- toYaml .Values.queryFrontend.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.queryFrontend.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.queryFrontend.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/query-frontend/hpa.yaml b/utils/assets/charts/loki/templates/query-frontend/hpa.yaml new file mode 100644 index 0000000..c326287 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-frontend/hpa.yaml @@ -0,0 +1,55 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.queryFrontend.autoscaling.enabled }} +{{- $apiVersion := include "loki.hpa.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.queryFrontendFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.queryFrontendLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "loki.queryFrontendFullname" . }} + minReplicas: {{ .Values.queryFrontend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.queryFrontend.autoscaling.maxReplicas }} + metrics: + {{- with .Values.queryFrontend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.queryFrontend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if (eq $apiVersion "autoscaling/v2") }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.queryFrontend.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.queryFrontend.autoscaling.behavior.enabled }} + behavior: + {{- with .Values.queryFrontend.autoscaling.behavior.scaleDown }} + scaleDown: {{ toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.queryFrontend.autoscaling.behavior.scaleUp }} + scaleUp: {{ toYaml . | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/query-frontend/poddisruptionbudget-query-frontend.yaml b/utils/assets/charts/loki/templates/query-frontend/poddisruptionbudget-query-frontend.yaml new file mode 100644 index 0000000..f100405 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-frontend/poddisruptionbudget-query-frontend.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.queryFrontend.replicas) 1) }} +{{- if kindIs "invalid" .Values.queryFrontend.maxUnavailable }} +{{- fail "`.Values.queryFrontend.maxUnavailable` must be set when `.Values.queryFrontend.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.queryFrontendFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.queryFrontendLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.queryFrontendSelectorLabels" . | nindent 6 }} + {{- with .Values.queryFrontend.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/query-frontend/service-query-frontend-headless.yaml b/utils/assets/charts/loki/templates/query-frontend/service-query-frontend-headless.yaml new file mode 100644 index 0000000..8da9054 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-frontend/service-query-frontend-headless.yaml @@ -0,0 +1,46 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.queryFrontendFullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.queryFrontendLabels" . | nindent 4 }} + {{- with .Values.queryFrontend.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.queryFrontend.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + clusterIP: None + type: ClusterIP + publishNotReadyAddresses: true + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.queryFrontend.appProtocol.grpc }} + appProtocol: {{ .Values.queryFrontend.appProtocol.grpc }} + {{- end }} + - name: grpclb + port: 9096 + targetPort: grpc + protocol: TCP + {{- if .Values.queryFrontend.appProtocol.grpc }} + appProtocol: {{ .Values.queryFrontend.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.queryFrontendSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/query-frontend/service-query-frontend.yaml b/utils/assets/charts/loki/templates/query-frontend/service-query-frontend.yaml new file mode 100644 index 0000000..a239695 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-frontend/service-query-frontend.yaml @@ -0,0 +1,44 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.queryFrontendFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.queryFrontendLabels" . | nindent 4 }} + {{- with .Values.queryFrontend.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.queryFrontend.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + publishNotReadyAddresses: true + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- if .Values.queryFrontend.appProtocol.grpc }} + appProtocol: {{ .Values.queryFrontend.appProtocol.grpc }} + {{- end }} + - name: grpclb + port: 9096 + targetPort: grpc + protocol: TCP + {{- if .Values.queryFrontend.appProtocol.grpc }} + appProtocol: {{ .Values.queryFrontend.appProtocol.grpc }} + {{- end }} + selector: + {{- include "loki.queryFrontendSelectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/loki/templates/query-scheduler/_helpers-query-scheduler.tpl b/utils/assets/charts/loki/templates/query-scheduler/_helpers-query-scheduler.tpl new file mode 100644 index 0000000..1f64802 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-scheduler/_helpers-query-scheduler.tpl @@ -0,0 +1,40 @@ +{{/* +query-scheduler fullname +*/}} +{{- define "loki.querySchedulerFullname" -}} +{{ include "loki.fullname" . }}-query-scheduler +{{- end }} + +{{/* +query-scheduler common labels +*/}} +{{- define "loki.querySchedulerLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: query-scheduler +{{- end }} + +{{/* +query-scheduler selector labels +*/}} +{{- define "loki.querySchedulerSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: query-scheduler +{{- end }} + +{{/* +query-scheduler image +*/}} +{{- define "loki.querySchedulerImage" -}} +{{- $dict := dict "loki" .Values.loki.image "service" .Values.queryScheduler.image "global" .Values.global.image "defaultVersion" .Chart.AppVersion -}} +{{- include "loki.lokiImage" $dict -}} +{{- end }} + +{{/* +query-scheduler priority class name +*/}} +{{- define "loki.querySchedulerPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.queryScheduler.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/query-scheduler/deployment-query-scheduler.yaml b/utils/assets/charts/loki/templates/query-scheduler/deployment-query-scheduler.yaml new file mode 100644 index 0000000..fbb1f28 --- /dev/null +++ b/utils/assets/charts/loki/templates/query-scheduler/deployment-query-scheduler.yaml @@ -0,0 +1,146 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.querySchedulerFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.querySchedulerLabels" . | nindent 4 }} + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.queryScheduler.replicas }} + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.querySchedulerSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryScheduler.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.querySchedulerSelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryScheduler.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + app.kubernetes.io/part-of: memberlist + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.queryScheduler.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryScheduler.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.querySchedulerPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.queryScheduler.terminationGracePeriodSeconds }} + containers: + - name: query-scheduler + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=query-scheduler + {{- with .Values.queryScheduler.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.queryScheduler.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.queryScheduler.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + livenessProbe: + {{- toYaml .Values.loki.livenessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.queryScheduler.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.queryScheduler.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.queryScheduler.extraContainers }} + {{- toYaml .Values.queryScheduler.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.queryScheduler.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryScheduler.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryScheduler.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.queryScheduler.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/query-scheduler/poddisruptionbudget-query-scheduler.yaml b/utils/assets/charts/loki/templates/query-scheduler/poddisruptionbudget-query-scheduler.yaml new file mode 100644 index 0000000..ed8051f --- /dev/null +++ b/utils/assets/charts/loki/templates/query-scheduler/poddisruptionbudget-query-scheduler.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.queryScheduler.replicas) 1) }} +{{- if kindIs "invalid" .Values.queryScheduler.maxUnavailable }} +{{- fail "`.Values.queryScheduler.maxUnavailable` must be set when `.Values.queryScheduler.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.querySchedulerFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.querySchedulerLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.querySchedulerSelectorLabels" . | nindent 6 }} + {{- with .Values.queryScheduler.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/query-scheduler/service-query-scheduler.yaml b/utils/assets/charts/loki/templates/query-scheduler/service-query-scheduler.yaml new file mode 100644 index 0000000..746c7bd --- /dev/null +++ b/utils/assets/charts/loki/templates/query-scheduler/service-query-scheduler.yaml @@ -0,0 +1,38 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.querySchedulerFullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.querySchedulerLabels" . | nindent 4 }} + {{- with .Values.queryScheduler.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.queryScheduler.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpclb + port: 9095 + targetPort: grpc + protocol: TCP + {{- with .Values.queryScheduler.appProtocol.grpc }} + appProtocol: {{ . }} + {{- end }} + selector: + {{- include "loki.querySchedulerSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/read/_helpers-read.tpl b/utils/assets/charts/loki/templates/read/_helpers-read.tpl new file mode 100644 index 0000000..d205314 --- /dev/null +++ b/utils/assets/charts/loki/templates/read/_helpers-read.tpl @@ -0,0 +1,32 @@ +{{/* +read fullname +*/}} +{{- define "loki.readFullname" -}} +{{ include "loki.name" . }}-read +{{- end }} + +{{/* +read common labels +*/}} +{{- define "loki.readLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: read +{{- end }} + +{{/* +read selector labels +*/}} +{{- define "loki.readSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: read +{{- end }} + +{{/* +read priority class name +*/}} +{{- define "loki.readPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.read.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/read/deployment-read.yaml b/utils/assets/charts/loki/templates/read/deployment-read.yaml new file mode 100644 index 0000000..f024a40 --- /dev/null +++ b/utils/assets/charts/loki/templates/read/deployment-read.yaml @@ -0,0 +1,163 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (not .Values.read.legacyReadTarget ) }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.readFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + app.kubernetes.io/part-of: memberlist + {{- include "loki.readLabels" . | nindent 4 }} + {{- if or (not (empty .Values.loki.annotations)) (not (empty .Values.backend.annotations))}} + annotations: + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.read.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + {{- if not .Values.read.autoscaling.enabled }} + replicas: {{ .Values.read.replicas }} + {{- end }} + strategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.readSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/part-of: memberlist + {{- include "loki.readSelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.selectorLabels }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.readPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.read.terminationGracePeriodSeconds }} + containers: + - name: loki + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target={{ .Values.read.targetModule }} + - -legacy-read-mode=false + - -common.compactor-grpc-address={{ include "loki.backendFullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.global.clusterDomain }}:{{ .Values.loki.server.grpc_listen_port }} + {{- with .Values.read.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.loki.server.http_listen_port }} + protocol: TCP + - name: grpc + containerPort: {{ .Values.loki.server.grpc_listen_port }} + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.read.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.read.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: tmp + mountPath: /tmp + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end}} + {{- with .Values.read.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.read.resources | nindent 12 }} + {{- with .Values.read.extraContainers }} + {{- toYaml . | nindent 8}} + {{- end }} + {{- with .Values.read.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.dnsConfig }} + dnsConfig: + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.read.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: tmp + emptyDir: {} + - name: data + emptyDir: {} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.read.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/read/hpa.yaml b/utils/assets/charts/loki/templates/read/hpa.yaml new file mode 100644 index 0000000..5515ecb --- /dev/null +++ b/utils/assets/charts/loki/templates/read/hpa.yaml @@ -0,0 +1,55 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- $autoscalingv2 := .Capabilities.APIVersions.Has "autoscaling/v2" -}} +{{- if and $isSimpleScalable ( .Values.read.autoscaling.enabled ) }} +{{- if $autoscalingv2 }} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta1 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.readFullname" . }} + labels: + {{- include "loki.readLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 +{{- if and $isSimpleScalable (not .Values.read.legacyReadTarget ) }} + kind: Deployment + name: {{ include "loki.readFullname" . }} +{{- else }} + kind: StatefulSet + name: {{ include "loki.readFullname" . }} +{{- end }} + minReplicas: {{ .Values.read.autoscaling.minReplicas }} + maxReplicas: {{ .Values.read.autoscaling.maxReplicas }} + {{- with .Values.read.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} + metrics: + {{- with .Values.read.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.read.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/read/poddisruptionbudget-read.yaml b/utils/assets/charts/loki/templates/read/poddisruptionbudget-read.yaml new file mode 100644 index 0000000..af4fcbf --- /dev/null +++ b/utils/assets/charts/loki/templates/read/poddisruptionbudget-read.yaml @@ -0,0 +1,15 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (gt (int .Values.read.replicas) 1) }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.readFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.readLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.readSelectorLabels" . | nindent 6 }} + maxUnavailable: 1 +{{- end }} diff --git a/utils/assets/charts/loki/templates/read/service-read-headless.yaml b/utils/assets/charts/loki/templates/read/service-read-headless.yaml new file mode 100644 index 0000000..14ba0f6 --- /dev/null +++ b/utils/assets/charts/loki/templates/read/service-read-headless.yaml @@ -0,0 +1,41 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{ if $isSimpleScalable }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.readFullname" . }}-headless + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.readSelectorLabels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.read.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + variant: headless + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.read.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + appProtocol: tcp + selector: + {{- include "loki.readSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/read/service-read.yaml b/utils/assets/charts/loki/templates/read/service-read.yaml new file mode 100644 index 0000000..f4000fd --- /dev/null +++ b/utils/assets/charts/loki/templates/read/service-read.yaml @@ -0,0 +1,37 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if $isSimpleScalable }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.readFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.readLabels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.read.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.read.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + selector: + {{- include "loki.readSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/read/statefulset-read.yaml b/utils/assets/charts/loki/templates/read/statefulset-read.yaml new file mode 100644 index 0000000..93527f9 --- /dev/null +++ b/utils/assets/charts/loki/templates/read/statefulset-read.yaml @@ -0,0 +1,200 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (.Values.read.legacyReadTarget ) }} +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.readFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + app.kubernetes.io/part-of: memberlist + {{- include "loki.readLabels" . | nindent 4 }} + {{- if or (not (empty .Values.loki.annotations)) (not (empty .Values.read.annotations))}} + annotations: + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.read.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: +{{- if not .Values.read.autoscaling.enabled }} + {{- if eq .Values.deploymentMode "SingleBinary" }} + replicas: 0 + {{- else }} + replicas: {{ .Values.read.replicas }} + {{- end }} +{{- end }} + podManagementPolicy: {{ .Values.read.podManagementPolicy }} + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ printf "%s-headless" (include "loki.readFullname" .) }} + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.read.persistence.enableStatefulSetAutoDeletePVC) }} + {{/* + Data on the read nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: Delete + whenScaled: Delete + {{- end }} + selector: + matchLabels: + {{- include "loki.readSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/part-of: memberlist + {{- include "loki.readSelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.selectorLabels }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + {{ include "loki.enableServiceLinks" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.readPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.read.terminationGracePeriodSeconds }} + containers: + - name: loki + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target={{ .Values.read.targetModule }} + {{- with .Values.read.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.loki.server.http_listen_port }} + protocol: TCP + - name: grpc + containerPort: {{ .Values.loki.server.grpc_listen_port }} + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.read.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.read.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + {{- with .Values.read.lifecycle }} + lifecycle: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: tmp + mountPath: /tmp + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end}} + {{- with .Values.read.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.read.resources | nindent 12 }} + {{- with .Values.read.extraContainers }} + {{- toYaml . | nindent 8}} + {{- end }} + {{- with .Values.read.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.dnsConfig }} + dnsConfig: + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.read.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.read.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: tmp + emptyDir: {} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.read.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + {{- with .Values.read.persistence.annotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .Values.read.persistence.storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .Values.read.persistence.size | quote }} + {{- with .Values.read.persistence.selector }} + selector: + {{- toYaml . | nindent 10 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/results-cache/poddisruptionbudget-results-cache.yaml b/utils/assets/charts/loki/templates/results-cache/poddisruptionbudget-results-cache.yaml new file mode 100644 index 0000000..6bc393a --- /dev/null +++ b/utils/assets/charts/loki/templates/results-cache/poddisruptionbudget-results-cache.yaml @@ -0,0 +1,16 @@ +{{- if .Values.resultsCache.enabled }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.fullname" . }}-memcached-results-cache + namespace: {{ .Release.Namespace }} + labels: + {{- include "loki.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: memcached-results-cache +spec: + selector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: memcached-results-cache + maxUnavailable: 1 +{{- end -}} diff --git a/utils/assets/charts/loki/templates/results-cache/service-results-cache-headless.yaml b/utils/assets/charts/loki/templates/results-cache/service-results-cache-headless.yaml new file mode 100644 index 0000000..ce92008 --- /dev/null +++ b/utils/assets/charts/loki/templates/results-cache/service-results-cache-headless.yaml @@ -0,0 +1 @@ +{{- include "loki.memcached.service" (dict "ctx" $ "valuesSection" "resultsCache" "component" "results-cache" ) }} diff --git a/utils/assets/charts/loki/templates/results-cache/statefulset-results-cache.yaml b/utils/assets/charts/loki/templates/results-cache/statefulset-results-cache.yaml new file mode 100644 index 0000000..042e74e --- /dev/null +++ b/utils/assets/charts/loki/templates/results-cache/statefulset-results-cache.yaml @@ -0,0 +1 @@ +{{- include "loki.memcached.statefulSet" (dict "ctx" $ "valuesSection" "resultsCache" "component" "results-cache" ) }} diff --git a/utils/assets/charts/loki/templates/role.yaml b/utils/assets/charts/loki/templates/role.yaml new file mode 100644 index 0000000..1e714b6 --- /dev/null +++ b/utils/assets/charts/loki/templates/role.yaml @@ -0,0 +1,36 @@ +{{- if or .Values.rbac.pspEnabled .Values.rbac.sccEnabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "loki.name" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +{{- if .Values.rbac.pspEnabled }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ include "loki.name" . }} +{{- end }} +{{- if .Values.rbac.sccEnabled }} +rules: + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - use + resourceNames: + - {{ include "loki.name" . }} + {{- if and .Values.rbac.namespaced .Values.sidecar.rules.enabled }} + - apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/rolebinding.yaml b/utils/assets/charts/loki/templates/rolebinding.yaml new file mode 100644 index 0000000..cc0dfd2 --- /dev/null +++ b/utils/assets/charts/loki/templates/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if or .Values.rbac.pspEnabled .Values.rbac.sccEnabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "loki.name" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "loki.name" . }} +subjects: + - kind: ServiceAccount + name: {{ include "loki.serviceAccountName" . }} + namespace: {{ $.Release.Namespace }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ruler/_helpers-ruler.tpl b/utils/assets/charts/loki/templates/ruler/_helpers-ruler.tpl new file mode 100644 index 0000000..2079e03 --- /dev/null +++ b/utils/assets/charts/loki/templates/ruler/_helpers-ruler.tpl @@ -0,0 +1,47 @@ +{{/* +ruler fullname +*/}} +{{- define "loki.rulerFullname" -}} +{{ include "loki.fullname" . }}-ruler +{{- end }} + +{{/* +ruler common labels +*/}} +{{- define "loki.rulerLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: ruler +{{- end }} + +{{/* +ruler selector labels +*/}} +{{- define "loki.rulerSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: ruler +{{- end }} + +{{/* +ruler image +*/}} +{{- define "loki.rulerImage" -}} +{{- $dict := dict "loki" .Values.loki.image "service" .Values.ruler.image "global" .Values.global.image "defaultVersion" .Chart.AppVersion -}} +{{- include "loki.lokiImage" $dict -}} +{{- end }} + +{{/* +format rules dir +*/}} +{{- define "loki.rulerRulesDirName" -}} +rules-{{ . | replace "_" "-" | trimSuffix "-" | lower }} +{{- end }} + +{{/* +ruler priority class name +*/}} +{{- define "loki.rulerPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.ruler.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ruler/configmap-ruler.yaml b/utils/assets/charts/loki/templates/ruler/configmap-ruler.yaml new file mode 100644 index 0000000..3a0c533 --- /dev/null +++ b/utils/assets/charts/loki/templates/ruler/configmap-ruler.yaml @@ -0,0 +1,15 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if $isDistributed }} +{{- range $dir, $files := .Values.ruler.directories }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki.rulerFullname" $ }}-{{ include "loki.rulerRulesDirName" $dir }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.rulerLabels" $ | nindent 4 }} +data: + {{- toYaml $files | nindent 2}} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ruler/poddisruptionbudget-ruler.yaml b/utils/assets/charts/loki/templates/ruler/poddisruptionbudget-ruler.yaml new file mode 100644 index 0000000..b9c03cf --- /dev/null +++ b/utils/assets/charts/loki/templates/ruler/poddisruptionbudget-ruler.yaml @@ -0,0 +1,21 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed (gt (int .Values.ruler.replicas) 1) }} +{{- if kindIs "invalid" .Values.ruler.maxUnavailable }} +{{- fail "`.Values.ruler.maxUnavailable` must be set when `.Values.ruler.replicas` is greater than 1." }} +{{- else }} +apiVersion: {{ include "loki.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.rulerFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.rulerLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.rulerSelectorLabels" . | nindent 6 }} + {{- with .Values.ruler.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ruler/service-ruler.yaml b/utils/assets/charts/loki/templates/ruler/service-ruler.yaml new file mode 100644 index 0000000..8847683 --- /dev/null +++ b/utils/assets/charts/loki/templates/ruler/service-ruler.yaml @@ -0,0 +1,37 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ruler.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.rulerFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.rulerSelectorLabels" . | nindent 4 }} + {{- with .Values.ruler.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.ruler.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: 3100 + targetPort: http-metrics + protocol: TCP + - name: grpc + port: 9095 + targetPort: grpc + protocol: TCP + {{- with .Values.ruler.appProtocol.grpc }} + appProtocol: {{ . }} + {{- end }} + selector: + {{- include "loki.rulerSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/ruler/statefulset-ruler.yaml b/utils/assets/charts/loki/templates/ruler/statefulset-ruler.yaml new file mode 100644 index 0000000..87b42f2 --- /dev/null +++ b/utils/assets/charts/loki/templates/ruler/statefulset-ruler.yaml @@ -0,0 +1,184 @@ +{{- $isDistributed := eq (include "loki.deployment.isDistributed" .) "true" -}} +{{- if and $isDistributed .Values.ruler.enabled }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.rulerFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.rulerLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.ruler.replicas }} + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + serviceName: {{ include "loki.rulerFullname" . }} + selector: + matchLabels: + {{- include "loki.rulerSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "loki.config.checksum" . | nindent 8 }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ruler.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.rulerSelectorLabels" . | nindent 8 }} + app.kubernetes.io/part-of: memberlist + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ruler.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} + {{- with .Values.ruler.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ruler.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.rulerPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.ruler.terminationGracePeriodSeconds }} + {{- with .Values.ruler.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ruler + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=ruler + {{- with .Values.ruler.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: 3100 + protocol: TCP + - name: grpc + containerPort: 9095 + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.ruler.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.ruler.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + - name: tmp + mountPath: /tmp/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- range $dir, $_ := .Values.ruler.directories }} + - name: {{ include "loki.rulerRulesDirName" $dir }} + mountPath: /etc/loki/rules/{{ $dir }} + {{- end }} + {{- with .Values.ruler.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.ruler.resources | nindent 12 }} + {{- with .Values.ruler.extraContainers }} + {{- toYaml . | nindent 8}} + {{- end }} + {{- with .Values.ruler.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ruler.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ruler.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ruler.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- range $dir, $_ := .Values.ruler.directories }} + - name: {{ include "loki.rulerRulesDirName" $dir }} + configMap: + name: {{ include "loki.rulerFullname" $ }}-{{ include "loki.rulerRulesDirName" $dir }} + {{- end }} + - name: tmp + emptyDir: {} + {{- with .Values.ruler.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if not .Values.ruler.persistence.enabled }} + - name: data + emptyDir: {} + {{- else }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.ruler.persistence.annotations }} + annotations: + {{- . | toYaml | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .Values.ruler.persistence.storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .Values.ruler.persistence.size | quote }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/runtime-configmap.yaml b/utils/assets/charts/loki/templates/runtime-configmap.yaml new file mode 100644 index 0000000..2f38193 --- /dev/null +++ b/utils/assets/charts/loki/templates/runtime-configmap.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki.name" . }}-runtime + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +data: + runtime-config.yaml: | + {{- tpl (toYaml .Values.loki.runtimeConfig) . | nindent 4 }} diff --git a/utils/assets/charts/loki/templates/secret-license.yaml b/utils/assets/charts/loki/templates/secret-license.yaml new file mode 100644 index 0000000..eaa519f --- /dev/null +++ b/utils/assets/charts/loki/templates/secret-license.yaml @@ -0,0 +1,11 @@ +{{- if and (not .Values.enterprise.useExternalLicense) .Values.enterprise.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: enterprise-logs-license + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +data: + license.jwt: {{ .Values.enterprise.license.contents | b64enc }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/securitycontextconstraints.yaml b/utils/assets/charts/loki/templates/securitycontextconstraints.yaml new file mode 100644 index 0000000..c3a604d --- /dev/null +++ b/utils/assets/charts/loki/templates/securitycontextconstraints.yaml @@ -0,0 +1,40 @@ +{{- if .Values.rbac.sccEnabled }} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: {{ include "loki.name" . }} + labels: + {{- include "loki.labels" . | nindent 4 }} +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: true +allowPrivilegedContainer: false +allowedCapabilities: [] +defaultAddCapabilities: null +fsGroup: + type: RunAsAny +groups: [] +priority: null +readOnlyRootFilesystem: false +requiredDropCapabilities: + - ALL +runAsUser: + type: RunAsAny +seLinuxContext: + type: MustRunAs +seccompProfiles: + - '*' +supplementalGroups: + type: RunAsAny +volumes: + - configMap + - downwardAPI + - emptyDir + - hostPath + - persistentVolumeClaim + - projected + - secret +{{- end }} diff --git a/utils/assets/charts/loki/templates/service-memberlist.yaml b/utils/assets/charts/loki/templates/service-memberlist.yaml new file mode 100644 index 0000000..3d46f23 --- /dev/null +++ b/utils/assets/charts/loki/templates/service-memberlist.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.memberlist" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.memberlist.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp + port: 7946 + targetPort: http-memberlist + protocol: TCP + {{- with .Values.memberlist.service.publishNotReadyAddresses }} + publishNotReadyAddresses: {{ . }} + {{- end }} + selector: + {{- include "loki.selectorLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist diff --git a/utils/assets/charts/loki/templates/serviceaccount.yaml b/utils/assets/charts/loki/templates/serviceaccount.yaml new file mode 100644 index 0000000..dd89141 --- /dev/null +++ b/utils/assets/charts/loki/templates/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{ if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "loki.serviceAccountName" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- with .Values.serviceAccount.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/single-binary/_helpers-single-binary.tpl b/utils/assets/charts/loki/templates/single-binary/_helpers-single-binary.tpl new file mode 100644 index 0000000..4ea3c6d --- /dev/null +++ b/utils/assets/charts/loki/templates/single-binary/_helpers-single-binary.tpl @@ -0,0 +1,34 @@ +{{/* +singleBinary common labels +*/}} +{{- define "loki.singleBinaryLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: single-binary +{{- end }} + + +{{/* singleBinary selector labels */}} +{{- define "loki.singleBinarySelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: single-binary +{{- end }} + +{{/* +singleBinary priority class name +*/}} +{{- define "loki.singleBinaryPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.singleBinary.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} + +{{/* singleBinary replicas calculation */}} +{{- define "loki.singleBinaryReplicas" -}} +{{- $replicas := 1 }} +{{- $usingObjectStorage := eq (include "loki.isUsingObjectStorage" .) "true" }} +{{- if and $usingObjectStorage (gt (int .Values.singleBinary.replicas) 1)}} +{{- $replicas = int .Values.singleBinary.replicas -}} +{{- end }} +{{- printf "%d" $replicas }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/single-binary/hpa.yaml b/utils/assets/charts/loki/templates/single-binary/hpa.yaml new file mode 100644 index 0000000..c529f18 --- /dev/null +++ b/utils/assets/charts/loki/templates/single-binary/hpa.yaml @@ -0,0 +1,51 @@ +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- $usingObjectStorage := eq (include "loki.isUsingObjectStorage" .) "true" }} +{{- $autoscalingv2 := .Capabilities.APIVersions.Has "autoscaling/v2" -}} +{{- if and $isSingleBinary $usingObjectStorage ( .Values.singleBinary.autoscaling.enabled ) }} +{{- if $autoscalingv2 }} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta1 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.singleBinaryFullname" . }} + labels: + {{- include "loki.singleBinaryLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "loki.singleBinaryFullname" . }} + minReplicas: {{ .Values.singleBinary.autoscaling.minReplicas }} + maxReplicas: {{ .Values.singleBinary.autoscaling.maxReplicas }} + {{- with .Values.singleBinary.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} + metrics: + {{- with .Values.singleBinary.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.singleBinary.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/single-binary/pdb.yaml b/utils/assets/charts/loki/templates/single-binary/pdb.yaml new file mode 100644 index 0000000..bb1e1cc --- /dev/null +++ b/utils/assets/charts/loki/templates/single-binary/pdb.yaml @@ -0,0 +1,16 @@ +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- if and .Values.podDisruptionBudget $isSingleBinary -}} +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.singleBinarySelectorLabels" . | nindent 6 }} +{{ toYaml .Values.podDisruptionBudget | indent 2 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/single-binary/service-headless.yaml b/utils/assets/charts/loki/templates/single-binary/service-headless.yaml new file mode 100644 index 0000000..7522240 --- /dev/null +++ b/utils/assets/charts/loki/templates/single-binary/service-headless.yaml @@ -0,0 +1,35 @@ +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- if $isSingleBinary }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.name" . }}-headless + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.singleBinary.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + variant: headless + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.singleBinary.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + clusterIP: None + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + selector: + {{- include "loki.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/single-binary/service.yaml b/utils/assets/charts/loki/templates/single-binary/service.yaml new file mode 100644 index 0000000..352fcad --- /dev/null +++ b/utils/assets/charts/loki/templates/single-binary/service.yaml @@ -0,0 +1,40 @@ +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- if $isSingleBinary }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.singleBinaryFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.singleBinary.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.singleBinary.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + selector: + {{- include "loki.singleBinarySelectorLabels" . | nindent 4 }} + {{- with .Values.singleBinary.selectorLabels }} + {{- tpl (toYaml .) $ | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/single-binary/statefulset.yaml b/utils/assets/charts/loki/templates/single-binary/statefulset.yaml new file mode 100644 index 0000000..54f3d92 --- /dev/null +++ b/utils/assets/charts/loki/templates/single-binary/statefulset.yaml @@ -0,0 +1,278 @@ +{{- $isSingleBinary := eq (include "loki.deployment.isSingleBinary" .) "true" -}} +{{- if $isSingleBinary }} +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.singleBinaryFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.singleBinaryLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- if or (not (empty .Values.loki.annotations)) (not (empty .Values.singleBinary.annotations))}} + annotations: + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.singleBinary.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + replicas: {{ include "loki.singleBinaryReplicas" . }} + podManagementPolicy: Parallel + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ include "loki.singleBinaryFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.singleBinary.persistence.enableStatefulSetAutoDeletePVC) (.Values.singleBinary.persistence.enabled) }} + {{/* + Data on the singleBinary nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: Delete + whenScaled: Delete + {{- end }} + selector: + matchLabels: + {{- include "loki.singleBinarySelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.singleBinary.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.singleBinarySelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.singleBinary.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.singleBinary.selectorLabels }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + app.kubernetes.io/part-of: memberlist + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + {{ include "loki.enableServiceLinks" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.singleBinaryPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.singleBinary.terminationGracePeriodSeconds }} + {{- if .Values.singleBinary.initContainers }} + initContainers: + {{- with .Values.singleBinary.initContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + containers: + {{- if .Values.sidecar.rules.enabled }} + - name: loki-sc-rules + {{- if .Values.sidecar.image.sha }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.image.pullPolicy }} + env: + - name: METHOD + value: {{ .Values.sidecar.rules.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.rules.label }}" + {{- if .Values.sidecar.rules.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.rules.labelValue }} + {{- end }} + - name: FOLDER + value: "{{ .Values.sidecar.rules.folder }}" + - name: RESOURCE + value: {{ quote .Values.sidecar.rules.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- if .Values.sidecar.rules.searchNamespace }} + - name: NAMESPACE + value: "{{ .Values.sidecar.rules.searchNamespace | join "," }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.rules.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.rules.script }}" + {{- end }} + {{- if .Values.sidecar.rules.watchServerTimeout }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.rules.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.rules.watchClientTimeout }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.rules.watchClientTimeout }}" + {{- end }} + {{- if .Values.sidecar.rules.logLevel }} + - name: LOG_LEVEL + value: "{{ .Values.sidecar.rules.logLevel }}" + {{- end }} + {{- if .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml .Values.sidecar.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml .Values.sidecar.readinessProbe | nindent 12 }} + {{- end }} + {{- if .Values.sidecar.resources }} + resources: + {{- toYaml .Values.sidecar.resources | nindent 12 }} + {{- end }} + {{- if .Values.sidecar.securityContext }} + securityContext: + {{- toYaml .Values.sidecar.securityContext | nindent 12 }} + {{- end }} + volumeMounts: + - name: sc-rules-volume + mountPath: {{ .Values.sidecar.rules.folder | quote }} + {{- end}} + - name: loki + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target={{ .Values.singleBinary.targetModule }} + {{- with .Values.singleBinary.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.loki.server.http_listen_port }} + protocol: TCP + - name: grpc + containerPort: {{ .Values.loki.server.grpc_listen_port }} + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.singleBinary.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.singleBinary.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + volumeMounts: + - name: tmp + mountPath: /tmp + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + {{- if .Values.singleBinary.persistence.enabled }} + - name: storage + mountPath: /var/loki + {{- end }} + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- if .Values.sidecar.rules.enabled }} + - name: sc-rules-volume + mountPath: {{ .Values.sidecar.rules.folder | quote }} + {{- end}} + {{- with .Values.singleBinary.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.singleBinary.resources | nindent 12 }} + {{- with .Values.singleBinary.extraContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.singleBinary.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.singleBinary.dnsConfig }} + dnsConfig: + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.singleBinary.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.singleBinary.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: tmp + emptyDir: {} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- if .Values.sidecar.rules.enabled }} + - name: sc-rules-volume + {{- if .Values.sidecar.rules.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.rules.sizeLimit }} + {{- else }} + emptyDir: {} + {{- end -}} + {{- end -}} + {{- with .Values.singleBinary.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.singleBinary.persistence.enabled }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: storage + {{- with .Values.singleBinary.persistence.annotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .Values.singleBinary.persistence.storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .Values.singleBinary.persistence.size | quote }} + {{- with .Values.singleBinary.persistence.selector }} + selector: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/table-manager/_helpers-table-manager.tpl b/utils/assets/charts/loki/templates/table-manager/_helpers-table-manager.tpl new file mode 100644 index 0000000..ff25832 --- /dev/null +++ b/utils/assets/charts/loki/templates/table-manager/_helpers-table-manager.tpl @@ -0,0 +1,32 @@ +{{/* +table-manager fullname +*/}} +{{- define "loki.tableManagerFullname" -}} +{{ include "loki.fullname" . }}-table-manager +{{- end }} + +{{/* +table-manager common labels +*/}} +{{- define "loki.tableManagerLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: table-manager +{{- end }} + +{{/* +table-manager selector labels +*/}} +{{- define "loki.tableManagerSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: table-manager +{{- end }} + +{{/* +table-manager priority class name +*/}} +{{- define "loki.tableManagerPriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.tableManager.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/table-manager/deployment-table-manager.yaml b/utils/assets/charts/loki/templates/table-manager/deployment-table-manager.yaml new file mode 100644 index 0000000..770629b --- /dev/null +++ b/utils/assets/charts/loki/templates/table-manager/deployment-table-manager.yaml @@ -0,0 +1,126 @@ +{{- if .Values.tableManager.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.tableManagerFullname" . }} + labels: + {{- include "loki.tableManagerLabels" . | nindent 4 }} + annotations: + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.tableManager.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: 1 + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "loki.tableManagerSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tableManager.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.tableManagerSelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tableManager.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.tableManagerPriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.tableManager.terminationGracePeriodSeconds }} + containers: + - name: table-manager + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target=table-manager + {{- with .Values.tableManager.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.loki.server.http_listen_port }} + protocol: TCP + - name: grpc + containerPort: {{ .Values.loki.server.grpc_listen_port }} + protocol: TCP + {{- with .Values.tableManager.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tableManager.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + livenessProbe: + {{- toYaml .Values.loki.livenessProbe | nindent 12 }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.tableManager.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.tableManager.resources | nindent 12 }} + {{- if .Values.tableManager.extraContainers }} + {{- toYaml .Values.tableManager.extraContainers | nindent 8}} + {{- end }} + {{- with .Values.tableManager.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tableManager.dnsConfig }} + dnsConfig: + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.tableManager.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tableManager.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.tableManager.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/table-manager/service-table-manager.yaml b/utils/assets/charts/loki/templates/table-manager/service-table-manager.yaml new file mode 100644 index 0000000..214cd36 --- /dev/null +++ b/utils/assets/charts/loki/templates/table-manager/service-table-manager.yaml @@ -0,0 +1,36 @@ +{{- if .Values.tableManager.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.fullname" . }}-table-manager + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.tableManager.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + app.kubernetes.io/component: table-manager + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.tableManager.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + selector: + {{- include "loki.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: table-manager +{{- end }} diff --git a/utils/assets/charts/loki/templates/table-manager/servicemonitor-table-manager.yaml b/utils/assets/charts/loki/templates/table-manager/servicemonitor-table-manager.yaml new file mode 100644 index 0000000..09aa727 --- /dev/null +++ b/utils/assets/charts/loki/templates/table-manager/servicemonitor-table-manager.yaml @@ -0,0 +1,57 @@ +{{- if .Values.tableManager.enabled }} +{{- with .Values.serviceMonitor }} +{{- if .enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "loki.tableManagerFullname" $ }} + {{- with .namespace }} + namespace: {{ . }} + {{- end }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "loki.tableManagerLabels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "loki.tableManagerSelectorLabels" $ | nindent 6 }} + endpoints: + - port: http-metrics + {{- with .interval }} + interval: {{ . }} + {{- end }} + {{- with .scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .scheme }} + scheme: {{ . }} + {{- end }} + {{- with .tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .targetLabels }} + targetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/tests/_helpers.tpl b/utils/assets/charts/loki/templates/tests/_helpers.tpl new file mode 100644 index 0000000..9ef7c15 --- /dev/null +++ b/utils/assets/charts/loki/templates/tests/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* +Docker image name for loki helm test +*/}} +{{- define "loki.helmTestImage" -}} +{{- $dict := dict "service" .Values.test.image "global" .Values.global.image "defaultVersion" "latest" -}} +{{- include "loki.baseImage" $dict -}} +{{- end -}} + + +{{/* +test common labels +*/}} +{{- define "loki.helmTestLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: helm-test +{{- end }} diff --git a/utils/assets/charts/loki/templates/tests/test-canary.yaml b/utils/assets/charts/loki/templates/tests/test-canary.yaml new file mode 100644 index 0000000..9384865 --- /dev/null +++ b/utils/assets/charts/loki/templates/tests/test-canary.yaml @@ -0,0 +1,36 @@ +{{- with .Values.test }} +{{- if $.Values.lokiCanary.enabled }} +--- +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "loki.name" $ }}-helm-test" + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.helmTestLabels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": test +spec: + containers: + - name: loki-helm-test + image: {{ include "loki.helmTestImage" $ }} + env: + - name: CANARY_SERVICE_ADDRESS + value: "{{ .canaryServiceAddress }}" + - name: CANARY_PROMETHEUS_ADDRESS + value: "{{ .prometheusAddress }}" + {{- with .timeout }} + - name: CANARY_TEST_TIMEOUT + value: "{{ . }}" + {{- end }} + args: + - -test.v + restartPolicy: Never +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/tokengen/_helpers.yaml b/utils/assets/charts/loki/templates/tokengen/_helpers.yaml new file mode 100644 index 0000000..3c881f2 --- /dev/null +++ b/utils/assets/charts/loki/templates/tokengen/_helpers.yaml @@ -0,0 +1,22 @@ +{{/* +tokengen fullname +*/}} +{{- define "enterprise-logs.tokengenFullname" -}} +{{ include "loki.name" . }}-tokengen +{{- end }} + +{{/* +tokengen common labels +*/}} +{{- define "enterprise-logs.tokengenLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: tokengen +{{- end }} + +{{/* +tokengen selector labels +*/}} +{{- define "enterprise-logs.tokengenSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: tokengen +{{- end }} diff --git a/utils/assets/charts/loki/templates/tokengen/clusterrole-tokengen.yaml b/utils/assets/charts/loki/templates/tokengen/clusterrole-tokengen.yaml new file mode 100644 index 0000000..d357622 --- /dev/null +++ b/utils/assets/charts/loki/templates/tokengen/clusterrole-tokengen.yaml @@ -0,0 +1,21 @@ +{{ if and .Values.enterprise.tokengen.enabled .Values.enterprise.enabled }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ if not .Values.rbac.namespaced }}Cluster{{ end }}Role +metadata: + name: {{ template "enterprise-logs.tokengenFullname" . }} + labels: + {{- include "enterprise-logs.tokengenLabels" . | nindent 4 }} + {{- with .Values.enterprise.tokengen.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.tokengen.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "patch"] +{{- end }} diff --git a/utils/assets/charts/loki/templates/tokengen/clusterrolebinding-tokengen.yaml b/utils/assets/charts/loki/templates/tokengen/clusterrolebinding-tokengen.yaml new file mode 100644 index 0000000..fb21d8f --- /dev/null +++ b/utils/assets/charts/loki/templates/tokengen/clusterrolebinding-tokengen.yaml @@ -0,0 +1,25 @@ +{{ if and .Values.enterprise.tokengen.enabled .Values.enterprise.enabled }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ if not .Values.rbac.namespaced }}Cluster{{ end }}RoleBinding +metadata: + name: {{ template "enterprise-logs.tokengenFullname" . }} + labels: + {{- include "enterprise-logs.tokengenLabels" . | nindent 4 }} + {{- with .Values.enterprise.tokengen.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.tokengen.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: {{ if not .Values.rbac.namespaced }}Cluster{{ end }}Role + name: {{ template "enterprise-logs.tokengenFullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "enterprise-logs.tokengenFullname" . }} + namespace: {{ $.Release.Namespace }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/tokengen/job-tokengen.yaml b/utils/assets/charts/loki/templates/tokengen/job-tokengen.yaml new file mode 100644 index 0000000..b0950d6 --- /dev/null +++ b/utils/assets/charts/loki/templates/tokengen/job-tokengen.yaml @@ -0,0 +1,143 @@ +{{ if and .Values.enterprise.tokengen.enabled .Values.enterprise.enabled }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "enterprise-logs.tokengenFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "enterprise-logs.tokengenLabels" . | nindent 4 }} + {{- with .Values.enterprise.tokengen.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.tokengen.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install + "helm.sh/hook-weight": "10" +spec: + backoffLimit: 6 + completions: 1 + parallelism: 1 + template: + metadata: + labels: + {{- include "enterprise-logs.tokengenSelectorLabels" . | nindent 8 }} + {{- with .Values.enterprise.tokengen.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- with .Values.enterprise.tokengen.annotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.enterprise.tokengen.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + securityContext: + {{- toYaml .Values.enterprise.tokengen.securityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 8 }} + {{- end }} + initContainers: + - name: loki + image: {{ template "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + # The shared emptyDir exists only while the job is running, and is deleted once the job is completed. + # The tokengen generates a new admin token in case the 'token-file' file doesn't exist. + # As a result, subsequent executions of this tokengen job will generate new admin tokens. + # Note that previously generated tokens remain valid, as these remain present in the object storage. + - -config.file=/etc/loki/config/config.yaml + - -target={{ .Values.enterprise.tokengen.targetModule }} + - -tokengen.token-file=/shared/admin-token + {{- with .Values.enterprise.tokengen.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.enterprise.tokengen.extraVolumeMounts }} + {{ toYaml .Values.enterprise.tokengen.extraVolumeMounts | nindent 12 }} + {{- end }} + - name: shared + mountPath: /shared + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: license + mountPath: /etc/loki/license + env: + {{- if .Values.enterprise.tokengen.env }} + {{ toYaml .Values.enterprise.tokengen.env | nindent 12 }} + {{- end }} + {{- with .Values.enterprise.tokengen.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + containers: + - name: create-secret + image: {{ include "loki.kubectlImage" . }} + imagePullPolicy: {{ .Values.kubectlImage.pullPolicy }} + command: + - /bin/bash + - -euc + - | + # Create or update admin token secrets generated by tokengen job + kubectl create secret generic "{{ include "enterprise-logs.adminTokenSecret" . }}" \ + --from-file=token=/shared/admin-token \ + --dry-run=client -o yaml \ + | kubectl apply -f - + {{- with .Values.enterprise.adminToken.additionalNamespaces }} + {{- range . }} + kubectl --namespace "{{ . }}" create secret generic "{{ include "enterprise-logs.adminTokenSecret" $ }}" \ + --from-file=token=/shared/admin-token \ + --dry-run=client -o yaml \ + | kubectl apply -f - + {{- end }} + {{- end }} + volumeMounts: + {{- if .Values.enterprise.tokengen.extraVolumeMounts }} + {{ toYaml .Values.enterprise.tokengen.extraVolumeMounts | nindent 12 }} + {{- end }} + - name: shared + mountPath: /shared + - name: config + mountPath: /etc/loki/config + - name: license + mountPath: /etc/loki/license + restartPolicy: OnFailure + serviceAccount: {{ template "enterprise-logs.tokengenFullname" . }} + serviceAccountName: {{ template "enterprise-logs.tokengenFullname" . }} + {{- with .Values.enterprise.tokengen.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.enterprise.tokengen.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.enterprise.tokengen.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + - name: shared + emptyDir: {} + {{- if .Values.enterprise.tokengen.extraVolumes }} + {{ toYaml .Values.enterprise.tokengen.extraVolumes | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/tokengen/serviceaccount-tokengen.yaml b/utils/assets/charts/loki/templates/tokengen/serviceaccount-tokengen.yaml new file mode 100644 index 0000000..6f0e5a3 --- /dev/null +++ b/utils/assets/charts/loki/templates/tokengen/serviceaccount-tokengen.yaml @@ -0,0 +1,18 @@ +{{ if and .Values.enterprise.tokengen.enabled .Values.enterprise.enabled }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "enterprise-logs.tokengenFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "enterprise-logs.tokengenLabels" . | nindent 4 }} + {{- with .Values.enterprise.tokengen.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- with .Values.enterprise.tokengen.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + "helm.sh/hook": post-install +{{- end }} diff --git a/utils/assets/charts/loki/templates/validate.yaml b/utils/assets/charts/loki/templates/validate.yaml new file mode 100644 index 0000000..93e2490 --- /dev/null +++ b/utils/assets/charts/loki/templates/validate.yaml @@ -0,0 +1,41 @@ +{{- if .Values.config }} +{{- fail "Top level 'config' is not allowed. Most common configuration sections are exposed under the `loki` section. If you need to override the whole config, provide the configuration as a string that can contain template expressions under `loki.config`. Alternatively, you can provide the configuration as an external secret." }} +{{- end }} + +{{- if and (not .Values.lokiCanary.enabled) .Values.test.enabled }} +{{- fail "Helm test requires the Loki Canary to be enabled"}} +{{- end }} + +{{- $singleBinaryReplicas := int .Values.singleBinary.replicas }} +{{- $isUsingFilesystem := eq (include "loki.isUsingObjectStorage" .) "false" }} +{{- $atLeastOneScalableReplica := or (gt (int .Values.backend.replicas) 0) (gt (int .Values.read.replicas) 0) (gt (int .Values.write.replicas) 0) }} +{{- $atLeastOneDistributedReplica := or (gt (int .Values.ingester.replicas) 0) (gt (int .Values.distributor.replicas) 0) (gt (int .Values.querier.replicas) 0) (gt (int .Values.queryFrontend.replicas) 0) (gt (int .Values.queryScheduler.replicas) 0) (gt (int .Values.indexGateway.replicas) 0) (gt (int .Values.compactor.replicas) 0) (gt (int .Values.ruler.replicas) 0) }} + +{{- if and $isUsingFilesystem (gt $singleBinaryReplicas 1) }} +{{- fail "Cannot run more than 1 Single Binary replica without an object storage backend."}} +{{- end }} + +{{- if and $isUsingFilesystem (and (eq $singleBinaryReplicas 0) (or $atLeastOneScalableReplica $atLeastOneDistributedReplica)) }} +{{- fail "Cannot run scalable targets (backend, read, write) or distributed targets without an object storage backend."}} +{{- end }} + +{{- if and $atLeastOneScalableReplica $atLeastOneDistributedReplica (ne .Values.deploymentMode "SimpleScalable<->Distributed") }} +{{- fail "You have more than zero replicas configured for scalable targets (backend, read, write) and distributed targets. If this was intentional change the deploymentMode to the transitional 'SimpleScalable<->Distributed' mode" }} +{{- end }} + +{{- if and (gt $singleBinaryReplicas 0) $atLeastOneDistributedReplica }} +{{- fail "You have more than zero replicas configured for both the single binary and distributed targets, there is no transition mode between these targets please change one or the other to zero or transition to the SimpleScalable mode first."}} +{{- end }} + +{{- if and (gt $singleBinaryReplicas 0) $atLeastOneScalableReplica (ne .Values.deploymentMode "SingleBinary<->SimpleScalable") }} +{{- fail "You have more than zero replicas configured for both the single binary and simple scalable targets. If this was intentional change the deploymentMode to the transitional 'SingleBinary<->SimpleScalable' mode"}} +{{- end }} + +{{- if and (or (not (empty .Values.loki.schemaConfig)) (not (empty .Values.loki.structuredConfig.schema_config))) .Values.loki.useTestSchema }} +{{- fail "loki.useTestSchema must be false if loki.schemaConfig or loki.structuredConfig.schema_config are defined."}} +{{- end }} + + +{{- if and (empty .Values.loki.schemaConfig) (empty .Values.loki.structuredConfig.schema_config) (not .Values.loki.useTestSchema) }} +{{- fail "You must provide a schema_config for Loki, one is not provided as this will be individual for every Loki cluster. See https://grafana.com/docs/loki/latest/operations/storage/schema/ for schema information. For quick testing (with no persistence) add `--set loki.useTestSchema=true`"}} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/loki/templates/write/_helpers-write.tpl b/utils/assets/charts/loki/templates/write/_helpers-write.tpl new file mode 100644 index 0000000..8f526bc --- /dev/null +++ b/utils/assets/charts/loki/templates/write/_helpers-write.tpl @@ -0,0 +1,32 @@ +{{/* +write fullname +*/}} +{{- define "loki.writeFullname" -}} +{{ include "loki.name" . }}-write +{{- end }} + +{{/* +write common labels +*/}} +{{- define "loki.writeLabels" -}} +{{ include "loki.labels" . }} +app.kubernetes.io/component: write +{{- end }} + +{{/* +write selector labels +*/}} +{{- define "loki.writeSelectorLabels" -}} +{{ include "loki.selectorLabels" . }} +app.kubernetes.io/component: write +{{- end }} + +{{/* +write priority class name +*/}} +{{- define "loki.writePriorityClassName" -}} +{{- $pcn := coalesce .Values.global.priorityClassName .Values.write.priorityClassName -}} +{{- if $pcn }} +priorityClassName: {{ $pcn }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/write/hpa.yaml b/utils/assets/charts/loki/templates/write/hpa.yaml new file mode 100644 index 0000000..ba88ee2 --- /dev/null +++ b/utils/assets/charts/loki/templates/write/hpa.yaml @@ -0,0 +1,51 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- $autoscalingv2 := .Capabilities.APIVersions.Has "autoscaling/v2" -}} +{{- if and $isSimpleScalable ( .Values.write.autoscaling.enabled ) }} +{{- if $autoscalingv2 }} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta1 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.writeFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.writeLabels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "loki.writeFullname" . }} + minReplicas: {{ .Values.write.autoscaling.minReplicas }} + maxReplicas: {{ .Values.write.autoscaling.maxReplicas }} + {{- with .Values.write.autoscaling.behavior }} + behavior: + {{- toYaml . | nindent 4 }} + {{- end }} + metrics: + {{- with .Values.write.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.write.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if $autoscalingv2 }} + target: + type: Utilization + averageUtilization: {{ . }} + {{- else }} + targetAverageUtilization: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/write/poddisruptionbudget-write.yaml b/utils/assets/charts/loki/templates/write/poddisruptionbudget-write.yaml new file mode 100644 index 0000000..24e1356 --- /dev/null +++ b/utils/assets/charts/loki/templates/write/poddisruptionbudget-write.yaml @@ -0,0 +1,15 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if and $isSimpleScalable (gt (int .Values.write.replicas) 1) }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "loki.writeFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.writeLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "loki.writeSelectorLabels" . | nindent 6 }} + maxUnavailable: 1 +{{- end }} diff --git a/utils/assets/charts/loki/templates/write/service-write-headless.yaml b/utils/assets/charts/loki/templates/write/service-write-headless.yaml new file mode 100644 index 0000000..84cf5d7 --- /dev/null +++ b/utils/assets/charts/loki/templates/write/service-write-headless.yaml @@ -0,0 +1,41 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if $isSimpleScalable }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.writeFullname" . }}-headless + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.writeSelectorLabels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.write.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + variant: headless + prometheus.io/service-monitor: "false" + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.write.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + appProtocol: tcp + selector: + {{- include "loki.writeSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/write/service-write.yaml b/utils/assets/charts/loki/templates/write/service-write.yaml new file mode 100644 index 0000000..9603706 --- /dev/null +++ b/utils/assets/charts/loki/templates/write/service-write.yaml @@ -0,0 +1,37 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if $isSimpleScalable }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki.writeFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.writeLabels" . | nindent 4 }} + {{- with .Values.loki.serviceLabels }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.write.service.labels }} + {{- toYaml . | nindent 4}} + {{- end }} + annotations: + {{- with .Values.loki.serviceAnnotations }} + {{- toYaml . | nindent 4}} + {{- end }} + {{- with .Values.write.service.annotations }} + {{- toYaml . | nindent 4}} + {{- end }} +spec: + type: ClusterIP + ports: + - name: http-metrics + port: {{ .Values.loki.server.http_listen_port }} + targetPort: http-metrics + protocol: TCP + - name: grpc + port: {{ .Values.loki.server.grpc_listen_port }} + targetPort: grpc + protocol: TCP + selector: + {{- include "loki.writeSelectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/loki/templates/write/statefulset-write.yaml b/utils/assets/charts/loki/templates/write/statefulset-write.yaml new file mode 100644 index 0000000..fc3b301 --- /dev/null +++ b/utils/assets/charts/loki/templates/write/statefulset-write.yaml @@ -0,0 +1,217 @@ +{{- $isSimpleScalable := eq (include "loki.deployment.isScalable" .) "true" -}} +{{- if $isSimpleScalable }} +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki.writeFullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "loki.writeLabels" . | nindent 4 }} + app.kubernetes.io/part-of: memberlist + {{- if or (not (empty .Values.loki.annotations)) (not (empty .Values.backend.annotations))}} + annotations: + {{- with .Values.loki.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.write.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: +{{- if not .Values.write.autoscaling.enabled }} + {{- if eq .Values.deploymentMode "SingleBinary" }} + replicas: 0 + {{- else }} + replicas: {{ .Values.write.replicas }} + {{- end }} +{{- end }} + podManagementPolicy: {{ .Values.write.podManagementPolicy }} + updateStrategy: + rollingUpdate: + partition: 0 + serviceName: {{ include "loki.writeFullname" . }}-headless + revisionHistoryLimit: {{ .Values.loki.revisionHistoryLimit }} + {{- if and (semverCompare ">= 1.23-0" (include "loki.kubeVersion" .)) (.Values.write.persistence.enableStatefulSetAutoDeletePVC) (.Values.write.persistence.volumeClaimsEnabled) }} + {{/* + Data on the write nodes is easy to replace, so we want to always delete PVCs to make + operation easier, and will rely on re-fetching data when needed. + */}} + persistentVolumeClaimRetentionPolicy: + whenDeleted: Delete + whenScaled: Delete + {{- end }} + selector: + matchLabels: + {{- include "loki.writeSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include "loki.configMapOrSecretContentHash" (dict "ctx" . "name" "/config.yaml") }} + {{- with .Values.loki.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.write.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.writeSelectorLabels" . | nindent 8 }} + {{- with .Values.loki.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.write.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.write.selectorLabels }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + app.kubernetes.io/part-of: memberlist + spec: + serviceAccountName: {{ include "loki.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} + {{ include "loki.enableServiceLinks" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "loki.writePriorityClassName" . | nindent 6 }} + securityContext: + {{- toYaml .Values.loki.podSecurityContext | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.write.terminationGracePeriodSeconds }} + {{- if .Values.write.initContainers }} + initContainers: + {{- with .Values.write.initContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + containers: + - name: loki + image: {{ include "loki.image" . }} + imagePullPolicy: {{ .Values.loki.image.pullPolicy }} + args: + - -config.file=/etc/loki/config/config.yaml + - -target={{ .Values.write.targetModule }} + {{- with .Values.write.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.loki.server.http_listen_port }} + protocol: TCP + - name: grpc + containerPort: {{ .Values.loki.server.grpc_listen_port }} + protocol: TCP + - name: http-memberlist + containerPort: 7946 + protocol: TCP + {{- with .Values.write.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.write.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.loki.containerSecurityContext | nindent 12 }} + readinessProbe: + {{- toYaml .Values.loki.readinessProbe | nindent 12 }} + {{- if .Values.write.lifecycle }} + lifecycle: + {{- toYaml .Values.write.lifecycle | nindent 12 }} + {{- else if .Values.write.autoscaling.enabled }} + lifecycle: + preStop: + httpGet: + path: "/ingester/shutdown?terminate=false" + port: http-metrics + {{- end }} + volumeMounts: + - name: config + mountPath: /etc/loki/config + - name: runtime-config + mountPath: /etc/loki/runtime-config + - name: data + mountPath: /var/loki + {{- if .Values.enterprise.enabled }} + - name: license + mountPath: /etc/loki/license + {{- end }} + {{- with .Values.write.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.write.resources | nindent 12 }} + {{- with .Values.write.extraContainers }} + {{- toYaml . | nindent 8}} + {{- end }} + {{- with .Values.write.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.write.dnsConfig }} + dnsConfig: + {{- tpl . $ | nindent 8 }} + {{- end }} + {{- with .Values.write.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.write.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.write.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- if not .Values.write.persistence.volumeClaimsEnabled }} + - name: data + {{- toYaml .Values.write.persistence.dataVolumeParameters | nindent 10 }} + {{- end}} + - name: config + {{- include "loki.configVolume" . | nindent 10 }} + - name: runtime-config + configMap: + name: {{ template "loki.name" . }}-runtime + {{- if .Values.enterprise.enabled }} + - name: license + secret: + {{- if .Values.enterprise.useExternalLicense }} + secretName: {{ .Values.enterprise.externalLicenseName }} + {{- else }} + secretName: enterprise-logs-license + {{- end }} + {{- end }} + {{- with .Values.write.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.write.persistence.volumeClaimsEnabled }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: data + {{- with .Values.write.persistence.annotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: + - ReadWriteOnce + {{- with .Values.write.persistence.storageClass }} + storageClassName: {{ if (eq "-" .) }}""{{ else }}{{ . }}{{ end }} + {{- end }} + resources: + requests: + storage: {{ .Values.write.persistence.size | quote }} + {{- with .Values.write.persistence.selector }} + selector: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.write.extraVolumeClaimTemplates }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/loki/test/config_test.go b/utils/assets/charts/loki/test/config_test.go new file mode 100644 index 0000000..6926c7b --- /dev/null +++ b/utils/assets/charts/loki/test/config_test.go @@ -0,0 +1,220 @@ +package test + +import ( + "os" + "os/exec" + "testing" + + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" +) + +type replicas struct { + Replicas int `yaml:"replicas"` +} +type loki struct { + Storage struct { + Type string `yaml:"type"` + } `yaml:"storage"` +} + +type values struct { + DeploymentMode string `yaml:"deploymentMode"` + Backend replicas `yaml:"backend"` + Compactor replicas `yaml:"compactor"` + Distributor replicas `yaml:"distributor"` + IndexGateway replicas `yaml:"indexGateway"` + Ingester replicas `yaml:"ingester"` + Querier replicas `yaml:"querier"` + QueryFrontend replicas `yaml:"queryFrontend"` + QueryScheduler replicas `yaml:"queryScheduler"` + Read replicas `yaml:"read"` + Ruler replicas `yaml:"ruler"` + SingleBinary replicas `yaml:"singleBinary"` + Write replicas `yaml:"write"` + + Loki loki `yaml:"loki"` +} + +func templateConfig(t *testing.T, vals values) error { + y, err := yaml.Marshal(&vals) + require.NoError(t, err) + require.Greater(t, len(y), 0) + + f, err := os.CreateTemp("", "values.yaml") + require.NoError(t, err) + + _, err = f.Write(y) + require.NoError(t, err) + + cmd := exec.Command("helm", "dependency", "build") + // Dependency build needs to be run from the parent directory where the chart is located. + cmd.Dir = "../" + var cmdOutput []byte + if cmdOutput, err = cmd.CombinedOutput(); err != nil { + t.Log("dependency build failed", "err", string(cmdOutput)) + return err + } + + cmd = exec.Command("helm", "template", "../", "--values", f.Name()) + if cmdOutput, err := cmd.CombinedOutput(); err != nil { + t.Log("template failed", "err", string(cmdOutput)) + return err + } + + return nil +} + +// E.Welch these tests fail because the templateConfig function above can't resolve the chart dependencies and I'm not sure how to fix this.... + +//func Test_InvalidConfigs(t *testing.T) { +// t.Run("running both single binary and scalable targets", func(t *testing.T) { +// vals := values{ +// SingleBinary: replicas{Replicas: 1}, +// Write: replicas{Replicas: 1}, +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "gcs"}, +// }, +// } +// require.Error(t, templateConfig(t, vals)) +// }) +// +// t.Run("running both single binary and distributed targets", func(t *testing.T) { +// vals := values{ +// SingleBinary: replicas{Replicas: 1}, +// Distributor: replicas{Replicas: 1}, +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "gcs"}, +// }, +// } +// require.Error(t, templateConfig(t, vals)) +// }) +// +// t.Run("running both scalable and distributed targets", func(t *testing.T) { +// vals := values{ +// Read: replicas{Replicas: 1}, +// Distributor: replicas{Replicas: 1}, +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "gcs"}, +// }, +// } +// require.Error(t, templateConfig(t, vals)) +// }) +// +// t.Run("running scalable with filesystem storage", func(t *testing.T) { +// vals := values{ +// Read: replicas{Replicas: 1}, +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "filesystem"}, +// }, +// } +// +// require.Error(t, templateConfig(t, vals)) +// }) +// +// t.Run("running distributed with filesystem storage", func(t *testing.T) { +// vals := values{ +// Distributor: replicas{Replicas: 1}, +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "filesystem"}, +// }, +// } +// +// require.Error(t, templateConfig(t, vals)) +// }) +//} +// +//func Test_ValidConfigs(t *testing.T) { +// t.Run("single binary", func(t *testing.T) { +// vals := values{ +// +// DeploymentMode: "SingleBinary", +// +// SingleBinary: replicas{Replicas: 1}, +// +// Backend: replicas{Replicas: 0}, +// Compactor: replicas{Replicas: 0}, +// Distributor: replicas{Replicas: 0}, +// IndexGateway: replicas{Replicas: 0}, +// Ingester: replicas{Replicas: 0}, +// Querier: replicas{Replicas: 0}, +// QueryFrontend: replicas{Replicas: 0}, +// QueryScheduler: replicas{Replicas: 0}, +// Read: replicas{Replicas: 0}, +// Ruler: replicas{Replicas: 0}, +// Write: replicas{Replicas: 0}, +// +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "filesystem"}, +// }, +// } +// require.NoError(t, templateConfig(t, vals)) +// }) +// +// t.Run("scalable", func(t *testing.T) { +// vals := values{ +// +// DeploymentMode: "SimpleScalable", +// +// Backend: replicas{Replicas: 1}, +// Read: replicas{Replicas: 1}, +// Write: replicas{Replicas: 1}, +// +// Compactor: replicas{Replicas: 0}, +// Distributor: replicas{Replicas: 0}, +// IndexGateway: replicas{Replicas: 0}, +// Ingester: replicas{Replicas: 0}, +// Querier: replicas{Replicas: 0}, +// QueryFrontend: replicas{Replicas: 0}, +// QueryScheduler: replicas{Replicas: 0}, +// Ruler: replicas{Replicas: 0}, +// SingleBinary: replicas{Replicas: 0}, +// +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "gcs"}, +// }, +// } +// require.NoError(t, templateConfig(t, vals)) +// }) +// +// t.Run("distributed", func(t *testing.T) { +// vals := values{ +// DeploymentMode: "Distributed", +// +// Compactor: replicas{Replicas: 1}, +// Distributor: replicas{Replicas: 1}, +// IndexGateway: replicas{Replicas: 1}, +// Ingester: replicas{Replicas: 1}, +// Querier: replicas{Replicas: 1}, +// QueryFrontend: replicas{Replicas: 1}, +// QueryScheduler: replicas{Replicas: 1}, +// Ruler: replicas{Replicas: 1}, +// +// Backend: replicas{Replicas: 0}, +// Read: replicas{Replicas: 0}, +// SingleBinary: replicas{Replicas: 0}, +// Write: replicas{Replicas: 0}, +// +// Loki: loki{ +// Storage: struct { +// Type string `yaml:"type"` +// }{Type: "gcs"}, +// }, +// } +// require.NoError(t, templateConfig(t, vals)) +// }) +//} diff --git a/utils/assets/charts/loki/values.yaml b/utils/assets/charts/loki/values.yaml new file mode 100644 index 0000000..855e589 --- /dev/null +++ b/utils/assets/charts/loki/values.yaml @@ -0,0 +1,3618 @@ +# -- Overrides the version used to determine compatibility of resources with the target Kubernetes cluster. +# This is useful when using `helm template`, because then helm will use the client version of kubectl as the Kubernetes version, +# which may or may not match your cluster's server version. Example: 'v1.24.4'. Set to null to use the version that helm +# devises. +kubeVersionOverride: null + +global: + image: + # -- Overrides the Docker registry globally for all images + registry: null + # -- Overrides the priorityClassName for all pods + priorityClassName: null + # -- configures cluster domain ("cluster.local" by default) + clusterDomain: "cluster.local" + # -- configures DNS service name + dnsService: "kube-dns" + # -- configures DNS service namespace + dnsNamespace: "kube-system" +# -- Overrides the chart's name +nameOverride: null +# -- Overrides the chart's computed fullname +fullnameOverride: null +# -- Overrides the chart's cluster label +clusterLabelOverride: null +# -- Image pull secrets for Docker images +imagePullSecrets: [] +# -- Deployment mode lets you specify how to deploy Loki. +# There are 3 options: +# - SingleBinary: Loki is deployed as a single binary, useful for small installs typically without HA, up to a few tens of GB/day. +# - SimpleScalable: Loki is deployed as 3 targets: read, write, and backend. Useful for medium installs easier to manage than distributed, up to a about 1TB/day. +# - Distributed: Loki is deployed as individual microservices. The most complicated but most capable, useful for large installs, typically over 1TB/day. +# There are also 2 additional modes used for migrating between deployment modes: +# - SingleBinary<->SimpleScalable: Migrate from SingleBinary to SimpleScalable (or vice versa) +# - SimpleScalable<->Distributed: Migrate from SimpleScalable to Distributed (or vice versa) +# Note: SimpleScalable and Distributed REQUIRE the use of object storage. +deploymentMode: SimpleScalable +###################################################################################################################### +# +# Base Loki Configs including kubernetes configurations and configurations for Loki itself, +# see below for more specifics on Loki's configuration. +# +###################################################################################################################### +# -- Configuration for running Loki +# @default -- See values.yaml +loki: + # Configures the readiness probe for all of the Loki pods + readinessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 30 + timeoutSeconds: 1 + image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: grafana/loki + # -- Overrides the image tag whose default is the chart's appVersion + tag: 3.3.1 + # -- Overrides the image tag with an image digest + digest: null + # -- Docker image pull policy + pullPolicy: IfNotPresent + # -- Common annotations for all deployments/StatefulSets + annotations: {} + # -- Common annotations for all pods + podAnnotations: {} + # -- Common labels for all pods + podLabels: {} + # -- Common annotations for all services + serviceAnnotations: {} + # -- Common labels for all services + serviceLabels: {} + # -- The number of old ReplicaSets to retain to allow rollback + revisionHistoryLimit: 10 + # -- The SecurityContext for Loki pods + podSecurityContext: + fsGroup: 10001 + runAsGroup: 10001 + runAsNonRoot: true + runAsUser: 10001 + # -- The SecurityContext for Loki containers + containerSecurityContext: + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + # -- Should enableServiceLinks be enabled. Default to enable + enableServiceLinks: true + ###################################################################################################################### + # + # Loki Configuration + # + # There are several ways to pass configuration to Loki, listing them here in order of our preference for how + # you should use this chart. + # 1. Use the templated value of loki.config below and the corresponding override sections which follow. + # This allows us to set a lot of important Loki configurations and defaults and also allows us to maintain them + # over time as Loki changes and evolves. + # 2. Use the loki.structuredConfig section. + # This will completely override the templated value of loki.config, so you MUST provide the entire Loki config + # including any configuration that we set in loki.config unless you explicitly are trying to change one of those + # values and are not able to do so with the templated sections. + # If you choose this approach the burden is on you to maintain any changes we make to the templated config. + # 3. Use an existing secret or configmap to provide the configuration. + # This option is mostly provided for folks who have external processes which provide or modify the configuration. + # When using this option you can specify a different name for loki.generatedConfigObjectName and configObjectName + # if you have a process which takes the generated config and modifies it, or you can stop the chart from generating + # a config entirely by setting loki.generatedConfigObjectName to + # + ###################################################################################################################### + + # -- Defines what kind of object stores the configuration, a ConfigMap or a Secret. + # In order to move sensitive information (such as credentials) from the ConfigMap/Secret to a more secure location (e.g. vault), it is possible to use [environment variables in the configuration](https://grafana.com/docs/loki/latest/configuration/#use-environment-variables-in-the-configuration). + # Such environment variables can be then stored in a separate Secret and injected via the global.extraEnvFrom value. For details about environment injection from a Secret please see [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/#use-case-as-container-environment-variables). + configStorageType: ConfigMap + # -- The name of the object which Loki will mount as a volume containing the config. + # If the configStorageType is Secret, this will be the name of the Secret, if it is ConfigMap, this will be the name of the ConfigMap. + # The value will be passed through tpl. + configObjectName: '{{ include "loki.name" . }}' + # -- The name of the Secret or ConfigMap that will be created by this chart. + # If empty, no configmap or secret will be created. + # The value will be passed through tpl. + generatedConfigObjectName: '{{ include "loki.name" . }}' + # -- Config file contents for Loki + # @default -- See values.yaml + config: | + {{- if .Values.enterprise.enabled}} + {{- tpl .Values.enterprise.config . }} + {{- else }} + auth_enabled: {{ .Values.loki.auth_enabled }} + {{- end }} + + {{- with .Values.loki.server }} + server: + {{- toYaml . | nindent 2}} + {{- end}} + + pattern_ingester: + enabled: {{ .Values.loki.pattern_ingester.enabled }} + + memberlist: + {{- if .Values.loki.memberlistConfig }} + {{- toYaml .Values.loki.memberlistConfig | nindent 2 }} + {{- else }} + {{- if .Values.loki.extraMemberlistConfig}} + {{- toYaml .Values.loki.extraMemberlistConfig | nindent 2}} + {{- end }} + join_members: + - {{ include "loki.memberlist" . }} + {{- with .Values.migrate.fromDistributed }} + {{- if .enabled }} + - {{ .memberlistService }} + {{- end }} + {{- end }} + {{- end }} + + {{- with .Values.loki.ingester }} + ingester: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- if .Values.loki.commonConfig}} + common: + {{- toYaml .Values.loki.commonConfig | nindent 2}} + storage: + {{- include "loki.commonStorageConfig" . | nindent 4}} + {{- end}} + + {{- with .Values.loki.limits_config }} + limits_config: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + runtime_config: + file: /etc/loki/runtime-config/runtime-config.yaml + + {{- with .Values.chunksCache }} + {{- if .enabled }} + chunk_store_config: + chunk_cache_config: + default_validity: {{ .defaultValidity }} + background: + writeback_goroutines: {{ .writebackParallelism }} + writeback_buffer: {{ .writebackBuffer }} + writeback_size_limit: {{ .writebackSizeLimit }} + memcached: + batch_size: {{ .batchSize }} + parallelism: {{ .parallelism }} + memcached_client: + addresses: dnssrvnoa+_memcached-client._tcp.{{ template "loki.fullname" $ }}-chunks-cache.{{ $.Release.Namespace }}.svc + consistent_hash: true + timeout: {{ .timeout }} + max_idle_conns: 72 + {{- end }} + {{- end }} + + {{- if .Values.loki.schemaConfig }} + schema_config: + {{- toYaml .Values.loki.schemaConfig | nindent 2}} + {{- end }} + + {{- if .Values.loki.useTestSchema }} + schema_config: + {{- toYaml .Values.loki.testSchemaConfig | nindent 2}} + {{- end }} + + {{ include "loki.rulerConfig" . }} + + {{- if or .Values.tableManager.retention_deletes_enabled .Values.tableManager.retention_period }} + table_manager: + retention_deletes_enabled: {{ .Values.tableManager.retention_deletes_enabled }} + retention_period: {{ .Values.tableManager.retention_period }} + {{- end }} + + query_range: + align_queries_with_step: true + {{- with .Values.loki.query_range }} + {{- tpl (. | toYaml) $ | nindent 2 }} + {{- end }} + {{- if .Values.resultsCache.enabled }} + {{- with .Values.resultsCache }} + cache_results: true + results_cache: + cache: + default_validity: {{ .defaultValidity }} + background: + writeback_goroutines: {{ .writebackParallelism }} + writeback_buffer: {{ .writebackBuffer }} + writeback_size_limit: {{ .writebackSizeLimit }} + memcached_client: + consistent_hash: true + addresses: dnssrvnoa+_memcached-client._tcp.{{ template "loki.fullname" $ }}-results-cache.{{ $.Release.Namespace }}.svc + timeout: {{ .timeout }} + update_interval: 1m + {{- end }} + {{- end }} + + {{- with .Values.loki.storage_config }} + storage_config: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.query_scheduler }} + query_scheduler: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.compactor }} + compactor: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.analytics }} + analytics: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.querier }} + querier: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.index_gateway }} + index_gateway: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.frontend }} + frontend: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.frontend_worker }} + frontend_worker: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.distributor }} + distributor: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + tracing: + enabled: {{ .Values.loki.tracing.enabled }} + + {{- with .Values.loki.bloom_build }} + bloom_build: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + + {{- with .Values.loki.bloom_gateway }} + bloom_gateway: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} + # Should authentication be enabled + auth_enabled: true + # -- memberlist configuration (overrides embedded default) + memberlistConfig: {} + # -- Extra memberlist configuration + extraMemberlistConfig: {} + # -- Tenants list to be created on nginx htpasswd file, with name and password keys + tenants: [] + # -- Check https://grafana.com/docs/loki/latest/configuration/#server for more info on the server configuration. + server: + http_listen_port: 3100 + grpc_listen_port: 9095 + http_server_read_timeout: 600s + http_server_write_timeout: 600s + # -- Limits config + limits_config: + reject_old_samples: true + reject_old_samples_max_age: 168h + max_cache_freshness_per_query: 10m + split_queries_by_interval: 15m + query_timeout: 300s + volume_enabled: true + # -- Provides a reloadable runtime configuration file for some specific configuration + runtimeConfig: {} + # -- Check https://grafana.com/docs/loki/latest/configuration/#common_config for more info on how to provide a common configuration + commonConfig: + path_prefix: /var/loki + replication_factor: 3 + compactor_address: '{{ include "loki.compactorAddress" . }}' + # -- Storage config. Providing this will automatically populate all necessary storage configs in the templated config. + storage: + # Loki requires a bucket for chunks and the ruler. GEL requires a third bucket for the admin API. + # Please provide these values if you are using object storage. + # bucketNames: + # chunks: FIXME + # ruler: FIXME + # admin: FIXME + type: s3 + s3: + s3: null + endpoint: null + region: null + secretAccessKey: null + accessKeyId: null + signatureVersion: null + s3ForcePathStyle: false + insecure: false + http_config: {} + # -- Check https://grafana.com/docs/loki/latest/configure/#s3_storage_config for more info on how to provide a backoff_config + backoff_config: {} + disable_dualstack: false + gcs: + chunkBufferSize: 0 + requestTimeout: "0s" + enableHttp2: true + azure: + accountName: null + accountKey: null + connectionString: null + useManagedIdentity: false + useFederatedToken: false + userAssignedId: null + requestTimeout: null + endpointSuffix: null + chunkDelimiter: null + swift: + auth_version: null + auth_url: null + internal: null + username: null + user_domain_name: null + user_domain_id: null + user_id: null + password: null + domain_id: null + domain_name: null + project_id: null + project_name: null + project_domain_id: null + project_domain_name: null + region_name: null + container_name: null + max_retries: null + connect_timeout: null + request_timeout: null + filesystem: + chunks_directory: /var/loki/chunks + rules_directory: /var/loki/rules + admin_api_directory: /var/loki/admin + # -- Configure memcached as an external cache for chunk and results cache. Disabled by default + # must enable and specify a host for each cache you would like to use. + memcached: + chunk_cache: + enabled: false + host: "" + service: "memcached-client" + batch_size: 256 + parallelism: 10 + results_cache: + enabled: false + host: "" + service: "memcached-client" + timeout: "500ms" + default_validity: "12h" + # -- Check https://grafana.com/docs/loki/latest/configuration/#schema_config for more info on how to configure schemas + schemaConfig: {} + # -- a real Loki install requires a proper schemaConfig defined above this, however for testing or playing around + # you can enable useTestSchema + useTestSchema: false + testSchemaConfig: + configs: + - from: 2024-04-01 + store: tsdb + object_store: '{{ include "loki.testSchemaObjectStore" . }}' + schema: v13 + index: + prefix: index_ + period: 24h + # -- Check https://grafana.com/docs/loki/latest/configuration/#ruler for more info on configuring ruler + rulerConfig: + wal: + dir: /var/loki/ruler-wal + # -- Structured loki configuration, takes precedence over `loki.config`, `loki.schemaConfig`, `loki.storageConfig` + structuredConfig: {} + # -- Additional query scheduler config + query_scheduler: {} + # -- Additional storage config + storage_config: + boltdb_shipper: + index_gateway_client: + server_address: '{{ include "loki.indexGatewayAddress" . }}' + tsdb_shipper: + index_gateway_client: + server_address: '{{ include "loki.indexGatewayAddress" . }}' + bloom_shipper: + working_directory: /var/loki/data/bloomshipper + hedging: + at: "250ms" + max_per_second: 20 + up_to: 3 + # -- Optional compactor configuration + compactor: {} + # -- Optional pattern ingester configuration + pattern_ingester: + enabled: false + # -- Optional analytics configuration + analytics: {} + # -- Optional querier configuration + query_range: {} + # -- Optional querier configuration + querier: {} + # -- Optional ingester configuration + ingester: {} + # -- Optional index gateway configuration + index_gateway: + mode: simple + frontend: + scheduler_address: '{{ include "loki.querySchedulerAddress" . }}' + tail_proxy_url: '{{ include "loki.querierAddress" . }}' + frontend_worker: + scheduler_address: '{{ include "loki.querySchedulerAddress" . }}' + # -- Optional distributor configuration + distributor: {} + # -- Enable tracing + tracing: + enabled: false + bloom_build: + enabled: false + builder: + planner_address: '{{ include "loki.bloomPlannerAddress" . }}' + bloom_gateway: + enabled: false + client: + addresses: '{{ include "loki.bloomGatewayAddresses" . }}' +###################################################################################################################### +# +# Enterprise Loki Configs +# +###################################################################################################################### + +# -- Configuration for running Enterprise Loki +enterprise: + # Enable enterprise features, license must be provided + enabled: false + # Default verion of GEL to deploy + version: 3.1.1 + # -- Optional name of the GEL cluster, otherwise will use .Release.Name + # The cluster name must match what is in your GEL license + cluster_name: null + # -- Grafana Enterprise Logs license + # In order to use Grafana Enterprise Logs features, you will need to provide + # the contents of your Grafana Enterprise Logs license, either by providing the + # contents of the license.jwt, or the name Kubernetes Secret that contains your + # license.jwt. + # To set the license contents, use the flag `--set-file 'enterprise.license.contents=./license.jwt'` + license: + contents: "NOTAVALIDLICENSE" + # -- Set to true when providing an external license + useExternalLicense: false + # -- Name of external license secret to use + externalLicenseName: null + # -- Name of the external config secret to use + externalConfigName: "" + # -- Use GEL gateway, if false will use the default nginx gateway + gelGateway: true + # -- If enabled, the correct admin_client storage will be configured. If disabled while running enterprise, + # make sure auth is set to `type: trust`, or that `auth_enabled` is set to `false`. + adminApi: + enabled: true + # enterprise specific sections of the config.yaml file + config: | + {{- if .Values.enterprise.adminApi.enabled }} + admin_client: + {{ include "enterprise-logs.adminAPIStorageConfig" . | nindent 2 }} + {{ end }} + auth: + type: {{ .Values.enterprise.adminApi.enabled | ternary "enterprise" "trust" }} + auth_enabled: {{ .Values.loki.auth_enabled }} + cluster_name: {{ include "loki.clusterName" . }} + license: + path: /etc/loki/license/license.jwt + image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: grafana/enterprise-logs + # -- Docker image tag + tag: 3.3.1 + # -- Overrides the image tag with an image digest + digest: null + # -- Docker image pull policy + pullPolicy: IfNotPresent + adminToken: + # -- Alternative name for admin token secret, needed by tokengen and provisioner jobs + secret: null + # -- Additional namespace to also create the token in. Useful if your Grafana instance + # is in a different namespace + additionalNamespaces: [] + # -- Alternative name of the secret to store token for the canary + canarySecret: null + # -- Configuration for `tokengen` target + tokengen: + # -- Whether the job should be part of the deployment + enabled: true + # -- Comma-separated list of Loki modules to load for tokengen + targetModule: "tokengen" + # -- Additional CLI arguments for the `tokengen` target + extraArgs: [] + # -- Additional Kubernetes environment + env: [] + # -- Additional labels for the `tokengen` Job + labels: {} + # -- Additional annotations for the `tokengen` Job + annotations: {} + # -- Affinity for tokengen Pods + affinity: {} + # -- Node selector for tokengen Pods + nodeSelector: {} + # -- Tolerations for tokengen Job + tolerations: [] + # -- Additional volumes for Pods + extraVolumes: [] + # -- Additional volume mounts for Pods + extraVolumeMounts: [] + # -- Run containers as user `enterprise-logs(uid=10001)` + securityContext: + runAsNonRoot: true + runAsGroup: 10001 + runAsUser: 10001 + fsGroup: 10001 + # -- Environment variables from secrets or configmaps to add to the tokengen pods + extraEnvFrom: [] + # -- The name of the PriorityClass for tokengen Pods + priorityClassName: "" + # -- Configuration for `provisioner` target + provisioner: + # -- Whether the job should be part of the deployment + enabled: true + # -- Name of the secret to store provisioned tokens in + provisionedSecretPrefix: null + # -- Additional tenants to be created. Each tenant will get a read and write policy + # and associated token. Tenant must have a name and a namespace for the secret containting + # the token to be created in. For example + # additionalTenants: + # - name: loki + # secretNamespace: grafana + additionalTenants: [] + # -- Additional Kubernetes environment + env: [] + # -- Additional labels for the `provisioner` Job + labels: {} + # -- Additional annotations for the `provisioner` Job + annotations: {} + # -- Affinity for tokengen Pods + affinity: {} + # -- Node selector for tokengen Pods + nodeSelector: {} + # -- Tolerations for tokengen Pods + tolerations: [] + # -- The name of the PriorityClass for provisioner Job + priorityClassName: null + # -- Run containers as user `enterprise-logs(uid=10001)` + securityContext: + runAsNonRoot: true + runAsGroup: 10001 + runAsUser: 10001 + fsGroup: 10001 + # -- Provisioner image to Utilize + image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: grafana/enterprise-logs-provisioner + # -- Overrides the image tag whose default is the chart's appVersion + tag: null + # -- Overrides the image tag with an image digest + digest: null + # -- Docker image pull policy + pullPolicy: IfNotPresent + # -- Volume mounts to add to the provisioner pods + extraVolumeMounts: [] +# -- kubetclImage is used in the enterprise provisioner and tokengen jobs +kubectlImage: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: bitnami/kubectl + # -- Overrides the image tag whose default is the chart's appVersion + tag: null + # -- Overrides the image tag with an image digest + digest: null + # -- Docker image pull policy + pullPolicy: IfNotPresent +###################################################################################################################### +# +# Chart Testing +# +###################################################################################################################### + +# -- Section for configuring optional Helm test +test: + enabled: true + # -- Used to directly query the metrics endpoint of the canary for testing, this approach avoids needing prometheus for testing. + # This in a newer approach to using prometheusAddress such that tests do not have a dependency on prometheus + canaryServiceAddress: "http://loki-canary:3500/metrics" + # -- Address of the prometheus server to query for the test. This overrides any value set for canaryServiceAddress. + # This is kept for backward compatibility and may be removed in future releases. Previous value was 'http://prometheus:9090' + prometheusAddress: "" + # -- Number of times to retry the test before failing + timeout: 1m + # -- Additional labels for the test pods + labels: {} + # -- Additional annotations for test pods + annotations: {} + # -- Image to use for loki canary + image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: grafana/loki-helm-test + # -- Overrides the image tag whose default is the chart's appVersion + tag: "ewelch-distributed-helm-chart-17db5ee" + # -- Overrides the image tag with an image digest + digest: null + # -- Docker image pull policy + pullPolicy: IfNotPresent +# The Loki canary pushes logs to and queries from this loki installation to test +# that it's working correctly +lokiCanary: + enabled: true + # -- If true, the canary will send directly to Loki via the address configured for verification -- + # -- If false, it will write to stdout and an Agent will be needed to scrape and send the logs -- + push: true + # -- The name of the label to look for at loki when doing the checks. + labelname: pod + # -- Additional annotations for the `loki-canary` Daemonset + annotations: {} + # -- Additional labels for each `loki-canary` pod + podLabels: {} + service: + # -- Annotations for loki-canary Service + annotations: {} + # -- Additional labels for loki-canary Service + labels: {} + # -- Additional CLI arguments for the `loki-canary' command + extraArgs: [] + # -- Environment variables to add to the canary pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the canary pods + extraEnvFrom: [] + # -- Volume mounts to add to the canary pods + extraVolumeMounts: [] + # -- Volumes to add to the canary pods + extraVolumes: [] + # -- Resource requests and limits for the canary + resources: {} + # -- DNS config for canary pods + dnsConfig: {} + # -- Node selector for canary pods + nodeSelector: {} + # -- Tolerations for canary pods + tolerations: [] + # -- The name of the PriorityClass for loki-canary pods + priorityClassName: null + # -- Image to use for loki canary + image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: grafana/loki-canary + # -- Overrides the image tag whose default is the chart's appVersion + tag: null + # -- Overrides the image tag with an image digest + digest: null + # -- Docker image pull policy + pullPolicy: IfNotPresent + # -- Update strategy for the `loki-canary` Daemonset pods + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 +###################################################################################################################### +# +# Service Accounts and Kubernetes RBAC +# +###################################################################################################################### +serviceAccount: + # -- Specifies whether a ServiceAccount should be created + create: true + # -- The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: null + # -- Image pull secrets for the service account + imagePullSecrets: [] + # -- Annotations for the service account + annotations: {} + # -- Labels for the service account + labels: {} + # -- Set this toggle to false to opt out of automounting API credentials for the service account + automountServiceAccountToken: true +# RBAC configuration +rbac: + # -- If pspEnabled true, a PodSecurityPolicy is created for K8s that use psp. + pspEnabled: false + # -- For OpenShift set pspEnabled to 'false' and sccEnabled to 'true' to use the SecurityContextConstraints. + sccEnabled: false + # -- Specify PSP annotations + # Ref: https://kubernetes.io/docs/reference/access-authn-authz/psp-to-pod-security-standards/#podsecuritypolicy-annotations + pspAnnotations: {} + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + # -- Whether to install RBAC in the namespace only or cluster-wide. Useful if you want to watch ConfigMap globally. + namespaced: false +###################################################################################################################### +# +# Network Policy configuration +# +###################################################################################################################### +networkPolicy: + # -- Specifies whether Network Policies should be created + enabled: false + # -- Specifies whether the policies created will be standard Network Policies (flavor: kubernetes) + # or Cilium Network Policies (flavor: cilium) + flavor: kubernetes + metrics: + # -- Specifies the Pods which are allowed to access the metrics port. + # As this is cross-namespace communication, you also need the namespaceSelector. + podSelector: {} + # -- Specifies the namespaces which are allowed to access the metrics port + namespaceSelector: {} + # -- Specifies specific network CIDRs which are allowed to access the metrics port. + # In case you use namespaceSelector, you also have to specify your kubelet networks here. + # The metrics ports are also used for probes. + cidrs: [] + ingress: + # -- Specifies the Pods which are allowed to access the http port. + # As this is cross-namespace communication, you also need the namespaceSelector. + podSelector: {} + # -- Specifies the namespaces which are allowed to access the http port + namespaceSelector: {} + alertmanager: + # -- Specify the alertmanager port used for alerting + port: 9093 + # -- Specifies the alertmanager Pods. + # As this is cross-namespace communication, you also need the namespaceSelector. + podSelector: {} + # -- Specifies the namespace the alertmanager is running in + namespaceSelector: {} + externalStorage: + # -- Specify the port used for external storage, e.g. AWS S3 + ports: [] + # -- Specifies specific network CIDRs you want to limit access to + cidrs: [] + discovery: + # -- (int) Specify the port used for discovery + port: null + # -- Specifies the Pods labels used for discovery. + # As this is cross-namespace communication, you also need the namespaceSelector. + podSelector: {} + # -- Specifies the namespace the discovery Pods are running in + namespaceSelector: {} + egressWorld: + # -- Enable additional cilium egress rules to external world for write, read and backend. + enabled: false + egressKubeApiserver: + # -- Enable additional cilium egress rules to kube-apiserver for backend. + enabled: false +###################################################################################################################### +# +# Global memberlist configuration +# +###################################################################################################################### + +# Configuration for the memberlist service +memberlist: + service: + publishNotReadyAddresses: false + annotations: {} +###################################################################################################################### +# +# adminAPI configuration, enterprise only. +# +###################################################################################################################### + +# -- Configuration for the `admin-api` target +adminApi: + # -- Define the amount of instances + replicas: 1 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + # -- Additional CLI arguments for the `admin-api` target + extraArgs: {} + # -- Environment variables from secrets or configmaps to add to the admin-api pods + extraEnvFrom: [] + # -- Additional labels for the `admin-api` Deployment + labels: {} + # -- Additional annotations for the `admin-api` Deployment + annotations: {} + # -- Additional labels and annotations for the `admin-api` Service + service: + labels: {} + annotations: {} + # -- Run container as user `enterprise-logs(uid=10001)` + # `fsGroup` must not be specified, because these security options are applied + # on container level not on Pod level. + podSecurityContext: + runAsNonRoot: true + runAsGroup: 10001 + runAsUser: 10001 + containerSecurityContext: + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + # -- Update strategy + strategy: + type: RollingUpdate + # -- Readiness probe + readinessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + # -- Request and limit Kubernetes resources + # -- Values are defined in small.yaml and large.yaml + resources: {} + # -- Configure optional environment variables + env: [] + # -- Configure optional initContainers + initContainers: [] + # -- Conifgure optional extraContainers + extraContainers: [] + # -- Additional volumes for Pods + extraVolumes: [] + # -- Additional volume mounts for Pods + extraVolumeMounts: [] + # -- Affinity for admin-api Pods + affinity: {} + # -- Node selector for admin-api Pods + nodeSelector: {} + # -- Topology Spread Constraints for admin-api pods + topologySpreadConstraints: [] + # -- Tolerations for admin-api Pods + tolerations: [] + # -- Grace period to allow the admin-api to shutdown before it is killed + terminationGracePeriodSeconds: 60 +###################################################################################################################### +# +# Gateway and Ingress +# +# By default this chart will deploy a Nginx container to act as a gateway which handles routing of traffic +# and can also do auth. +# +# If you would prefer you can optionally disable this and enable using k8s ingress to do the incoming routing. +# +###################################################################################################################### + +# Configuration for the gateway +gateway: + # -- Specifies whether the gateway should be enabled + enabled: true + # -- Number of replicas for the gateway + replicas: 1 + # -- Default container port + containerPort: 8080 + # -- Enable logging of 2xx and 3xx HTTP requests + verboseLogging: true + autoscaling: + # -- Enable autoscaling for the gateway + enabled: false + # -- Minimum autoscaling replicas for the gateway + minReplicas: 1 + # -- Maximum autoscaling replicas for the gateway + maxReplicas: 3 + # -- Target CPU utilisation percentage for the gateway + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the gateway + targetMemoryUtilizationPercentage: + # -- See `kubectl explain deployment.spec.strategy` for more + # -- ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + # -- Behavior policies while scaling. + behavior: {} + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 60 + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + deploymentStrategy: + type: RollingUpdate + image: + # -- The Docker registry for the gateway image + registry: docker.io + # -- The gateway image repository + repository: nginxinc/nginx-unprivileged + # -- The gateway image tag + tag: 1.27-alpine + # -- Overrides the gateway image tag with an image digest + digest: null + # -- The gateway image pull policy + pullPolicy: IfNotPresent + # -- The name of the PriorityClass for gateway pods + priorityClassName: null + # -- Annotations for gateway deployment + annotations: {} + # -- Annotations for gateway pods + podAnnotations: {} + # -- Additional labels for gateway pods + podLabels: {} + # -- Additional CLI args for the gateway + extraArgs: [] + # -- Environment variables to add to the gateway pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the gateway pods + extraEnvFrom: [] + # -- Lifecycle for the gateway container + lifecycle: {} + # -- Volumes to add to the gateway pods + extraVolumes: [] + # -- Volume mounts to add to the gateway pods + extraVolumeMounts: [] + # -- The SecurityContext for gateway containers + podSecurityContext: + fsGroup: 101 + runAsGroup: 101 + runAsNonRoot: true + runAsUser: 101 + # -- The SecurityContext for gateway containers + containerSecurityContext: + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + # -- Resource requests and limits for the gateway + resources: {} + # -- Containers to add to the gateway pods + extraContainers: [] + # -- Grace period to allow the gateway to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for gateway pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: gateway + topologyKey: kubernetes.io/hostname + # -- DNS config for gateway pods + dnsConfig: {} + # -- Node selector for gateway pods + nodeSelector: {} + # -- Topology Spread Constraints for gateway pods + topologySpreadConstraints: [] + # -- Tolerations for gateway pods + tolerations: [] + # Gateway service configuration + service: + # -- Port of the gateway service + port: 80 + # -- Type of the gateway service + type: ClusterIP + # -- ClusterIP of the gateway service + clusterIP: null + # -- (int) Node port if service type is NodePort + nodePort: null + # -- Load balancer IPO address if service type is LoadBalancer + loadBalancerIP: null + # -- Annotations for the gateway service + annotations: {} + # -- Labels for gateway service + labels: {} + # Gateway ingress configuration + ingress: + # -- Specifies whether an ingress for the gateway should be created + enabled: false + # -- Ingress Class Name. MAY be required for Kubernetes versions >= 1.18 + ingressClassName: "" + # -- Annotations for the gateway ingress + annotations: {} + # -- Labels for the gateway ingress + labels: {} + # -- Hosts configuration for the gateway ingress, passed through the `tpl` function to allow templating + hosts: + - host: gateway.loki.example.com + paths: + - path: / + # -- pathType (e.g. ImplementationSpecific, Prefix, .. etc.) might also be required by some Ingress Controllers + # pathType: Prefix + # -- TLS configuration for the gateway ingress. Hosts passed through the `tpl` function to allow templating + tls: + - secretName: loki-gateway-tls + hosts: + - gateway.loki.example.com + # Basic auth configuration + basicAuth: + # -- Enables basic authentication for the gateway + enabled: false + # -- The basic auth username for the gateway + username: null + # -- The basic auth password for the gateway + password: null + # -- Uses the specified users from the `loki.tenants` list to create the htpasswd file. + # if `loki.tenants` is not set, the `gateway.basicAuth.username` and `gateway.basicAuth.password` are used. + # The value is templated using `tpl`. Override this to use a custom htpasswd, e.g. in case the default causes + # high CPU load. + # @default -- Either `loki.tenants` or `gateway.basicAuth.username` and `gateway.basicAuth.password`. + htpasswd: >- + {{ if .Values.loki.tenants }} + + + {{- range $t := .Values.loki.tenants }} + {{ htpasswd (required "All tenants must have a 'name' set" $t.name) (required "All tenants must have a 'password' set" $t.password) }} + + + {{- end }} + {{ else }} {{ htpasswd (required "'gateway.basicAuth.username' is required" .Values.gateway.basicAuth.username) (required "'gateway.basicAuth.password' is required" .Values.gateway.basicAuth.password) }} {{ end }} + # -- Existing basic auth secret to use. Must contain '.htpasswd' + existingSecret: null + # Configures the readiness probe for the gateway + readinessProbe: + httpGet: + path: / + port: http-metrics + initialDelaySeconds: 15 + timeoutSeconds: 1 + nginxConfig: + # -- Which schema to be used when building URLs. Can be 'http' or 'https'. + schema: http + # -- Enable listener for IPv6, disable on IPv4-only systems + enableIPv6: true + # -- NGINX log format + logFormat: |- + main '$remote_addr - $remote_user [$time_local] $status ' + '"$request" $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + # -- Allows appending custom configuration to the server block + serverSnippet: "" + # -- Allows appending custom configuration to the http block, passed through the `tpl` function to allow templating + httpSnippet: >- + {{ if .Values.loki.tenants }}proxy_set_header X-Scope-OrgID $remote_user;{{ end }} + # -- Allows customizing the `client_max_body_size` directive + clientMaxBodySize: 4M + # -- Whether ssl should be appended to the listen directive of the server block or not. + ssl: false + # -- Override Read URL + customReadUrl: null + # -- Override Write URL + customWriteUrl: null + # -- Override Backend URL + customBackendUrl: null + # -- Allows overriding the DNS resolver address nginx will use. + resolver: "" + # -- Config file contents for Nginx. Passed through the `tpl` function to allow templating + # @default -- See values.yaml + file: | + {{- include "loki.nginxFile" . | indent 2 -}} +# -- If running enterprise and using the default enterprise gateway, configs go here. +enterpriseGateway: + # -- Define the amount of instances + replicas: 1 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + # -- Additional CLI arguments for the `gateway` target + extraArgs: {} + # -- Environment variables from secrets or configmaps to add to the enterprise gateway pods + extraEnvFrom: [] + # -- Additional labels for the `gateway` Pod + labels: {} + # -- Additional annotations for the `gateway` Pod + annotations: {} + # -- Additional labels and annotations for the `gateway` Service + # -- Service overriding service type + service: + type: ClusterIP + labels: {} + annotations: {} + # -- Run container as user `enterprise-logs(uid=10001)` + podSecurityContext: + runAsNonRoot: true + runAsGroup: 10001 + runAsUser: 10001 + fsGroup: 10001 + containerSecurityContext: + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + # -- If you want to use your own proxy URLs, set this to false. + useDefaultProxyURLs: true + # -- update strategy + strategy: + type: RollingUpdate + # -- Readiness probe + readinessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + # -- Request and limit Kubernetes resources + # -- Values are defined in small.yaml and large.yaml + resources: {} + # -- Configure optional environment variables + env: [] + # -- Configure optional initContainers + initContainers: [] + # -- Conifgure optional extraContainers + extraContainers: [] + # -- Additional volumes for Pods + extraVolumes: [] + # -- Additional volume mounts for Pods + extraVolumeMounts: [] + # -- Affinity for gateway Pods + affinity: {} + # -- Node selector for gateway Pods + nodeSelector: {} + # -- Topology Spread Constraints for enterprise-gateway pods + topologySpreadConstraints: [] + # -- Tolerations for gateway Pods + tolerations: [] + # -- Grace period to allow the gateway to shutdown before it is killed + terminationGracePeriodSeconds: 60 +# -- Ingress configuration Use either this ingress or the gateway, but not both at once. +# If you enable this, make sure to disable the gateway. +# You'll need to supply authn configuration for your ingress controller. +ingress: + enabled: false + ingressClassName: "" + annotations: {} + # nginx.ingress.kubernetes.io/auth-type: basic + # nginx.ingress.kubernetes.io/auth-secret: loki-distributed-basic-auth + # nginx.ingress.kubernetes.io/auth-secret-type: auth-map + # nginx.ingress.kubernetes.io/configuration-snippet: | + # proxy_set_header X-Scope-OrgID $remote_user; + labels: {} + # blackbox.monitoring.exclude: "true" + paths: + # -- Paths that are exposed by Loki Distributor. + # If deployment mode is Distributed, the requests are forwarded to the service: `{{"loki.distributorFullname"}}`. + # If deployment mode is SimpleScalable, the requests are forwarded to write k8s service: `{{"loki.writeFullname"}}`. + # If deployment mode is SingleBinary, the requests are forwarded to the central/single k8s service: `{{"loki.singleBinaryFullname"}}` + distributor: + - /api/prom/push + - /loki/api/v1/push + - /otlp/v1/logs + # -- Paths that are exposed by Loki Query Frontend. + # If deployment mode is Distributed, the requests are forwarded to the service: `{{"loki.queryFrontendFullname"}}`. + # If deployment mode is SimpleScalable, the requests are forwarded to write k8s service: `{{"loki.readFullname"}}`. + # If deployment mode is SingleBinary, the requests are forwarded to the central/single k8s service: `{{"loki.singleBinaryFullname"}}` + queryFrontend: + - /api/prom/query + # this path covers labels and labelValues endpoints + - /api/prom/label + - /api/prom/series + - /api/prom/tail + - /loki/api/v1/query + - /loki/api/v1/query_range + - /loki/api/v1/tail + # this path covers labels and labelValues endpoints + - /loki/api/v1/label + - /loki/api/v1/labels + - /loki/api/v1/series + - /loki/api/v1/index/stats + - /loki/api/v1/index/volume + - /loki/api/v1/index/volume_range + - /loki/api/v1/format_query + - /loki/api/v1/detected_field + - /loki/api/v1/detected_fields + - /loki/api/v1/detected_labels + - /loki/api/v1/patterns + # -- Paths that are exposed by Loki Ruler. + # If deployment mode is Distributed, the requests are forwarded to the service: `{{"loki.rulerFullname"}}`. + # If deployment mode is SimpleScalable, the requests are forwarded to k8s service: `{{"loki.backendFullname"}}`. + # If deployment mode is SimpleScalable but `read.legacyReadTarget` is `true`, the requests are forwarded to k8s service: `{{"loki.readFullname"}}`. + # If deployment mode is SingleBinary, the requests are forwarded to the central/single k8s service: `{{"loki.singleBinaryFullname"}}` + ruler: + - /api/prom/rules + - /api/prom/api/v1/rules + - /api/prom/api/v1/alerts + - /loki/api/v1/rules + - /prometheus/api/v1/rules + - /prometheus/api/v1/alerts + # -- Hosts configuration for the ingress, passed through the `tpl` function to allow templating + hosts: + - loki.example.com + # -- TLS configuration for the ingress. Hosts passed through the `tpl` function to allow templating + tls: [] +# - hosts: +# - loki.example.com +# secretName: loki-distributed-tls + +###################################################################################################################### +# +# Migration +# +###################################################################################################################### + +# -- Options that may be necessary when performing a migration from another helm chart +migrate: + # -- When migrating from a distributed chart like loki-distributed or enterprise-logs + fromDistributed: + # -- Set to true if migrating from a distributed helm chart + enabled: false + # -- If migrating from a distributed service, provide the distributed deployment's + # memberlist service DNS so the new deployment can join its ring. + memberlistService: "" +###################################################################################################################### +# +# Single Binary Deployment +# +# For small Loki installations up to a few 10's of GB per day, or for testing and development. +# +###################################################################################################################### + +# Configuration for the single binary node(s) +singleBinary: + # -- Number of replicas for the single binary + replicas: 0 + autoscaling: + # -- Enable autoscaling + enabled: false + # -- Minimum autoscaling replicas for the single binary + minReplicas: 1 + # -- Maximum autoscaling replicas for the single binary + maxReplicas: 3 + # -- Target CPU utilisation percentage for the single binary + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the single binary + targetMemoryUtilizationPercentage: + image: + # -- The Docker registry for the single binary image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the single binary image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the single binary image. Overrides `loki.image.tag` + tag: null + # -- The name of the PriorityClass for single binary pods + priorityClassName: null + # -- Annotations for single binary StatefulSet + annotations: {} + # -- Annotations for single binary pods + podAnnotations: {} + # -- Additional labels for each `single binary` pod + podLabels: {} + # -- Additional selector labels for each `single binary` pod + selectorLabels: {} + service: + # -- Annotations for single binary Service + annotations: {} + # -- Additional labels for single binary Service + labels: {} + # -- Comma-separated list of Loki modules to load for the single binary + targetModule: "all" + # -- Labels for single binary service + extraArgs: [] + # -- Environment variables to add to the single binary pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the single binary pods + extraEnvFrom: [] + # -- Extra containers to add to the single binary loki pod + extraContainers: [] + # -- Init containers to add to the single binary pods + initContainers: [] + # -- Volume mounts to add to the single binary pods + extraVolumeMounts: [] + # -- Volumes to add to the single binary pods + extraVolumes: [] + # -- Resource requests and limits for the single binary + resources: {} + # -- Grace period to allow the single binary to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for single binary pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: single-binary + topologyKey: kubernetes.io/hostname + # -- DNS config for single binary pods + dnsConfig: {} + # -- Node selector for single binary pods + nodeSelector: {} + # -- Tolerations for single binary pods + tolerations: [] + persistence: + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: true + # -- Enable persistent disk + enabled: true + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Selector for persistent disk + selector: null + # -- Annotations for volume claim + annotations: {} +###################################################################################################################### +# +# Simple Scalable Deployment (SSD) Mode +# +# For small to medium size Loki deployments up to around 1 TB/day, this is the default mode for this helm chart +# +###################################################################################################################### + +# Configuration for the write pod(s) +write: + # -- Number of replicas for the write + replicas: 3 + autoscaling: + # -- Enable autoscaling for the write. + enabled: false + # -- Minimum autoscaling replicas for the write. + minReplicas: 2 + # -- Maximum autoscaling replicas for the write. + maxReplicas: 6 + # -- Target CPU utilisation percentage for the write. + targetCPUUtilizationPercentage: 60 + # -- Target memory utilization percentage for the write. + targetMemoryUtilizationPercentage: + # -- Behavior policies while scaling. + behavior: + # -- see https://github.com/grafana/loki/blob/main/docs/sources/operations/storage/wal.md#how-to-scale-updown for scaledown details + scaleUp: + policies: + - type: Pods + value: 1 + periodSeconds: 900 + scaleDown: + policies: + - type: Pods + value: 1 + periodSeconds: 1800 + stabilizationWindowSeconds: 3600 + image: + # -- The Docker registry for the write image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the write image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the write image. Overrides `loki.image.tag` + tag: null + # -- The name of the PriorityClass for write pods + priorityClassName: null + # -- Annotations for write StatefulSet + annotations: {} + # -- Annotations for write pods + podAnnotations: {} + # -- Additional labels for each `write` pod + podLabels: {} + # -- Additional selector labels for each `write` pod + selectorLabels: {} + service: + # -- Annotations for write Service + annotations: {} + # -- Additional labels for write Service + labels: {} + # -- Comma-separated list of Loki modules to load for the write + targetModule: "write" + # -- Additional CLI args for the write + extraArgs: [] + # -- Environment variables to add to the write pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the write pods + extraEnvFrom: [] + # -- Lifecycle for the write container + lifecycle: {} + # -- The default /flush_shutdown preStop hook is recommended as part of the ingester + # scaledown process so it's added to the template by default when autoscaling is enabled, + # but it's disabled to optimize rolling restarts in instances that will never be scaled + # down or when using chunks storage with WAL disabled. + # https://github.com/grafana/loki/blob/main/docs/sources/operations/storage/wal.md#how-to-scale-updown + # -- Init containers to add to the write pods + initContainers: [] + # -- Containers to add to the write pods + extraContainers: [] + # -- Volume mounts to add to the write pods + extraVolumeMounts: [] + # -- Volumes to add to the write pods + extraVolumes: [] + # -- volumeClaimTemplates to add to StatefulSet + extraVolumeClaimTemplates: [] + # -- Resource requests and limits for the write + resources: {} + # -- Grace period to allow the write to shutdown before it is killed. Especially for the ingester, + # this must be increased. It must be long enough so writes can be gracefully shutdown flushing/transferring + # all data and to successfully leave the member ring on shutdown. + terminationGracePeriodSeconds: 300 + # -- Affinity for write pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: write + topologyKey: kubernetes.io/hostname + # -- DNS config for write pods + dnsConfig: {} + # -- Node selector for write pods + nodeSelector: {} + # -- Topology Spread Constraints for write pods + topologySpreadConstraints: [] + # -- Tolerations for write pods + tolerations: [] + # -- The default is to deploy all pods in parallel. + podManagementPolicy: "Parallel" + persistence: + # -- Enable volume claims in pod spec + volumeClaimsEnabled: true + # -- Parameters used for the `data` volume when volumeClaimEnabled if false + dataVolumeParameters: + emptyDir: {} + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: false + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Selector for persistent disk + selector: null + # -- Annotations for volume claim + annotations: {} +# -- Configuration for the read pod(s) +read: + # -- Number of replicas for the read + replicas: 3 + autoscaling: + # -- Enable autoscaling for the read, this is only used if `queryIndex.enabled: true` + enabled: false + # -- Minimum autoscaling replicas for the read + minReplicas: 2 + # -- Maximum autoscaling replicas for the read + maxReplicas: 6 + # -- Target CPU utilisation percentage for the read + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the read + targetMemoryUtilizationPercentage: + # -- Behavior policies while scaling. + behavior: {} + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 60 + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + image: + # -- The Docker registry for the read image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the read image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the read image. Overrides `loki.image.tag` + tag: null + # -- The name of the PriorityClass for read pods + priorityClassName: null + # -- Annotations for read deployment + annotations: {} + # -- Annotations for read pods + podAnnotations: {} + # -- Additional labels for each `read` pod + podLabels: {} + # -- Additional selector labels for each `read` pod + selectorLabels: {} + service: + # -- Annotations for read Service + annotations: {} + # -- Additional labels for read Service + labels: {} + # -- Comma-separated list of Loki modules to load for the read + targetModule: "read" + # -- Whether or not to use the 2 target type simple scalable mode (read, write) or the + # 3 target type (read, write, backend). Legacy refers to the 2 target type, so true will + # run two targets, false will run 3 targets. + legacyReadTarget: false + # -- Additional CLI args for the read + extraArgs: [] + # -- Containers to add to the read pods + extraContainers: [] + # -- Environment variables to add to the read pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the read pods + extraEnvFrom: [] + # -- Lifecycle for the read container + lifecycle: {} + # -- Volume mounts to add to the read pods + extraVolumeMounts: [] + # -- Volumes to add to the read pods + extraVolumes: [] + # -- Resource requests and limits for the read + resources: {} + # -- Grace period to allow the read to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for read pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: read + topologyKey: kubernetes.io/hostname + # -- DNS config for read pods + dnsConfig: {} + # -- Node selector for read pods + nodeSelector: {} + # -- Topology Spread Constraints for read pods + topologySpreadConstraints: [] + # -- Tolerations for read pods + tolerations: [] + # -- The default is to deploy all pods in parallel. + podManagementPolicy: "Parallel" + persistence: + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: true + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Selector for persistent disk + selector: null + # -- Annotations for volume claim + annotations: {} +# -- Configuration for the backend pod(s) +backend: + # -- Number of replicas for the backend + replicas: 3 + autoscaling: + # -- Enable autoscaling for the backend. + enabled: false + # -- Minimum autoscaling replicas for the backend. + minReplicas: 3 + # -- Maximum autoscaling replicas for the backend. + maxReplicas: 6 + # -- Target CPU utilization percentage for the backend. + targetCPUUtilizationPercentage: 60 + # -- Target memory utilization percentage for the backend. + targetMemoryUtilizationPercentage: + # -- Behavior policies while scaling. + behavior: {} + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 60 + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + image: + # -- The Docker registry for the backend image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the backend image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the backend image. Overrides `loki.image.tag` + tag: null + # -- The name of the PriorityClass for backend pods + priorityClassName: null + # -- Annotations for backend StatefulSet + annotations: {} + # -- Annotations for backend pods + podAnnotations: {} + # -- Additional labels for each `backend` pod + podLabels: {} + # -- Additional selector labels for each `backend` pod + selectorLabels: {} + service: + # -- Annotations for backend Service + annotations: {} + # -- Additional labels for backend Service + labels: {} + # -- Comma-separated list of Loki modules to load for the backend + targetModule: "backend" + # -- Additional CLI args for the backend + extraArgs: [] + # -- Environment variables to add to the backend pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the backend pods + extraEnvFrom: [] + # -- Init containers to add to the backend pods + initContainers: [] + # -- Volume mounts to add to the backend pods + extraVolumeMounts: [] + # -- Volumes to add to the backend pods + extraVolumes: [] + # -- Resource requests and limits for the backend + resources: {} + # -- Grace period to allow the backend to shutdown before it is killed. Especially for the ingester, + # this must be increased. It must be long enough so backends can be gracefully shutdown flushing/transferring + # all data and to successfully leave the member ring on shutdown. + terminationGracePeriodSeconds: 300 + # -- Affinity for backend pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: backend + topologyKey: kubernetes.io/hostname + # -- DNS config for backend pods + dnsConfig: {} + # -- Node selector for backend pods + nodeSelector: {} + # -- Topology Spread Constraints for backend pods + topologySpreadConstraints: [] + # -- Tolerations for backend pods + tolerations: [] + # -- The default is to deploy all pods in parallel. + podManagementPolicy: "Parallel" + persistence: + # -- Enable volume claims in pod spec + volumeClaimsEnabled: true + # -- Parameters used for the `data` volume when volumeClaimEnabled if false + dataVolumeParameters: + emptyDir: {} + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: true + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Selector for persistent disk + selector: null + # -- Annotations for volume claim + annotations: {} +###################################################################################################################### +# +# Microservices Mode +# +# For large Loki deployments ingesting more than 1 TB/day +# +###################################################################################################################### + +# -- Configuration for the ingester +ingester: + # -- Number of replicas for the ingester, when zoneAwareReplication.enabled is true, the total + # number of replicas will match this value with each zone having 1/3rd of the total replicas. + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + autoscaling: + # -- Enable autoscaling for the ingester + enabled: false + # -- Minimum autoscaling replicas for the ingester + minReplicas: 1 + # -- Maximum autoscaling replicas for the ingester + maxReplicas: 3 + # -- Target CPU utilisation percentage for the ingester + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the ingester + targetMemoryUtilizationPercentage: null + # -- Allows one to define custom metrics using the HPA/v2 schema (for example, Pods, Object or External metrics) + customMetrics: [] + # - type: Pods + # pods: + # metric: + # name: loki_lines_total + # target: + # type: AverageValue + # averageValue: 10k + behavior: + # -- Enable autoscaling behaviours + enabled: false + # -- define scale down policies, must conform to HPAScalingRules + scaleDown: {} + # -- define scale up policies, must conform to HPAScalingRules + scaleUp: {} + image: + # -- The Docker registry for the ingester image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the ingester image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the ingester image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + priorityClassName: null + # -- Labels for ingester pods + podLabels: {} + # -- Annotations for ingester pods + podAnnotations: {} + # -- The name of the PriorityClass for ingester pods + # -- Labels for ingestor service + serviceLabels: {} + # -- Annotations for ingestor service + serviceAnnotations: {} + # -- Additional CLI args for the ingester + extraArgs: [] + # -- Environment variables to add to the ingester pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the ingester pods + extraEnvFrom: [] + # -- Volume mounts to add to the ingester pods + extraVolumeMounts: [] + # -- Volumes to add to the ingester pods + extraVolumes: [] + # -- Resource requests and limits for the ingester + resources: {} + # -- Containers to add to the ingester pods + extraContainers: [] + # -- Init containers to add to the ingester pods + initContainers: [] + # -- Grace period to allow the ingester to shutdown before it is killed. Especially for the ingestor, + # this must be increased. It must be long enough so ingesters can be gracefully shutdown flushing/transferring + # all data and to successfully leave the member ring on shutdown. + terminationGracePeriodSeconds: 300 + # -- Lifecycle for the ingester container + lifecycle: {} + # -- topologySpread for ingester pods. + # @default -- Defaults to allow skew no more than 1 node + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/component: ingester + # -- Affinity for ingester pods. Ignored if zoneAwareReplication is enabled. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: ingester + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: 1 + # -- Node selector for ingester pods + nodeSelector: {} + # -- Tolerations for ingester pods + tolerations: [] + # -- readiness probe settings for ingester pods. If empty, use `loki.readinessProbe` + readinessProbe: {} + # -- liveness probe settings for ingester pods. If empty use `loki.livenessProbe` + livenessProbe: {} + # -- UpdateStrategy for the ingester StatefulSets. + updateStrategy: + # -- One of 'OnDelete' or 'RollingUpdate' + type: RollingUpdate + # -- Optional for updateStrategy.type=RollingUpdate. See [Partitioned rolling updates](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions) in the StatefulSet docs for details. + # rollingUpdate: + # partition: 0 + persistence: + # -- Enable creating PVCs which is required when using boltdb-shipper + enabled: false + # -- Use emptyDir with ramdisk for storage. **Please note that all data in ingester will be lost on pod restart** + inMemory: false + # -- List of the ingester PVCs + # @notationType -- list + claims: + - name: data + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # - name: wal + # size: 150Gi + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: false + whenDeleted: Retain + whenScaled: Retain + # -- Adds the appProtocol field to the ingester service. This allows ingester to work with istio protocol selection. + appProtocol: + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + grpc: "" + # -- Enabling zone awareness on ingesters will create 3 statefulests where all writes will send a replica to each zone. + # This is primarily intended to accelerate rollout operations by allowing for multiple ingesters within a single + # zone to be shutdown and restart simultaneously (the remaining 2 zones will be guaranteed to have at least one copy + # of the data). + # Note: This can be used to run Loki over multiple cloud provider availability zones however this is not currently + # recommended as Loki is not optimized for this and cross zone network traffic costs can become extremely high + # extremely quickly. Even with zone awareness enabled, it is recommended to run Loki in a single availability zone. + zoneAwareReplication: + # -- Enable zone awareness. + enabled: true + # -- The percent of replicas in each zone that will be restarted at once. In a value of 0-100 + maxUnavailablePct: 33 + # -- zoneA configuration + zoneA: + # -- optionally define a node selector for this zone + nodeSelector: null + # -- optionally define extra affinity rules, by default different zones are not allowed to schedule on the same host + extraAffinity: {} + # -- Specific annotations to add to zone A statefulset + annotations: {} + # -- Specific annotations to add to zone A pods + podAnnotations: {} + zoneB: + # -- optionally define a node selector for this zone + nodeSelector: null + # -- optionally define extra affinity rules, by default different zones are not allowed to schedule on the same host + extraAffinity: {} + # -- Specific annotations to add to zone B statefulset + annotations: {} + # -- Specific annotations to add to zone B pods + podAnnotations: {} + zoneC: + # -- optionally define a node selector for this zone + nodeSelector: null + # -- optionally define extra affinity rules, by default different zones are not allowed to schedule on the same host + extraAffinity: {} + # -- Specific annotations to add to zone C statefulset + annotations: {} + # -- Specific annotations to add to zone C pods + podAnnotations: {} + # -- The migration block allows migrating non zone aware ingesters to zone aware ingesters. + migration: + enabled: false + excludeDefaultZone: false + readPath: false + writePath: false +# -- Configuration for the distributor +distributor: + # -- Number of replicas for the distributor + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + autoscaling: + # -- Enable autoscaling for the distributor + enabled: false + # -- Minimum autoscaling replicas for the distributor + minReplicas: 1 + # -- Maximum autoscaling replicas for the distributor + maxReplicas: 3 + # -- Target CPU utilisation percentage for the distributor + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the distributor + targetMemoryUtilizationPercentage: null + # -- Allows one to define custom metrics using the HPA/v2 schema (for example, Pods, Object or External metrics) + customMetrics: [] + # - type: Pods + # pods: + # metric: + # name: loki_lines_total + # target: + # type: AverageValue + # averageValue: 10k + behavior: + # -- Enable autoscaling behaviours + enabled: false + # -- define scale down policies, must conform to HPAScalingRules + scaleDown: {} + # -- define scale up policies, must conform to HPAScalingRules + scaleUp: {} + image: + # -- The Docker registry for the distributor image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the distributor image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the distributor image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for distributor pods + priorityClassName: null + # -- Labels for distributor pods + podLabels: {} + # -- Annotations for distributor pods + podAnnotations: {} + # -- Labels for distributor service + serviceLabels: {} + # -- Annotations for distributor service + serviceAnnotations: {} + # -- Additional CLI args for the distributor + extraArgs: [] + # -- Environment variables to add to the distributor pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the distributor pods + extraEnvFrom: [] + # -- Volume mounts to add to the distributor pods + extraVolumeMounts: [] + # -- Volumes to add to the distributor pods + extraVolumes: [] + # -- Resource requests and limits for the distributor + resources: {} + # -- Containers to add to the distributor pods + extraContainers: [] + # -- Grace period to allow the distributor to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for distributor pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: distributor + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: null + # -- Max Surge for distributor pods + maxSurge: 0 + # -- Node selector for distributor pods + nodeSelector: {} + # -- Topology Spread Constraints for distributor pods + topologySpreadConstraints: [] + # -- Tolerations for distributor pods + tolerations: [] + # -- Adds the appProtocol field to the distributor service. This allows distributor to work with istio protocol selection. + appProtocol: + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + grpc: "" +# -- Configuration for the querier +querier: + # -- Number of replicas for the querier + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + autoscaling: + # -- Enable autoscaling for the querier, this is only used if `indexGateway.enabled: true` + enabled: false + # -- Minimum autoscaling replicas for the querier + minReplicas: 1 + # -- Maximum autoscaling replicas for the querier + maxReplicas: 3 + # -- Target CPU utilisation percentage for the querier + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the querier + targetMemoryUtilizationPercentage: null + # -- Allows one to define custom metrics using the HPA/v2 schema (for example, Pods, Object or External metrics) + customMetrics: [] + # - type: External + # external: + # metric: + # name: loki_inflight_queries + # target: + # type: AverageValue + # averageValue: 12 + behavior: + # -- Enable autoscaling behaviours + enabled: false + # -- define scale down policies, must conform to HPAScalingRules + scaleDown: {} + # -- define scale up policies, must conform to HPAScalingRules + scaleUp: {} + image: + # -- The Docker registry for the querier image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the querier image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the querier image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for querier pods + priorityClassName: null + # -- Labels for querier pods + podLabels: {} + # -- Annotations for querier pods + podAnnotations: {} + # -- Labels for querier service + serviceLabels: {} + # -- Annotations for querier service + serviceAnnotations: {} + # -- Additional CLI args for the querier + extraArgs: [] + # -- Environment variables to add to the querier pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the querier pods + extraEnvFrom: [] + # -- Volume mounts to add to the querier pods + extraVolumeMounts: [] + # -- Volumes to add to the querier pods + extraVolumes: [] + # -- Resource requests and limits for the querier + resources: {} + # -- Containers to add to the querier pods + extraContainers: [] + # -- Init containers to add to the querier pods + initContainers: [] + # -- Grace period to allow the querier to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- topologySpread for querier pods. + # @default -- Defaults to allow skew no more then 1 node + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/component: querier + # -- Affinity for querier pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: querier + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: null + # -- Max Surge for querier pods + maxSurge: 0 + # -- Node selector for querier pods + nodeSelector: {} + # -- Tolerations for querier pods + tolerations: [] + # -- DNSConfig for querier pods + dnsConfig: {} + persistence: + # -- Enable creating PVCs for the querier cache + enabled: false + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Annotations for querier PVCs + annotations: {} + # -- Adds the appProtocol field to the querier service. This allows querier to work with istio protocol selection. + appProtocol: + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + grpc: "" +# -- Configuration for the query-frontend +queryFrontend: + # -- Number of replicas for the query-frontend + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + autoscaling: + # -- Enable autoscaling for the query-frontend + enabled: false + # -- Minimum autoscaling replicas for the query-frontend + minReplicas: 1 + # -- Maximum autoscaling replicas for the query-frontend + maxReplicas: 3 + # -- Target CPU utilisation percentage for the query-frontend + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the query-frontend + targetMemoryUtilizationPercentage: null + # -- Allows one to define custom metrics using the HPA/v2 schema (for example, Pods, Object or External metrics) + customMetrics: [] + # - type: Pods + # pods: + # metric: + # name: loki_query_rate + # target: + # type: AverageValue + # averageValue: 100 + behavior: + # -- Enable autoscaling behaviours + enabled: false + # -- define scale down policies, must conform to HPAScalingRules + scaleDown: {} + # -- define scale up policies, must conform to HPAScalingRules + scaleUp: {} + image: + # -- The Docker registry for the query-frontend image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the query-frontend image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the query-frontend image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for query-frontend pods + priorityClassName: null + # -- Labels for query-frontend pods + podLabels: {} + # -- Annotations for query-frontend pods + podAnnotations: {} + # -- Labels for query-frontend service + serviceLabels: {} + # -- Annotations for query-frontend service + serviceAnnotations: {} + # -- Additional CLI args for the query-frontend + extraArgs: [] + # -- Environment variables to add to the query-frontend pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the query-frontend pods + extraEnvFrom: [] + # -- Volume mounts to add to the query-frontend pods + extraVolumeMounts: [] + # -- Volumes to add to the query-frontend pods + extraVolumes: [] + # -- Resource requests and limits for the query-frontend + resources: {} + # -- Containers to add to the query-frontend pods + extraContainers: [] + # -- Grace period to allow the query-frontend to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for query-frontend pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: query-frontend + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: null + # -- Node selector for query-frontend pods + nodeSelector: {} + # -- Topology Spread Constraints for query-frontend pods + topologySpreadConstraints: [] + # -- Tolerations for query-frontend pods + tolerations: [] + # -- Adds the appProtocol field to the queryFrontend service. This allows queryFrontend to work with istio protocol selection. + appProtocol: + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + grpc: "" +# -- Configuration for the query-scheduler +queryScheduler: + # -- Number of replicas for the query-scheduler. + # It should be lower than `-querier.max-concurrent` to avoid generating back-pressure in queriers; + # it's also recommended that this value evenly divides the latter + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + image: + # -- The Docker registry for the query-scheduler image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the query-scheduler image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the query-scheduler image. Overrides `loki.image.tag` + tag: null + # -- The name of the PriorityClass for query-scheduler pods + priorityClassName: null + # -- Labels for query-scheduler pods + podLabels: {} + # -- Annotations for query-scheduler pods + podAnnotations: {} + # -- Labels for query-scheduler service + serviceLabels: {} + # -- Annotations for query-scheduler service + serviceAnnotations: {} + # -- Additional CLI args for the query-scheduler + extraArgs: [] + # -- Environment variables to add to the query-scheduler pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the query-scheduler pods + extraEnvFrom: [] + # -- Volume mounts to add to the query-scheduler pods + extraVolumeMounts: [] + # -- Volumes to add to the query-scheduler pods + extraVolumes: [] + # -- Resource requests and limits for the query-scheduler + resources: {} + # -- Containers to add to the query-scheduler pods + extraContainers: [] + # -- Grace period to allow the query-scheduler to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for query-scheduler pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: query-scheduler + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: 1 + # -- Node selector for query-scheduler pods + nodeSelector: {} + # -- Topology Spread Constraints for query-scheduler pods + topologySpreadConstraints: [] + # -- Tolerations for query-scheduler pods + tolerations: [] + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + appProtocol: + grpc: "" +# -- Configuration for the index-gateway +indexGateway: + # -- Number of replicas for the index-gateway + replicas: 0 + # -- Whether the index gateway should join the memberlist hashring + joinMemberlist: true + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + image: + # -- The Docker registry for the index-gateway image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the index-gateway image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the index-gateway image. Overrides `loki.image.tag` + tag: null + # -- The name of the PriorityClass for index-gateway pods + priorityClassName: null + # -- Labels for index-gateway pods + podLabels: {} + # -- Annotations for index-gateway pods + podAnnotations: {} + # -- Labels for index-gateway service + serviceLabels: {} + # -- Annotations for index-gateway service + serviceAnnotations: {} + # -- Additional CLI args for the index-gateway + extraArgs: [] + # -- Environment variables to add to the index-gateway pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the index-gateway pods + extraEnvFrom: [] + # -- Volume mounts to add to the index-gateway pods + extraVolumeMounts: [] + # -- Volumes to add to the index-gateway pods + extraVolumes: [] + # -- Resource requests and limits for the index-gateway + resources: {} + # -- Containers to add to the index-gateway pods + extraContainers: [] + # -- Init containers to add to the index-gateway pods + initContainers: [] + # -- Grace period to allow the index-gateway to shutdown before it is killed. + terminationGracePeriodSeconds: 300 + # -- Affinity for index-gateway pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: index-gateway + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: null + # -- Node selector for index-gateway pods + nodeSelector: {} + # -- Topology Spread Constraints for index-gateway pods + topologySpreadConstraints: [] + # -- Tolerations for index-gateway pods + tolerations: [] + persistence: + # -- Enable creating PVCs which is required when using boltdb-shipper + enabled: false + # -- Use emptyDir with ramdisk for storage. **Please note that all data in indexGateway will be lost on pod restart** + inMemory: false + # -- Size of persistent or memory disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Annotations for index gateway PVCs + annotations: {} + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: false + whenDeleted: Retain + whenScaled: Retain + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + appProtocol: + grpc: "" + # -- UpdateStrategy for the indexGateway StatefulSet. + updateStrategy: + # -- One of 'OnDelete' or 'RollingUpdate' + type: RollingUpdate + # -- Optional for updateStrategy.type=RollingUpdate. See [Partitioned rolling updates](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions) in the StatefulSet docs for details. + # rollingUpdate: + # partition: 0 +# -- Configuration for the compactor +compactor: + # -- Number of replicas for the compactor + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + image: + # -- The Docker registry for the compactor image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the compactor image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the compactor image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for compactor pods + priorityClassName: null + # -- Labels for compactor pods + podLabels: {} + # -- Annotations for compactor pods + podAnnotations: {} + # -- Affinity for compactor pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: compactor + topologyKey: kubernetes.io/hostname + # -- Labels for compactor service + serviceLabels: {} + # -- Annotations for compactor service + serviceAnnotations: {} + # -- Additional CLI args for the compactor + extraArgs: [] + # -- Environment variables to add to the compactor pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the compactor pods + extraEnvFrom: [] + # -- Volume mounts to add to the compactor pods + extraVolumeMounts: [] + # -- Volumes to add to the compactor pods + extraVolumes: [] + # -- readiness probe settings for ingester pods. If empty, use `loki.readinessProbe` + readinessProbe: {} + # -- liveness probe settings for ingester pods. If empty use `loki.livenessProbe` + livenessProbe: {} + # -- Resource requests and limits for the compactor + resources: {} + # -- Containers to add to the compactor pods + extraContainers: [] + # -- Init containers to add to the compactor pods + initContainers: [] + # -- Grace period to allow the compactor to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Node selector for compactor pods + nodeSelector: {} + # -- Tolerations for compactor pods + tolerations: [] + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + appProtocol: + grpc: "" + persistence: + # -- Enable creating PVCs for the compactor + enabled: false + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Annotations for compactor PVCs + annotations: {} + # -- List of the compactor PVCs + # @notationType -- list + claims: + - name: data + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # - name: wal + # size: 150Gi + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: false + whenDeleted: Retain + whenScaled: Retain + serviceAccount: + create: false + # -- The name of the ServiceAccount to use for the compactor. + # If not set and create is true, a name is generated by appending + # "-compactor" to the common ServiceAccount. + name: null + # -- Image pull secrets for the compactor service account + imagePullSecrets: [] + # -- Annotations for the compactor service account + annotations: {} + # -- Set this toggle to false to opt out of automounting API credentials for the service account + automountServiceAccountToken: true +# -- Configuration for the bloom-gateway +bloomGateway: + # -- Number of replicas for the bloom-gateway + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + image: + # -- The Docker registry for the bloom-gateway image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the bloom-gateway image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the bloom-gateway image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for bloom-gateway pods + priorityClassName: null + # -- Labels for bloom-gateway pods + podLabels: {} + # -- Annotations for bloom-gateway pods + podAnnotations: {} + # -- Affinity for bloom-gateway pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: bloom-gateway + topologyKey: kubernetes.io/hostname + # -- Labels for bloom-gateway service + serviceLabels: {} + # -- Annotations for bloom-gateway service + serviceAnnotations: {} + # -- Additional CLI args for the bloom-gateway + extraArgs: [] + # -- Environment variables to add to the bloom-gateway pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the bloom-gateway pods + extraEnvFrom: [] + # -- Volume mounts to add to the bloom-gateway pods + extraVolumeMounts: [] + # -- Volumes to add to the bloom-gateway pods + extraVolumes: [] + # -- readiness probe settings for ingester pods. If empty, use `loki.readinessProbe` + readinessProbe: {} + # -- liveness probe settings for ingester pods. If empty use `loki.livenessProbe` + livenessProbe: {} + # -- Resource requests and limits for the bloom-gateway + resources: {} + # -- Containers to add to the bloom-gateway pods + extraContainers: [] + # -- Init containers to add to the bloom-gateway pods + initContainers: [] + # -- Grace period to allow the bloom-gateway to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Node selector for bloom-gateway pods + nodeSelector: {} + # -- Tolerations for bloom-gateway pods + tolerations: [] + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + appProtocol: + grpc: "" + persistence: + # -- Enable creating PVCs for the bloom-gateway + enabled: false + # -- Annotations for bloom-gateway PVCs + annotations: {} + # -- List of the bloom-gateway PVCs + # @notationType -- list + claims: + - name: data + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: false + whenDeleted: Retain + whenScaled: Retain + serviceAccount: + create: false + # -- The name of the ServiceAccount to use for the bloom-gateway. + # If not set and create is true, a name is generated by appending + # "-bloom-gateway" to the common ServiceAccount. + name: null + # -- Image pull secrets for the bloom-gateway service account + imagePullSecrets: [] + # -- Annotations for the bloom-gateway service account + annotations: {} + # -- Set this toggle to false to opt out of automounting API credentials for the service account + automountServiceAccountToken: true +# -- Configuration for the bloom-planner +bloomPlanner: + # -- Number of replicas for the bloom-planner + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + image: + # -- The Docker registry for the bloom-planner image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the bloom-planner image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the bloom-planner image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for bloom-planner pods + priorityClassName: null + # -- Labels for bloom-planner pods + podLabels: {} + # -- Annotations for bloom-planner pods + podAnnotations: {} + # -- Affinity for bloom-planner pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: bloom-planner + topologyKey: kubernetes.io/hostname + # -- Labels for bloom-planner service + serviceLabels: {} + # -- Annotations for bloom-planner service + serviceAnnotations: {} + # -- Additional CLI args for the bloom-planner + extraArgs: [] + # -- Environment variables to add to the bloom-planner pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the bloom-planner pods + extraEnvFrom: [] + # -- Volume mounts to add to the bloom-planner pods + extraVolumeMounts: [] + # -- Volumes to add to the bloom-planner pods + extraVolumes: [] + # -- readiness probe settings for ingester pods. If empty, use `loki.readinessProbe` + readinessProbe: {} + # -- liveness probe settings for ingester pods. If empty use `loki.livenessProbe` + livenessProbe: {} + # -- Resource requests and limits for the bloom-planner + resources: {} + # -- Containers to add to the bloom-planner pods + extraContainers: [] + # -- Init containers to add to the bloom-planner pods + initContainers: [] + # -- Grace period to allow the bloom-planner to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Node selector for bloom-planner pods + nodeSelector: {} + # -- Tolerations for bloom-planner pods + tolerations: [] + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + appProtocol: + grpc: "" + persistence: + # -- Enable creating PVCs for the bloom-planner + enabled: false + # -- Annotations for bloom-planner PVCs + annotations: {} + # -- List of the bloom-planner PVCs + # @notationType -- list + claims: + - name: data + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: false + whenDeleted: Retain + whenScaled: Retain + serviceAccount: + create: false + # -- The name of the ServiceAccount to use for the bloom-planner. + # If not set and create is true, a name is generated by appending + # "-bloom-planner" to the common ServiceAccount. + name: null + # -- Image pull secrets for the bloom-planner service account + imagePullSecrets: [] + # -- Annotations for the bloom-planner service account + annotations: {} + # -- Set this toggle to false to opt out of automounting API credentials for the service account + automountServiceAccountToken: true +# -- Configuration for the bloom-builder +bloomBuilder: + # -- Number of replicas for the bloom-builder + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + autoscaling: + # -- Enable autoscaling for the bloom-builder + enabled: false + # -- Minimum autoscaling replicas for the bloom-builder + minReplicas: 1 + # -- Maximum autoscaling replicas for the bloom-builder + maxReplicas: 3 + # -- Target CPU utilisation percentage for the bloom-builder + targetCPUUtilizationPercentage: 60 + # -- Target memory utilisation percentage for the bloom-builder + targetMemoryUtilizationPercentage: null + # -- Allows one to define custom metrics using the HPA/v2 schema (for example, Pods, Object or External metrics) + customMetrics: [] + # - type: Pods + # pods: + # metric: + # name: loki_query_rate + # target: + # type: AverageValue + # averageValue: 100 + behavior: + # -- Enable autoscaling behaviours + enabled: false + # -- define scale down policies, must conform to HPAScalingRules + scaleDown: {} + # -- define scale up policies, must conform to HPAScalingRules + scaleUp: {} + image: + # -- The Docker registry for the bloom-builder image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the bloom-builder image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the bloom-builder image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for bloom-builder pods + priorityClassName: null + # -- Labels for bloom-builder pods + podLabels: {} + # -- Annotations for bloom-builder pods + podAnnotations: {} + # -- Labels for bloom-builder service + serviceLabels: {} + # -- Annotations for bloom-builder service + serviceAnnotations: {} + # -- Additional CLI args for the bloom-builder + extraArgs: [] + # -- Environment variables to add to the bloom-builder pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the bloom-builder pods + extraEnvFrom: [] + # -- Volume mounts to add to the bloom-builder pods + extraVolumeMounts: [] + # -- Volumes to add to the bloom-builder pods + extraVolumes: [] + # -- Resource requests and limits for the bloom-builder + resources: {} + # -- Containers to add to the bloom-builder pods + extraContainers: [] + # -- Grace period to allow the bloom-builder to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for bloom-builder pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: bloom-builder + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: null + # -- Node selector for bloom-builder pods + nodeSelector: {} + # -- Tolerations for bloom-builder pods + tolerations: [] + # -- Adds the appProtocol field to the queryFrontend service. This allows bloomBuilder to work with istio protocol selection. + appProtocol: + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + grpc: "" +# -- Configuration for the pattern ingester +patternIngester: + # -- Number of replicas for the pattern ingester + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + image: + # -- The Docker registry for the pattern ingester image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the pattern ingester image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the pattern ingester image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for pattern ingester pods + priorityClassName: null + # -- Labels for pattern ingester pods + podLabels: {} + # -- Annotations for pattern ingester pods + podAnnotations: {} + # -- Affinity for pattern ingester pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: pattern-ingester + topologyKey: kubernetes.io/hostname + # -- Labels for pattern ingester service + serviceLabels: {} + # -- Annotations for pattern ingester service + serviceAnnotations: {} + # -- Additional CLI args for the pattern ingester + extraArgs: [] + # -- Environment variables to add to the pattern ingester pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the pattern ingester pods + extraEnvFrom: [] + # -- Volume mounts to add to the pattern ingester pods + extraVolumeMounts: [] + # -- Volumes to add to the pattern ingester pods + extraVolumes: [] + # -- readiness probe settings for ingester pods. If empty, use `loki.readinessProbe` + readinessProbe: {} + # -- liveness probe settings for ingester pods. If empty use `loki.livenessProbe` + livenessProbe: {} + # -- Resource requests and limits for the pattern ingester + resources: {} + # -- Containers to add to the pattern ingester pods + extraContainers: [] + # -- Init containers to add to the pattern ingester pods + initContainers: [] + # -- Grace period to allow the pattern ingester to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Node selector for pattern ingester pods + nodeSelector: {} + # -- Topology Spread Constraints for pattern ingester pods + topologySpreadConstraints: [] + # -- Tolerations for pattern ingester pods + tolerations: [] + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + appProtocol: + grpc: "" + persistence: + # -- Enable creating PVCs for the pattern ingester + enabled: false + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Annotations for pattern ingester PVCs + annotations: {} + # -- List of the pattern ingester PVCs + # @notationType -- list + claims: + - name: data + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # - name: wal + # size: 150Gi + # -- Enable StatefulSetAutoDeletePVC feature + enableStatefulSetAutoDeletePVC: false + whenDeleted: Retain + whenScaled: Retain + serviceAccount: + create: false + # -- The name of the ServiceAccount to use for the pattern ingester. + # If not set and create is true, a name is generated by appending + # "-pattern-ingester" to the common ServiceAccount. + name: null + # -- Image pull secrets for the pattern ingester service account + imagePullSecrets: [] + # -- Annotations for the pattern ingester service account + annotations: {} + # -- Set this toggle to false to opt out of automounting API credentials for the service account + automountServiceAccountToken: true +# -- Configuration for the ruler +ruler: + # -- The ruler component is optional and can be disabled if desired. + enabled: true + # -- Number of replicas for the ruler + replicas: 0 + # -- hostAliases to add + hostAliases: [] + # - ip: 1.2.3.4 + # hostnames: + # - domain.tld + image: + # -- The Docker registry for the ruler image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the ruler image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the ruler image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for ruler pods + priorityClassName: null + # -- Labels for compactor pods + podLabels: {} + # -- Annotations for ruler pods + podAnnotations: {} + # -- Labels for ruler service + serviceLabels: {} + # -- Annotations for ruler service + serviceAnnotations: {} + # -- Additional CLI args for the ruler + extraArgs: [] + # -- Environment variables to add to the ruler pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the ruler pods + extraEnvFrom: [] + # -- Volume mounts to add to the ruler pods + extraVolumeMounts: [] + # -- Volumes to add to the ruler pods + extraVolumes: [] + # -- Resource requests and limits for the ruler + resources: {} + # -- Containers to add to the ruler pods + extraContainers: [] + # -- Init containers to add to the ruler pods + initContainers: [] + # -- Grace period to allow the ruler to shutdown before it is killed + terminationGracePeriodSeconds: 300 + # -- Affinity for ruler pods. + # @default -- Hard node anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: ruler + topologyKey: kubernetes.io/hostname + # -- Pod Disruption Budget maxUnavailable + maxUnavailable: null + # -- Node selector for ruler pods + nodeSelector: {} + # -- Topology Spread Constraints for ruler pods + topologySpreadConstraints: [] + # -- Tolerations for ruler pods + tolerations: [] + # -- DNSConfig for ruler pods + dnsConfig: {} + persistence: + # -- Enable creating PVCs which is required when using recording rules + enabled: false + # -- Size of persistent disk + size: 10Gi + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Annotations for ruler PVCs + annotations: {} + # -- Set the optional grpc service protocol. Ex: "grpc", "http2" or "https" + appProtocol: + grpc: "" + # -- Directories containing rules files + directories: {} + # tenant_foo: + # rules1.txt: | + # groups: + # - name: should_fire + # rules: + # - alert: HighPercentageError + # expr: | + # sum(rate({app="foo", env="production"} |= "error" [5m])) by (job) + # / + # sum(rate({app="foo", env="production"}[5m])) by (job) + # > 0.05 + # for: 10m + # labels: + # severity: warning + # annotations: + # summary: High error rate + # - name: credentials_leak + # rules: + # - alert: http-credentials-leaked + # annotations: + # message: "{{ $labels.job }} is leaking http basic auth credentials." + # expr: 'sum by (cluster, job, pod) (count_over_time({namespace="prod"} |~ "http(s?)://(\\w+):(\\w+)@" [5m]) > 0)' + # for: 10m + # labels: + # severity: critical + # rules2.txt: | + # groups: + # - name: example + # rules: + # - alert: HighThroughputLogStreams + # expr: sum by(container) (rate({job=~"loki-dev/.*"}[1m])) > 1000 + # for: 2m + # tenant_bar: + # rules1.txt: | + # groups: + # - name: should_fire + # rules: + # - alert: HighPercentageError + # expr: | + # sum(rate({app="foo", env="production"} |= "error" [5m])) by (job) + # / + # sum(rate({app="foo", env="production"}[5m])) by (job) + # > 0.05 + # for: 10m + # labels: + # severity: warning + # annotations: + # summary: High error rate + # - name: credentials_leak + # rules: + # - alert: http-credentials-leaked + # annotations: + # message: "{{ $labels.job }} is leaking http basic auth credentials." + # expr: 'sum by (cluster, job, pod) (count_over_time({namespace="prod"} |~ "http(s?)://(\\w+):(\\w+)@" [5m]) > 0)' + # for: 10m + # labels: + # severity: critical + # rules2.txt: | + # groups: + # - name: example + # rules: + # - alert: HighThroughputLogStreams + # expr: sum by(container) (rate({job=~"loki-dev/.*"}[1m])) > 1000 + # for: 2m +memcached: + image: + # -- Memcached Docker image repository + repository: memcached + # -- Memcached Docker image tag + tag: 1.6.32-alpine + # -- Memcached Docker image pull policy + pullPolicy: IfNotPresent + # -- The SecurityContext override for memcached pods + podSecurityContext: + runAsNonRoot: true + runAsUser: 11211 + runAsGroup: 11211 + fsGroup: 11211 + # -- The name of the PriorityClass for memcached pods + priorityClassName: null + # -- The SecurityContext for memcached containers + containerSecurityContext: + readOnlyRootFilesystem: true + capabilities: + drop: [ALL] + allowPrivilegeEscalation: false +memcachedExporter: + # -- Whether memcached metrics should be exported + enabled: true + image: + repository: prom/memcached-exporter + tag: v0.15.0 + pullPolicy: IfNotPresent + resources: + requests: {} + limits: {} + # -- The SecurityContext for memcached exporter containers + containerSecurityContext: + readOnlyRootFilesystem: true + capabilities: + drop: [ALL] + allowPrivilegeEscalation: false + # -- Extra args to add to the exporter container. + # Example: + # extraArgs: + # memcached.tls.enable: true + # memcached.tls.cert-file: /certs/cert.crt + # memcached.tls.key-file: /certs/cert.key + # memcached.tls.ca-file: /certs/ca.crt + # memcached.tls.insecure-skip-verify: false + # memcached.tls.server-name: memcached + extraArgs: {} +resultsCache: + # -- Specifies whether memcached based results-cache should be enabled + enabled: true + # -- Specify how long cached results should be stored in the results-cache before being expired + defaultValidity: 12h + # -- Memcached operation timeout + timeout: 500ms + # -- Total number of results-cache replicas + replicas: 1 + # -- Port of the results-cache service + port: 11211 + # -- Amount of memory allocated to results-cache for object storage (in MB). + allocatedMemory: 1024 + # -- Maximum item results-cache for memcached (in MB). + maxItemMemory: 5 + # -- Maximum number of connections allowed + connectionLimit: 16384 + # -- Max memory to use for cache write back + writebackSizeLimit: 500MB + # -- Max number of objects to use for cache write back + writebackBuffer: 500000 + # -- Number of parallel threads for cache write back + writebackParallelism: 1 + # -- Extra init containers for results-cache pods + initContainers: [] + # -- Annotations for the results-cache pods + annotations: {} + # -- Node selector for results-cache pods + nodeSelector: {} + # -- Affinity for results-cache pods + affinity: {} + # -- topologySpreadConstraints allows to customize the default topologySpreadConstraints. This can be either a single dict as shown below or a slice of topologySpreadConstraints. + # labelSelector is taken from the constraint itself (if it exists) or is generated by the chart using the same selectors as for services. + topologySpreadConstraints: [] + # maxSkew: 1 + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: ScheduleAnyway + # -- Tolerations for results-cache pods + tolerations: [] + # -- Pod Disruption Budget + podDisruptionBudget: + maxUnavailable: 1 + # -- The name of the PriorityClass for results-cache pods + priorityClassName: null + # -- Labels for results-cache pods + podLabels: {} + # -- Annotations for results-cache pods + podAnnotations: {} + # -- Management policy for results-cache pods + podManagementPolicy: Parallel + # -- Grace period to allow the results-cache to shutdown before it is killed + terminationGracePeriodSeconds: 60 + # -- Stateful results-cache strategy + statefulStrategy: + type: RollingUpdate + # -- Add extended options for results-cache memcached container. The format is the same as for the memcached -o/--extend flag. + # Example: + # extraExtendedOptions: 'tls,modern,track_sizes' + extraExtendedOptions: "" + # -- Additional CLI args for results-cache + extraArgs: {} + # -- Additional containers to be added to the results-cache pod. + extraContainers: [] + # -- Additional volumes to be added to the results-cache pod (applies to both memcached and exporter containers). + # Example: + # extraVolumes: + # - name: extra-volume + # secret: + # secretName: extra-volume-secret + extraVolumes: [] + # -- Additional volume mounts to be added to the results-cache pod (applies to both memcached and exporter containers). + # Example: + # extraVolumeMounts: + # - name: extra-volume + # mountPath: /etc/extra-volume + # readOnly: true + extraVolumeMounts: [] + # -- Resource requests and limits for the results-cache + # By default a safe memory limit will be requested based on allocatedMemory value (floor (* 1.2 allocatedMemory)). + resources: null + # -- Service annotations and labels + service: + annotations: {} + labels: {} + # -- Persistence settings for the results-cache + persistence: + # -- Enable creating PVCs for the results-cache + enabled: false + # -- Size of persistent disk, must be in G or Gi + storageSize: 10G + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Volume mount path + mountPath: /data +chunksCache: + # -- Specifies whether memcached based chunks-cache should be enabled + enabled: true + # -- Batchsize for sending and receiving chunks from chunks cache + batchSize: 4 + # -- Parallel threads for sending and receiving chunks from chunks cache + parallelism: 5 + # -- Memcached operation timeout + timeout: 2000ms + # -- Specify how long cached chunks should be stored in the chunks-cache before being expired + defaultValidity: 0s + # -- Total number of chunks-cache replicas + replicas: 1 + # -- Port of the chunks-cache service + port: 11211 + # -- Amount of memory allocated to chunks-cache for object storage (in MB). + allocatedMemory: 8192 + # -- Maximum item memory for chunks-cache (in MB). + maxItemMemory: 5 + # -- Maximum number of connections allowed + connectionLimit: 16384 + # -- Max memory to use for cache write back + writebackSizeLimit: 500MB + # -- Max number of objects to use for cache write back + writebackBuffer: 500000 + # -- Number of parallel threads for cache write back + writebackParallelism: 1 + # -- Extra init containers for chunks-cache pods + initContainers: [] + # -- Annotations for the chunks-cache pods + annotations: {} + # -- Node selector for chunks-cache pods + nodeSelector: {} + # -- Affinity for chunks-cache pods + affinity: {} + # -- topologySpreadConstraints allows to customize the default topologySpreadConstraints. This can be either a single dict as shown below or a slice of topologySpreadConstraints. + # labelSelector is taken from the constraint itself (if it exists) or is generated by the chart using the same selectors as for services. + topologySpreadConstraints: [] + # maxSkew: 1 + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: ScheduleAnyway + # -- Tolerations for chunks-cache pods + tolerations: [] + # -- Pod Disruption Budget + podDisruptionBudget: + maxUnavailable: 1 + # -- The name of the PriorityClass for chunks-cache pods + priorityClassName: null + # -- Labels for chunks-cache pods + podLabels: {} + # -- Annotations for chunks-cache pods + podAnnotations: {} + # -- Management policy for chunks-cache pods + podManagementPolicy: Parallel + # -- Grace period to allow the chunks-cache to shutdown before it is killed + terminationGracePeriodSeconds: 60 + # -- Stateful chunks-cache strategy + statefulStrategy: + type: RollingUpdate + # -- Add extended options for chunks-cache memcached container. The format is the same as for the memcached -o/--extend flag. + # Example: + # extraExtendedOptions: 'tls,no_hashexpand' + extraExtendedOptions: "" + # -- Additional CLI args for chunks-cache + extraArgs: {} + # -- Additional containers to be added to the chunks-cache pod. + extraContainers: [] + # -- Additional volumes to be added to the chunks-cache pod (applies to both memcached and exporter containers). + # Example: + # extraVolumes: + # - name: extra-volume + # secret: + # secretName: extra-volume-secret + extraVolumes: [] + # -- Additional volume mounts to be added to the chunks-cache pod (applies to both memcached and exporter containers). + # Example: + # extraVolumeMounts: + # - name: extra-volume + # mountPath: /etc/extra-volume + # readOnly: true + extraVolumeMounts: [] + # -- Resource requests and limits for the chunks-cache + # By default a safe memory limit will be requested based on allocatedMemory value (floor (* 1.2 allocatedMemory)). + resources: null + # -- Service annotations and labels + service: + annotations: {} + labels: {} + # -- Persistence settings for the chunks-cache + persistence: + # -- Enable creating PVCs for the chunks-cache + enabled: false + # -- Size of persistent disk, must be in G or Gi + storageSize: 10G + # -- Storage class to be used. + # If defined, storageClassName: . + # If set to "-", storageClassName: "", which disables dynamic provisioning. + # If empty or set to null, no storageClassName spec is + # set, choosing the default provisioner (gp2 on AWS, standard on GKE, AWS, and OpenStack). + storageClass: null + # -- Volume mount path + mountPath: /data +###################################################################################################################### +# +# Subchart configurations +# +###################################################################################################################### +# -- Setting for the Grafana Rollout Operator https://github.com/grafana/helm-charts/tree/main/charts/rollout-operator +rollout_operator: + enabled: false + # -- podSecurityContext is the pod security context for the rollout operator. + # When installing on OpenShift, override podSecurityContext settings with + # + # rollout_operator: + # podSecurityContext: + # fsGroup: null + # runAsGroup: null + # runAsUser: null + podSecurityContext: + fsGroup: 10001 + runAsGroup: 10001 + runAsNonRoot: true + runAsUser: 10001 + seccompProfile: + type: RuntimeDefault + # Set the container security context + securityContext: + readOnlyRootFilesystem: true + capabilities: + drop: [ALL] + allowPrivilegeEscalation: false +# -- Configuration for the minio subchart +minio: + enabled: false + replicas: 1 + # Minio requires 2 to 16 drives for erasure code (drivesPerNode * replicas) + # https://docs.min.io/docs/minio-erasure-code-quickstart-guide + # Since we only have 1 replica, that means 2 drives must be used. + drivesPerNode: 2 + rootUser: enterprise-logs + rootPassword: supersecret + buckets: + - name: chunks + policy: none + purge: false + - name: ruler + policy: none + purge: false + - name: admin + policy: none + purge: false + persistence: + size: 5Gi + annotations: {} + resources: + requests: + cpu: 100m + memory: 128Mi + # Allow the address used by Loki to refer to Minio to be overridden + address: null +# Create extra manifests via values. Would be passed through `tpl` for templating +# objects can also be provided as multiline strings, useful for templating field names +extraObjects: [] +# - apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: loki-alerting-rules +# data: +# loki-alerting-rules.yaml: |- +# groups: +# - name: example +# rules: +# - alert: example +# expr: | +# sum(count_over_time({app="loki"} |~ "error")) > 0 +# for: 3m +# labels: +# severity: warning +# category: logs +# annotations: +# message: "loki has encountered errors" +# - | +# apiVersion: v1 +# kind: Secret +# type: Opaque +# metadata: +# name: loki-distributed-basic-auth +# data: +# {{- range .Values.loki.tenants }} +# {{ .name }}: {{ b64enc .password | quote }} +# {{- end }} + +sidecar: + image: + # -- The Docker registry and image for the k8s sidecar + repository: kiwigrid/k8s-sidecar + # -- Docker image tag + tag: 1.28.0 + # -- Docker image sha. If empty, no sha will be used + sha: "" + # -- Docker image pull policy + pullPolicy: IfNotPresent + # -- Resource requests and limits for the sidecar + resources: {} + # limits: + # cpu: 100m + # memory: 100Mi + # requests: + # cpu: 50m + # memory: 50Mi + # -- The SecurityContext for the sidecar. + securityContext: {} + # -- Set to true to skip tls verification for kube api calls. + skipTlsVerify: false + # -- Ensure that rule files aren't conflicting and being overwritten by prefixing their name with the namespace they are defined in. + enableUniqueFilenames: false + # -- Readiness probe definition. Probe is disabled on the sidecar by default. + readinessProbe: {} + # -- Liveness probe definition. Probe is disabled on the sidecar by default. + livenessProbe: {} + rules: + # -- Whether or not to create a sidecar to ingest rule from specific ConfigMaps and/or Secrets. + enabled: true + # -- Label that the configmaps/secrets with rules will be marked with. + label: loki_rule + # -- Label value that the configmaps/secrets with rules will be set to. + labelValue: "" + # -- Folder into which the rules will be placed. + folder: /rules + # -- Comma separated list of namespaces. If specified, the sidecar will search for config-maps/secrets inside these namespaces. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify 'ALL' to search in all namespaces. + searchNamespace: null + # -- Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH request, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # -- Search in configmap, secret, or both. + resource: both + # -- Absolute path to the shell script to execute after a configmap or secret has been reloaded. + script: null + # -- WatchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S. + watchServerTimeout: 60 + # + # -- WatchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # Defaults to 66sec. + watchClientTimeout: 60 + # -- Log level of the sidecar container. + logLevel: INFO +############################################## WARNING ############################################################### +# +# DEPRECATED VALUES +# +# The following values are deprecated and will be removed in a future version of the helm chart! +# +############################################## WARNING ############################################################## + +# -- DEPRECATED Monitoring section determines which monitoring features to enable, this section is being replaced +# by https://github.com/grafana/meta-monitoring-chart +monitoring: + # Dashboards for monitoring Loki + dashboards: + # -- If enabled, create configmap with dashboards for monitoring Loki + enabled: false + # -- Alternative namespace to create dashboards ConfigMap in + namespace: null + # -- Additional annotations for the dashboards ConfigMap + annotations: {} + # -- Labels for the dashboards ConfigMap + labels: + grafana_dashboard: "1" + # -- DEPRECATED Recording rules for monitoring Loki, required for some dashboards + rules: + # -- If enabled, create PrometheusRule resource with Loki recording rules + enabled: false + # -- Include alerting rules + alerting: true + # -- Specify which individual alerts should be disabled + # -- Instead of turning off each alert one by one, set the .monitoring.rules.alerting value to false instead. + # -- If you disable all the alerts and keep .monitoring.rules.alerting set to true, the chart will fail to render. + disabled: {} + # LokiRequestErrors: true + # LokiRequestPanics: true + # -- Alternative namespace to create PrometheusRule resources in + namespace: null + # -- Additional annotations for the rules PrometheusRule resource + annotations: {} + # -- Additional labels for the rules PrometheusRule resource + labels: {} + # -- Additional labels for PrometheusRule alerts + additionalRuleLabels: {} + # -- Additional groups to add to the rules file + additionalGroups: [] + # - name: additional-loki-rules + # rules: + # - record: job:loki_request_duration_seconds_bucket:sum_rate + # expr: sum(rate(loki_request_duration_seconds_bucket[1m])) by (le, job) + # - record: job_route:loki_request_duration_seconds_bucket:sum_rate + # expr: sum(rate(loki_request_duration_seconds_bucket[1m])) by (le, job, route) + # - record: node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate + # expr: sum(rate(container_cpu_usage_seconds_total[1m])) by (node, namespace, pod, container) + # -- DEPRECATED ServiceMonitor configuration + serviceMonitor: + # -- If enabled, ServiceMonitor resources for Prometheus Operator are created + enabled: false + # -- Namespace selector for ServiceMonitor resources + namespaceSelector: {} + # -- ServiceMonitor annotations + annotations: {} + # -- Additional ServiceMonitor labels + labels: {} + # -- ServiceMonitor scrape interval + # Default is 15s because included recording rules use a 1m rate, and scrape interval needs to be at + # least 1/4 rate interval. + interval: 15s + # -- ServiceMonitor scrape timeout in Go duration format (e.g. 15s) + scrapeTimeout: null + # -- ServiceMonitor relabel configs to apply to samples before scraping + # https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + relabelings: [] + # -- ServiceMonitor metric relabel configs to apply to samples before ingestion + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#endpoint + metricRelabelings: [] + # -- ServiceMonitor will use http by default, but you can pick https as well + scheme: http + # -- ServiceMonitor will use these tlsConfig settings to make the health check requests + tlsConfig: null + # -- If defined, will create a MetricsInstance for the Grafana Agent Operator. + metricsInstance: + # -- If enabled, MetricsInstance resources for Grafana Agent Operator are created + enabled: true + # -- MetricsInstance annotations + annotations: {} + # -- Additional MetricsInstance labels + labels: {} + # -- If defined a MetricsInstance will be created to remote write metrics. + remoteWrite: null + # -- DEPRECATED Self monitoring determines whether Loki should scrape its own logs. + # This feature currently relies on the Grafana Agent Operator being installed, + # which is installed by default using the grafana-agent-operator sub-chart. + # It will create custom resources for GrafanaAgent, LogsInstance, and PodLogs to configure + # scrape configs to scrape its own logs with the labels expected by the included dashboards. + selfMonitoring: + enabled: false + # -- Tenant to use for self monitoring + tenant: + # -- Name of the tenant + name: "self-monitoring" + # -- Password of the gateway for Basic auth + password: null + # -- Namespace to create additional tenant token secret in. Useful if your Grafana instance + # is in a separate namespace. Token will still be created in the canary namespace. + secretNamespace: "{{ .Release.Namespace }}" + # -- DEPRECATED Grafana Agent configuration + grafanaAgent: + # -- DEPRECATED Controls whether to install the Grafana Agent Operator and its CRDs. + # Note that helm will not install CRDs if this flag is enabled during an upgrade. + # In that case install the CRDs manually from https://github.com/grafana/agent/tree/main/production/operator/crds + installOperator: false + # -- Grafana Agent annotations + annotations: {} + # -- Additional Grafana Agent labels + labels: {} + # -- Enable the config read api on port 8080 of the agent + enableConfigReadAPI: false + # -- The name of the PriorityClass for GrafanaAgent pods + priorityClassName: null + # -- Resource requests and limits for the grafanaAgent pods + resources: {} + # limits: + # memory: 200Mi + # requests: + # cpu: 50m + # memory: 100Mi + # -- Tolerations for GrafanaAgent pods + tolerations: [] + # PodLogs configuration + podLogs: + # -- PodLogs version + apiVersion: monitoring.grafana.com/v1alpha1 + # -- PodLogs annotations + annotations: {} + # -- Additional PodLogs labels + labels: {} + # -- PodLogs relabel configs to apply to samples before scraping + # https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + relabelings: [] + # -- Additional pipeline stages to process logs after scraping + # https://grafana.com/docs/agent/latest/operator/api/#pipelinestagespec-a-namemonitoringgrafanacomv1alpha1pipelinestagespeca + additionalPipelineStages: [] + # LogsInstance configuration + logsInstance: + # -- LogsInstance annotations + annotations: {} + # -- Additional LogsInstance labels + labels: {} + # -- Additional clients for remote write + clients: null +# -- DEPRECATED Configuration for the table-manager. The table-manager is only necessary when using a deprecated +# index type such as Cassandra, Bigtable, or DynamoDB, it has not been necessary since loki introduced self- +# contained index types like 'boltdb-shipper' and 'tsdb'. This will be removed in a future helm chart. +tableManager: + # -- Specifies whether the table-manager should be enabled + enabled: false + image: + # -- The Docker registry for the table-manager image. Overrides `loki.image.registry` + registry: null + # -- Docker image repository for the table-manager image. Overrides `loki.image.repository` + repository: null + # -- Docker image tag for the table-manager image. Overrides `loki.image.tag` + tag: null + # -- Command to execute instead of defined in Docker image + command: null + # -- The name of the PriorityClass for table-manager pods + priorityClassName: null + # -- Labels for table-manager pods + podLabels: {} + # -- Annotations for table-manager deployment + annotations: {} + # -- Annotations for table-manager pods + podAnnotations: {} + service: + # -- Annotations for table-manager Service + annotations: {} + # -- Additional labels for table-manager Service + labels: {} + # -- Additional CLI args for the table-manager + extraArgs: [] + # -- Environment variables to add to the table-manager pods + extraEnv: [] + # -- Environment variables from secrets or configmaps to add to the table-manager pods + extraEnvFrom: [] + # -- Volume mounts to add to the table-manager pods + extraVolumeMounts: [] + # -- Volumes to add to the table-manager pods + extraVolumes: [] + # -- Resource requests and limits for the table-manager + resources: {} + # -- Containers to add to the table-manager pods + extraContainers: [] + # -- Grace period to allow the table-manager to shutdown before it is killed + terminationGracePeriodSeconds: 30 + # -- Affinity for table-manager pods. + # @default -- Hard node and anti-affinity + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: table-manager + topologyKey: kubernetes.io/hostname + # -- DNS config table-manager pods + dnsConfig: {} + # -- Node selector for table-manager pods + nodeSelector: {} + # -- Tolerations for table-manager pods + tolerations: [] + # -- Enable deletes by retention + retention_deletes_enabled: false + # -- Set retention period + retention_period: 0 diff --git a/utils/assets/charts/mongo-express/.helmignore b/utils/assets/charts/mongo-express/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/utils/assets/charts/mongo-express/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/mongo-express/Chart.lock b/utils/assets/charts/mongo-express/Chart.lock new file mode 100644 index 0000000..8416fb4 --- /dev/null +++ b/utils/assets/charts/mongo-express/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami/ + version: 2.19.1 +- name: mongodb + repository: https://charts.bitnami.com/bitnami/ + version: 15.1.5 +digest: sha256:f94e50f72a9f2bb6f026d89a570966c8c49e10cec562719d4c8b318e38b248ec +generated: "2024-04-28T01:57:09.199414152Z" diff --git a/utils/assets/charts/mongo-express/Chart.yaml b/utils/assets/charts/mongo-express/Chart.yaml new file mode 100644 index 0000000..9a14be0 --- /dev/null +++ b/utils/assets/charts/mongo-express/Chart.yaml @@ -0,0 +1,26 @@ +annotations: + artifacthub.io/signKey: | + fingerprint: 9E57D2479D48B84463EF491F66D280CE667AD6C8 + url: https://cowboysysop.github.io/charts/pgp-public-key-2022-02-19.asc + kubeVersion: '>=1.24' +apiVersion: v2 +appVersion: 1.0.2 +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami/ + version: 2.19.1 +- condition: mongodb.enabled + name: mongodb + repository: https://charts.bitnami.com/bitnami/ + version: 15.1.5 +description: Web-based MongoDB admin interface, written with Node.js and express +home: https://github.com/mongo-express/mongo-express +icon: https://raw.githubusercontent.com/mongo-express/mongo-express/master/public/images/mongo-express-logo.png +maintainers: +- email: sebastien.prudhomme@gmail.com + name: sebastien-prudhomme +name: mongo-express +sources: +- https://github.com/mongo-express/mongo-express +- https://github.com/cowboysysop/charts/tree/master/charts/mongo-express +version: 6.5.2 diff --git a/utils/assets/charts/mongo-express/LICENSE b/utils/assets/charts/mongo-express/LICENSE new file mode 100644 index 0000000..f953294 --- /dev/null +++ b/utils/assets/charts/mongo-express/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-present Sébastien Prud'homme + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/utils/assets/charts/mongo-express/README.md b/utils/assets/charts/mongo-express/README.md new file mode 100644 index 0000000..b947fb7 --- /dev/null +++ b/utils/assets/charts/mongo-express/README.md @@ -0,0 +1,229 @@ +# Mongo Express + +[Mongo Express](https://github.com/mongo-express/mongo-express) is a web-based MongoDB admin interface, written with Node.js and express. + +**DISCLAIMER**: This is an unofficial chart not supported by Mongo Express authors. + +## TL;DR; + +```bash +$ helm repo add cowboysysop https://cowboysysop.github.io/charts/ +$ helm install my-release cowboysysop/mongo-express +``` + +## Introduction + +This chart bootstraps a Mongo Express deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes >= 1.24 +- Helm >= 3.9 + +## Installing + +Install the chart using: + +```bash +$ helm repo add cowboysysop https://cowboysysop.github.io/charts/ +$ helm install my-release cowboysysop/mongo-express +``` + +These commands deploy Mongo Express on the Kubernetes cluster in the default configuration and with the release name `my-release`. The deployment configuration can be customized by specifying the customization parameters with the `helm install` command using the `--values` or `--set` arguments. Find more information in the [configuration section](#configuration) of this document. + +## Upgrading + +Upgrade the chart deployment using: + +```bash +$ helm upgrade my-release cowboysysop/mongo-express +``` + +The command upgrades the existing `my-release` deployment with the most latest release of the chart. + +**TIP**: Use `helm repo update` to update information on available charts in the chart repositories. + +### Upgrading to version 5.0.0 + +The chart is now tested with Kubernetes >= 1.24 and Helm >= 3.9. + +Future upgrades may introduce undetected breaking changes if you continue to use older versions. + +### Upgrading to version 4.0.0 + +Some parameters related to port management have been modified: + +- Parameter `service.port` has been renamed `service.ports.http`. +- Parameter `service.nodePort` has been renamed `service.nodePorts.http`. + +### Upgrading to version 3.0.0 + +Some parameters related to image management have been modified: + +- Registry prefix in `image.repository` parameters is now configured in `image.registry`. +- Parameter `imagePullSecrets` has been renamed `global.imagePullSecrets`. + +### Upgrading to version 2.0.0 + +The chart is no more compatible with Helm 2. + +Refer to the [Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/) for more information. + +## Uninstalling + +Uninstall the `my-release` deployment using: + +```bash +$ helm uninstall my-release +``` + +The command deletes the release named `my-release` and frees all the kubernetes resources associated with the release. + +**TIP**: Specify the `--purge` argument to the above command to remove the release from the store and make its name free for later use. + +## Configuration + +### Global parameters + +| Name | Description | Default | +| ------------------------- | ----------------------------------------------- | ------- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | + +### Common parameters + +| Name | Description | Default | +| ------------------- | -------------------------------------------------------------------------------------------------- | ------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | Partially override `mongo-express.fullname` template with a string (will prepend the release name) | `""` | +| `fullnameOverride` | Fully override `mongo-express.fullname` template with a string | `""` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | + +### Parameters + +| Name | Description | Default | +| ------------------------------------ | --------------------------------------------------------------------------------------------------------- | ------------------------ | +| `replicaCount` | Number of replicas | `1` | +| `image.registry` | Image registry | `docker.io` | +| `image.repository` | Image repository | `mongo-express` | +| `image.tag` | Image tag | `1.0.2` | +| `image.digest` | Image digest | `""` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `pdb.create` | Specifies whether a pod disruption budget should be created | `false` | +| `pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `1` | +| `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `nil` | +| `serviceAccount.create` | Specifies whether a service account should be created | `true` | +| `serviceAccount.annotations` | Service account annotations | `{}` | +| `serviceAccount.name` | The name of the service account to use (Generated using the `mongo-express.fullname` template if not set) | `nil` | +| `deploymentAnnotations` | Additional deployment annotations | `{}` | +| `podAnnotations` | Additional pod annotations | `{}` | +| `podLabels` | Additional pod labels | `{}` | +| `podSecurityContext` | Pod security context | `{}` | +| `priorityClassName` | Priority class name | `nil` | +| `runtimeClassName` | Runtime class name | `""` | +| `topologySpreadConstraints` | Topology Spread Constraints for pod assignment | `[]` | +| `securityContext` | Container security context | `{}` | +| `containerPorts.http` | Container port for HTTP | `8081` | +| `livenessProbe.enabled` | Enable liveness probe | `true` | +| `livenessProbe.initialDelaySeconds` | Delay before the liveness probe is initiated | `0` | +| `livenessProbe.periodSeconds` | How often to perform the liveness probe | `10` | +| `livenessProbe.timeoutSeconds` | When the liveness probe times out | `1` | +| `livenessProbe.failureThreshold` | Minimum consecutive failures for the liveness probe to be considered failed after having succeeded | `3` | +| `livenessProbe.successThreshold` | Minimum consecutive successes for the liveness probe to be considered successful after having failed | `1` | +| `readinessProbe.enabled` | Enable readiness probe | `true` | +| `readinessProbe.initialDelaySeconds` | Delay before the readiness probe is initiated | `0` | +| `readinessProbe.periodSeconds` | How often to perform the readiness probe | `10` | +| `readinessProbe.timeoutSeconds` | When the readiness probe times out | `1` | +| `readinessProbe.failureThreshold` | Minimum consecutive failures for the readiness probe to be considered failed after having succeeded | `3` | +| `readinessProbe.successThreshold` | Minimum consecutive successes for the readiness probe to be considered successful after having failed | `1` | +| `startupProbe.enabled` | Enable startup probe | `false` | +| `startupProbe.initialDelaySeconds` | Delay before the startup probe is initiated | `0` | +| `startupProbe.periodSeconds` | How often to perform the startup probe | `10` | +| `startupProbe.timeoutSeconds` | When the startup probe times out | `1` | +| `startupProbe.failureThreshold` | Minimum consecutive failures for the startup probe to be considered failed after having succeeded | `3` | +| `startupProbe.successThreshold` | Minimum consecutive successes for the startup probe to be considered successful after having failed | `1` | +| `service.annotations` | Service annotations | `{}` | +| `service.type` | Service type | `ClusterIP` | +| `service.clusterIP` | Static cluster IP address or None for headless service when service type is ClusterIP | `nil` | +| `service.loadBalancerIP` | Static load balancer IP address when service type is LoadBalancer | `nil` | +| `service.loadBalancerSourceRanges` | Source IP address ranges when service type is LoadBalancer | `nil` | +| `service.externalTrafficPolicy` | External traffic routing policy when service type is LoadBalancer or NodePort | `Cluster` | +| `service.ports.http` | Service port for HTTP | `8081` | +| `service.nodePorts.http` | Service node port for HTTP when service type is LoadBalancer or NodePort | `nil` | +| `ingress.enabled` | Enable ingress controller resource | `false` | +| `ingress.ingressClassName` | IngressClass that will be be used to implement the Ingress | `""` | +| `ingress.pathType` | Ingress path type | `ImplementationSpecific` | +| `ingress.annotations` | Ingress annotations | `{}` | +| `ingress.hosts[0].host` | Hostname to your Mongo Express installation | `mongo-express.local` | +| `ingress.hosts[0].paths` | Paths within the url structure | `["/"]` | +| `ingress.tls` | TLS configuration | `[]` | +| `resources` | CPU/Memory resource requests/limits | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Tolerations for pod assignment | `[]` | +| `affinity` | Map of node/pod affinities | `{}` | +| `extraArgs` | Additional container arguments | `{}` | +| `extraEnvVars` | Additional container environment variables | `[]` | +| `extraEnvVarsCM` | Name of existing ConfigMap containing additional container environment variables | `nil` | +| `extraEnvVarsSecret` | Name of existing Secret containing additional container environment variables | `nil` | + +### Config parameters + +| Name | Description | Default | +| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `mongodbServer` | MongoDB host name or IP address | `mongodb` | +| `mongodbPort` | MongoDB port | `27017` | +| `mongodbEnableAdmin` | Enable administrator access | `false` | +| `mongodbAdminUsername` | Administrator username | `root` | +| `mongodbAdminPassword` | Administrator password | `""` | +| `mongodbAuthUsername` | Database username (only needed if `mongodbEnableAdmin` is `false`) | `""` | +| `mongodbAuthPassword` | Database password (only needed if `mongodbEnableAdmin` is `false`) | `""` | +| `mongodbAuthDatabase` | Database name (only needed if `mongodbEnableAdmin` is `false`) | `""` | +| `siteBaseUrl` | Set the express baseUrl to ease mounting at a subdirectory | `/` | +| `siteCookieSecret` | String used by cookie-parser middleware to sign cookies (Random 32 character long alphanumeric string if not set) | `""` | +| `siteSessionSecret` | String used to sign the session ID cookie by express-session middleware (Random 32 character long alphanumeric string if not set) | `""` | +| `basicAuthUsername` | Mongo Express web login name | `""` | +| `basicAuthPassword` | Mongo Express web login password | `""` | +| `existingSecret` | Name of existing Secret to use | `""` | +| `existingSecretKeyMongodbAdminPassword` | Key in existing Secret that contains administrator password | `mongodb-admin-password` | +| `existingSecretKeyMongodbAuthPassword` | Key in existing Secret that contains database password | `mongodb-auth-password` | +| `existingSecretKeySiteCookieSecret` | Key in existing Secret that contains string used by cookie-parser middleware to sign cookies | `site-cookie-secret` | +| `existingSecretKeySiteSessionSecret` | Key in existing Secret that contains string used to sign the session ID cookie by express-session middleware | `site-session-secret` | +| `existingSecretKeyBasicAuthPassword` | Key in existing Secret that contains Mongo Express web login password | `basic-auth-password` | + +### MongoDB parameters + +| Name | Description | Default | +| ----------------- | ------------------------------------------------------------ | ------- | +| `mongodb.enabled` | Whether to use the MongoDB chart (for testing purposes only) | `false` | + +### Tests parameters + +| Name | Description | Default | +| ------------------------ | ----------------- | -------------------- | +| `tests.image.registry` | Image registry | `ghcr.io` | +| `tests.image.repository` | Image repository | `cowboysysop/pytest` | +| `tests.image.tag` | Image tag | `1.0.41` | +| `tests.image.digest` | Image digest | `""` | +| `tests.image.pullPolicy` | Image pull policy | `IfNotPresent` | + +## Setting parameters + +Specify the parameters you which to customize using the `--set` argument to the `helm install` command. For instance, + +```bash +$ helm install my-release \ + --set nameOverride=my-name cowboysysop/mongo-express +``` + +The above command sets the `nameOverride` to `my-name`. + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```bash +$ helm install my-release \ + --values values.yaml cowboysysop/mongo-express +``` + +**TIP**: You can use the default [values.yaml](values.yaml). diff --git a/utils/assets/charts/mongo-express/charts/common/.helmignore b/utils/assets/charts/mongo-express/charts/common/.helmignore new file mode 100644 index 0000000..7c7c21d --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# img folder +img/ diff --git a/utils/assets/charts/mongo-express/charts/common/Chart.yaml b/utils/assets/charts/mongo-express/charts/common/Chart.yaml new file mode 100644 index 0000000..8d0e546 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.19.1 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts +type: library +version: 2.19.1 diff --git a/utils/assets/charts/mongo-express/charts/common/README.md b/utils/assets/charts/mongo-express/charts/common/README.md new file mode 100644 index 0000000..0d01a1e --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_affinities.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..e85b1df --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_affinities.tpl @@ -0,0 +1,139 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_capabilities.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..115674a --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_capabilities.tpl @@ -0,0 +1,229 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- if .Values.global }} + {{- if .Values.global.kubeVersion }} + {{- .Values.global.kubeVersion -}} + {{- else }} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} + {{- end -}} +{{- else }} +{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- if semverCompare "<1.7-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if .Values.ingress -}} +{{- if .Values.ingress.apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- if semverCompare "<1.10-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- if semverCompare ">=1.23-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_compatibility.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..17665d5 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_compatibility.tpl @@ -0,0 +1,39 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} +{{- if .context.Values.global.compatibility -}} + {{- if .context.Values.global.compatibility.openshift -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_errors.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..07ded6f --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_errors.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_images.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_images.tpl new file mode 100644 index 0000000..1bcb779 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_images.tpl @@ -0,0 +1,117 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := .imageRoot.registry -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = .global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- if .global }} + {{- range .global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- if $context.Values.global }} + {{- range $context.Values.global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_ingress.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..efa5b85 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_labels.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..d90a6cd --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_names.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_names.tpl new file mode 100644 index 0000000..a222924 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_resources.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..030fa1a --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "1024Mi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "1024Mi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "1024Mi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "1024Mi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "1024Mi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.5" "memory" "4096Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "1024Mi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.5" "memory" "4096Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "1024Mi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_secrets.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..84dbe38 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_secrets.tpl @@ -0,0 +1,182 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- else if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} + {{- end -}} +{{- else if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} +{{- else }} + + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_storage.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..16405a0 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_storage.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} + +{{- $storageClass := .persistence.storageClass -}} +{{- if .global -}} + {{- if .global.storageClass -}} + {{- $storageClass = .global.storageClass -}} + {{- end -}} +{{- end -}} + +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} + +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_tplvalues.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a8ed763 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,38 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_utils.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..bfbddf0 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/_warnings.tpl b/utils/assets/charts/mongo-express/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..0f763cd --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/_warnings.tpl @@ -0,0 +1,82 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/tutorials/understand-rolling-tags-containers +{{- end }} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/validations/_cassandra.tpl b/utils/assets/charts/mongo-express/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..eda9aad --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Cassandra required passwords are not empty. + +Usage: +{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret" + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.cassandra.passwords" -}} + {{- $existingSecret := include "common.cassandra.values.existingSecret" . -}} + {{- $enabled := include "common.cassandra.values.enabled" . -}} + {{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}} + {{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/validations/_mariadb.tpl b/utils/assets/charts/mongo-express/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..17d83a2 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/validations/_mongodb.tpl b/utils/assets/charts/mongo-express/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..bbb445b --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,113 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MongoDB® required passwords are not empty. + +Usage: +{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MongoDB® values are stored, e.g: "mongodb-passwords-secret" + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mongodb.passwords" -}} + {{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mongodb.values.enabled" . -}} + {{- $authPrefix := include "common.mongodb.values.key.auth" . -}} + {{- $architecture := include "common.mongodb.values.architecture" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyDatabase := printf "%s.database" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}} + {{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}} + + {{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }} + {{- if and $valueUsername $valueDatabase -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replicaset") -}} + {{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/validations/_mysql.tpl b/utils/assets/charts/mongo-express/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..ca3953f --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MySQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mysql.passwords" -}} + {{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mysql.values.enabled" . -}} + {{- $architecture := include "common.mysql.values.architecture" . -}} + {{- $authPrefix := include "common.mysql.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/validations/_postgresql.tpl b/utils/assets/charts/mongo-express/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..8c9aa57 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,134 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate PostgreSQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/validations/_redis.tpl b/utils/assets/charts/mongo-express/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..fc0d208 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,81 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Redis® required passwords are not empty. + +Usage: +{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret" + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.redis.passwords" -}} + {{- $enabled := include "common.redis.values.enabled" . -}} + {{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}} + {{- $standarizedVersion := include "common.redis.values.standarized.version" . }} + + {{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }} + {{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }} + + {{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }} + {{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}} + {{- if eq $useAuth "true" -}} + {{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/templates/validations/_validations.tpl b/utils/assets/charts/mongo-express/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..31ceda8 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/common/values.yaml b/utils/assets/charts/mongo-express/charts/common/values.yaml new file mode 100644 index 0000000..9abe0e1 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/utils/assets/charts/mongo-express/charts/mongodb/.helmignore b/utils/assets/charts/mongo-express/charts/mongodb/.helmignore new file mode 100644 index 0000000..fb56657 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +# img folder +img/ diff --git a/utils/assets/charts/mongo-express/charts/mongodb/Chart.lock b/utils/assets/charts/mongo-express/charts/mongodb/Chart.lock new file mode 100644 index 0000000..f71335b --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + version: 2.19.1 +digest: sha256:c883732817d9aaa3304f7b3109262aa338959de15b432dc5a2dbde13d2e136a5 +generated: "2024-04-04T18:44:10.549119256Z" diff --git a/utils/assets/charts/mongo-express/charts/mongodb/Chart.yaml b/utils/assets/charts/mongo-express/charts/mongodb/Chart.yaml new file mode 100644 index 0000000..3e31042 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/Chart.yaml @@ -0,0 +1,41 @@ +annotations: + category: Database + images: | + - name: kubectl + image: docker.io/bitnami/kubectl:1.29.3-debian-12-r3 + - name: mongodb + image: docker.io/bitnami/mongodb:7.0.8-debian-12-r2 + - name: mongodb-exporter + image: docker.io/bitnami/mongodb-exporter:0.40.0-debian-12-r15 + - name: nginx + image: docker.io/bitnami/nginx:1.25.4-debian-12-r7 + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r18 + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 7.0.8 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x +description: MongoDB(R) is a relational open source NoSQL database. Easy to use, it + stores data in JSON-like documents. Automated scalability and high-performance. + Ideal for developing cloud native applications. +home: https://bitnami.com +icon: https://bitnami.com/assets/stacks/mongodb/img/mongodb-stack-220x234.png +keywords: +- mongodb +- database +- nosql +- cluster +- replicaset +- replication +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: mongodb +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/mongodb +version: 15.1.5 diff --git a/utils/assets/charts/mongo-express/charts/mongodb/README.md b/utils/assets/charts/mongo-express/charts/mongodb/README.md new file mode 100644 index 0000000..c2be64e --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/README.md @@ -0,0 +1,1123 @@ + + +# MongoDB(R) packaged by Bitnami + +MongoDB(R) is a relational open source NoSQL database. Easy to use, it stores data in JSON-like documents. Automated scalability and high-performance. Ideal for developing cloud native applications. + +[Overview of MongoDB®](http://www.mongodb.org) + +Disclaimer: The respective trademarks mentioned in the offering are owned by the respective companies. We do not provide a commercial license for any of these products. This listing has an open-source license. MongoDB(R) is run and maintained by MongoDB, which is a completely separate project from Bitnami. + +## TL;DR + +```console +helm install my-release oci://registry-1.docker.io/bitnamicharts/mongodb +``` + +Looking to use MongoDBreg; in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart bootstraps a [MongoDB(®)](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Architecture + +This chart allows installing MongoDB(®) using two different architecture setups: `standalone` or `replicaset`. Use the `architecture` parameter to choose the one to use: + +```console +architecture="standalone" +architecture="replicaset" +``` + +### Standalone architecture + +The *standalone* architecture installs a deployment (or StatefulSet) with one MongoDB® server (it cannot be scaled): + +```text + ---------------- + | MongoDB® | + | svc | + ---------------- + | + v + ------------ + |MongoDB®| + | Server | + | Pod | + ----------- +``` + +### Replicaset architecture + +The chart also supports the *replicaset* architecture with and without a MongoDB(®) Arbiter: + +When the MongoDB(®) Arbiter is enabled, the chart installs two StatefulSets: A StatefulSet with N MongoDB(®) servers (organised with one primary and N-1 secondary nodes), and a StatefulSet with one MongoDB(®) arbiter node (it cannot be scaled). + +```text + ---------------- ---------------- ---------------- ------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | | Arbiter | + | external svc | | external svc | | external svc | | svc | + ---------------- ---------------- ---------------- ------------- + | | | | + v v v v + ---------------- ---------------- ---------------- -------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | | MongoDB® | + | Server | | Server | | Server | | Arbiter | + | Pod | | Pod | | Pod | | Pod | + ---------------- ---------------- ---------------- -------------- + primary secondary secondary +``` + +The PSA model is useful when the third Availability Zone cannot hold a full MongoDB(®) instance. The MongoDB(®) Arbiter as decision maker is lightweight and can run alongside other workloads. + +> NOTE: An update takes your MongoDB(®) replicaset offline if the Arbiter is enabled and the number of MongoDB(®) replicas is two. Helm applies updates to the StatefulSets for the MongoDB(®) instance and the Arbiter at the same time so you lose two out of three quorum votes. + +Without the Arbiter, the chart deploys a single statefulset with N MongoDB(®) servers (organised with one primary and N-1 secondary nodes). + +```text + ---------------- ---------------- ---------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | + | external svc | | external svc | | external svc | + ---------------- ---------------- ---------------- + | | | + v v v + ---------------- ---------------- ---------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | + | Server | | Server | | Server | + | Pod | | Pod | | Pod | + ---------------- ---------------- ---------------- + primary secondary secondary +``` + +There are no services load balancing requests between MongoDB(®) nodes; instead, each node has an associated service to access them individually. + +> NOTE: Although the first replica is initially assigned the primary role, any of the secondary nodes can become the primary if it is down, or during upgrades. Do not make any assumption about what replica has the primary role. Instead, configure your MongoDB(®) client with the list of MongoDB(®) hostnames so it can dynamically choose the node to send requests. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- PV provisioner support in the underlying infrastructure + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys MongoDB(®) on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcePreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### [Rolling vs Immutable tags](https://docs.bitnami.com/tutorials/understand-rolling-tags-containers) + +It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. + +Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. + +### Customize a new MongoDB instance + +The [Bitnami MongoDB(®) image](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) supports the use of custom scripts to initialize a fresh instance. In order to execute the scripts, two options are available: + +- Specify them using the `initdbScripts` parameter as dict. +- Define an external Kubernetes ConfigMap with all the initialization scripts by setting the `initdbScriptsConfigMap` parameter. Note that this will override the previous option. + +The allowed script extensions are `.sh` and `.js`. + +### Replicaset: Access MongoDB(®) nodes from outside the cluster + +In order to access MongoDB(®) nodes from outside the cluster when using a replicaset architecture, a specific service per MongoDB(®) pod will be created. There are two ways of configuring external access: + +- Using LoadBalancer services +- Using NodePort services. + +#### Use LoadBalancer services + +Two alternatives are available to use *LoadBalancer* services: + +- Use random load balancer IP addresses using an *initContainer* that waits for the IP addresses to be ready and discovers them automatically. An example deployment configuration is shown below: + + ```text + architecture=replicaset + replicaCount=2 + externalAccess.enabled=true + externalAccess.service.type=LoadBalancer + externalAccess.service.port=27017 + externalAccess.autoDiscovery.enabled=true + serviceAccount.create=true + rbac.create=true + ``` + + > NOTE: This option requires creating RBAC rules on clusters where RBAC policies are enabled. + +- Manually specify the load balancer IP addresses. An example deployment configuration is shown below, with the placeholder EXTERNAL-IP-ADDRESS-X used in place of the load balancer IP addresses: + + ```text + architecture=replicaset + replicaCount=2 + externalAccess.enabled=true + externalAccess.service.type=LoadBalancer + externalAccess.service.port=27017 + externalAccess.service.loadBalancerIPs[0]='EXTERNAL-IP-ADDRESS-1' + externalAccess.service.loadBalancerIPs[1]='EXTERNAL-IP-ADDRESS-2' + ``` + + > NOTE: This option requires knowing the load balancer IP addresses, so that each MongoDB® node's advertised hostname is configured with it. + +#### Use NodePort services + +Manually specify the node ports to use. An example deployment configuration is shown below, with the placeholder NODE-PORT-X used in place of the node ports: + +```text +architecture=replicaset +replicaCount=2 +externalAccess.enabled=true +externalAccess.service.type=NodePort +externalAccess.service.nodePorts[0]='NODE-PORT-1' +externalAccess.service.nodePorts[1]='NODE-PORT-2' +``` + +> NOTE: This option requires knowing the node ports that will be exposed, so each MongoDB® node's advertised hostname is configured with it. + +The pod will try to get the external IP address of the node using the command `curl -s https://ipinfo.io/IP-ADDRESS` unless the `externalAccess.service.domain` parameter is set. + +### Bootstrapping with an External Cluster + +This chart is equipped with the ability to bring online a set of Pods that connect to an existing MongoDB(®) deployment that lies outside of Kubernetes. This effectively creates a hybrid MongoDB(®) Deployment where both Pods in Kubernetes and Instances such as Virtual Machines can partake in a single MongoDB(®) Deployment. This is helpful in situations where one may be migrating MongoDB(®) from Virtual Machines into Kubernetes, for example. To take advantage of this, use the following as an example configuration: + +```yaml +externalAccess: + externalMaster: + enabled: true + host: external-mongodb-0.internal +``` + +:warning: To bootstrap MongoDB(®) with an external master that lies outside of Kubernetes, be sure to set up external access using any of the suggested methods in this chart to have connectivity between the MongoDB(®) members. :warning: + +### Add extra environment variables + +To add extra environment variables (useful for advanced operations like custom init scripts), use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: LOG_LEVEL + value: error +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` properties. + +### Use Sidecars and Init Containers + +If additional containers are needed in the same pod (such as additional metrics or logging exporters), they can be defined using the `sidecars` config parameter. + +```yaml +sidecars: +- name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +If these sidecars export extra ports, extra port definitions can be added using the `service.extraPorts` parameter (where available), as shown in the example below: + +```yaml +service: + extraPorts: + - name: extraPort + port: 11311 + targetPort: 11311 +``` + +> NOTE: This Helm chart already includes sidecar containers for the Prometheus exporters (where applicable). These can be activated by adding the `--enable-metrics=true` parameter at deployment time. The `sidecars` parameter should therefore only be used for any extra sidecar containers. + +If additional init containers are needed in the same pod, they can be defined using the `initContainers` parameter. Here is an example: + +```yaml +initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Learn more about [sidecar containers](https://kubernetes.io/docs/concepts/workloads/pods/) and [init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +### Backup and restore MongoDB(R) deployments + +Two different approaches are available to back up and restore Bitnami MongoDB® Helm chart deployments on Kubernetes: + +- Back up the data from the source deployment and restore it in a new deployment using MongoDB® built-in backup/restore tools. +- Back up the persistent volumes from the source deployment and attach them to a new deployment using Velero, a Kubernetes backup/restore tool. + +#### Method 1: Backup and restore data using MongoDB® built-in tools + +This method involves the following steps: + +- Use the *mongodump* tool to create a snapshot of the data in the source cluster. +- Create a new MongoDB® Cluster deployment and forward the MongoDB® Cluster service port for the new deployment. +- Restore the data using the *mongorestore* tool to import the backup to the new cluster. + +> NOTE: Under this approach, it is important to create the new deployment on the destination cluster using the same credentials as the original deployment on the source cluster. + +#### Method 2: Back up and restore persistent data volumes + +This method involves copying the persistent data volumes for the MongoDB® nodes and reusing them in a new deployment with [Velero](https://velero.io/), an open source Kubernetes backup/restore tool. This method is only suitable when: + +- The Kubernetes provider is [supported by Velero](https://velero.io/docs/latest/supported-providers/). +- Both clusters are on the same Kubernetes provider, as this is a requirement of [Velero's native support for migrating persistent volumes](https://velero.io/docs/latest/migration-case/). +- The restored deployment on the destination cluster will have the same name, namespace, topology and credentials as the original deployment on the source cluster. + +This method involves the following steps: + +- Install Velero on the source and destination clusters. +- Use Velero to back up the PersistentVolumes (PVs) used by the deployment on the source cluster. +- Use Velero to restore the backed-up PVs on the destination cluster. +- Create a new deployment on the destination cluster with the same chart, deployment name, credentials and other parameters as the original. This new deployment will use the restored PVs and hence the original data. + +Refer to our detailed [tutorial on backing up and restoring MongoDB® chart deployments on Kubernetes](https://docs.bitnami.com/tutorials/backup-restore-data-mongodb-kubernetes/), which covers both these approaches, for more information. + +### Use custom Prometheus rules + +Custom Prometheus rules can be defined for the Prometheus Operator by using the `prometheusRule` parameter. A basic configuration example is shown below: + +```text + metrics: + enabled: true + prometheusRule: + enabled: true + rules: + - name: rule1 + rules: + - alert: HighRequestLatency + expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 + for: 10m + labels: + severity: page + annotations: + summary: High request latency +``` + +### Enable SSL/TLS + +This chart supports enabling SSL/TLS between nodes in the cluster, as well as between MongoDB(®) clients and nodes, by setting the `MONGODB_EXTRA_FLAGS` and `MONGODB_CLIENT_EXTRA_FLAGS` container environment variables, together with the correct `MONGODB_ADVERTISED_HOSTNAME`. To enable full TLS encryption, set the `tls.enabled` parameter to `true`. + +#### Generate the self-signed certificates via pre-install Helm hooks + +The `secrets-ca.yaml` file utilizes the Helm "pre-install" hook to ensure that the certificates will only be generated on chart install. + +The `genCA()` function will create a new self-signed x509 certificate authority. The `genSignedCert()` function creates an object with the certificate and key, which are base64-encoded and used in a YAML-like object. The `genSignedCert()` function is passed the CN, an empty IP list (the nil part), the validity and the CA created previously. + +A Kubernetes Secret is used to hold the signed certificate created above, and the `initContainer` sets up the rest. Using Helm's hook annotations ensures that the certificates will only be generated on chart install. This will prevent overriding the certificates if the chart is upgraded. + +#### Use your own CA + +To use your own CA, set `tls.caCert` and `tls.caKey` with appropriate base64 encoded data. The `secrets-ca.yaml` file will utilize this data to create the Secret. + +> NOTE: Currently, only RSA private keys are supported. + +#### Access the cluster + +To access the cluster, enable the init container which generates the MongoDB(®) server/client PEM key needed to access the cluster. Please be sure to include the `$my_hostname` section with your actual hostname, and the alternative hostnames section should contain the hostnames that should be allowed access to the MongoDB(®) replicaset. Additionally, if external access is enabled, the load balancer IP addresses are added to the alternative names list. + +> NOTE: You will be generating self-signed certificates for the MongoDB(®) deployment. The init container generates a new MongoDB(®) private key which will be used to create a Certificate Authority (CA) and the public certificate for the CA. The Certificate Signing Request will be created as well and signed using the private key of the CA previously created. Finally, the PEM bundle will be created using the private key and public certificate. This process will be repeated for each node in the cluster. + +#### Start the cluster + +After the certificates have been generated and made available to the containers at the correct mount points, the MongoDB(®) server will be started with TLS enabled. The options for the TLS mode will be one of `disabled`, `allowTLS`, `preferTLS`, or `requireTLS`. This value can be changed via the `MONGODB_EXTRA_FLAGS` field using the `tlsMode` parameter. The client should now be able to connect to the TLS-enabled cluster with the provided certificates. + +### Set Pod affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Persistence + +The [Bitnami MongoDB(®)](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) image stores the MongoDB(®) data and configurations at the `/bitnami/mongodb` path of the container. + +The chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at this location. The volume is created using dynamic volume provisioning. + +If you encounter errors when working with persistent volumes, refer to our [troubleshooting guide for persistent volumes](https://docs.bitnami.com/kubernetes/faq/troubleshooting/troubleshooting-persistence-volumes/). + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | +| `global.namespaceOverride` | Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride | `""` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- | +| `nameOverride` | String to partially override mongodb.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override mongodb.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `commonLabels` | Add labels to all the deployed resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `commonAnnotations` | Common annotations to add to all Mongo resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `topologyKey` | Override common lib default topology key. If empty - "kubernetes.io/hostname" is used | `""` | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### MongoDB(®) parameters + +| Name | Description | Value | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| `image.registry` | MongoDB(®) image registry | `REGISTRY_NAME` | +| `image.repository` | MongoDB(®) image registry | `REPOSITORY_NAME/mongodb` | +| `image.digest` | MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | MongoDB(®) image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Set to true if you would like to see extra information on logs | `false` | +| `schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `architecture` | MongoDB(®) architecture (`standalone` or `replicaset`) | `standalone` | +| `useStatefulSet` | Set to true to use a StatefulSet instead of a Deployment (only when `architecture=standalone`) | `false` | +| `auth.enabled` | Enable authentication | `true` | +| `auth.rootUser` | MongoDB(®) root user | `root` | +| `auth.rootPassword` | MongoDB(®) root password | `""` | +| `auth.usernames` | List of custom users to be created during the initialization | `[]` | +| `auth.passwords` | List of passwords for the custom users set at `auth.usernames` | `[]` | +| `auth.databases` | List of custom databases to be created during the initialization | `[]` | +| `auth.username` | DEPRECATED: use `auth.usernames` instead | `""` | +| `auth.password` | DEPRECATED: use `auth.passwords` instead | `""` | +| `auth.database` | DEPRECATED: use `auth.databases` instead | `""` | +| `auth.replicaSetKey` | Key used for authentication in the replicaset (only when `architecture=replicaset`) | `""` | +| `auth.existingSecret` | Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) | `""` | +| `tls.enabled` | Enable MongoDB(®) TLS support between nodes in the cluster as well as between mongo clients and nodes | `false` | +| `tls.mTLS.enabled` | IF TLS support is enabled, require clients to provide certificates | `true` | +| `tls.autoGenerated` | Generate a custom CA and self-signed certificates | `true` | +| `tls.existingSecret` | Existing secret with TLS certificates (keys: `mongodb-ca-cert`, `mongodb-ca-key`) | `""` | +| `tls.caCert` | Custom CA certificated (base64 encoded) | `""` | +| `tls.caKey` | CA certificate private key (base64 encoded) | `""` | +| `tls.pemChainIncluded` | Flag to denote that the Certificate Authority (CA) certificates are bundled with the endpoint cert. | `false` | +| `tls.standalone.existingSecret` | Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `""` | +| `tls.replicaset.existingSecrets` | Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `[]` | +| `tls.hidden.existingSecrets` | Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `[]` | +| `tls.arbiter.existingSecret` | Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `""` | +| `tls.image.registry` | Init container TLS certs setup image registry | `REGISTRY_NAME` | +| `tls.image.repository` | Init container TLS certs setup image repository | `REPOSITORY_NAME/nginx` | +| `tls.image.digest` | Init container TLS certs setup image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `tls.image.pullPolicy` | Init container TLS certs setup image pull policy | `IfNotPresent` | +| `tls.image.pullSecrets` | Init container TLS certs specify docker-registry secret names as an array | `[]` | +| `tls.extraDnsNames` | Add extra dns names to the CA, can solve x509 auth issue for pod clients | `[]` | +| `tls.mode` | Allows to set the tls mode which should be used when tls is enabled (options: `allowTLS`, `preferTLS`, `requireTLS`) | `requireTLS` | +| `tls.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). | `nano` | +| `tls.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `tls.securityContext` | Init container generate-tls-cert Security context | `{}` | +| `automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `hostAliases` | Add deployment host aliases | `[]` | +| `replicaSetName` | Name of the replica set (only when `architecture=replicaset`) | `rs0` | +| `replicaSetHostnames` | Enable DNS hostnames in the replicaset config (only when `architecture=replicaset`) | `true` | +| `enableIPv6` | Switch to enable/disable IPv6 on MongoDB(®) | `false` | +| `directoryPerDB` | Switch to enable/disable DirectoryPerDB on MongoDB(®) | `false` | +| `systemLogVerbosity` | MongoDB(®) system log verbosity level | `0` | +| `disableSystemLog` | Switch to enable/disable MongoDB(®) system log | `false` | +| `disableJavascript` | Switch to enable/disable MongoDB(®) server-side JavaScript execution | `false` | +| `enableJournal` | Switch to enable/disable MongoDB(®) Journaling | `true` | +| `configuration` | MongoDB(®) configuration file to be used for Primary and Secondary nodes | `""` | + +### replicaSetConfigurationSettings settings applied during runtime (not via configuration file) + +| Name | Description | Value | +| ----------------------------------------------- | --------------------------------------------------------------------------------------------------- | ------- | +| `replicaSetConfigurationSettings.enabled` | Enable MongoDB(®) Switch to enable/disable configuring MongoDB(®) run time rs.conf settings | `false` | +| `replicaSetConfigurationSettings.configuration` | run-time rs.conf settings | `{}` | +| `existingConfigmap` | Name of existing ConfigMap with MongoDB(®) configuration for Primary and Secondary nodes | `""` | +| `initdbScripts` | Dictionary of initdb scripts | `{}` | +| `initdbScriptsConfigMap` | Existing ConfigMap with custom initdb scripts | `""` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `args` | Override default container args (useful when using custom images) | `[]` | +| `extraFlags` | MongoDB(®) additional command line flags | `[]` | +| `extraEnvVars` | Extra environment variables to add to MongoDB(®) pods | `[]` | +| `extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | + +### MongoDB(®) statefulset parameters + +| Name | Description | Value | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `annotations` | Additional labels to be added to the MongoDB(®) statefulset. Evaluated as a template | `{}` | +| `labels` | Annotations to be added to the MongoDB(®) statefulset. Evaluated as a template | `{}` | +| `replicaCount` | Number of MongoDB(®) nodes | `2` | +| `updateStrategy.type` | Strategy to use to replace existing MongoDB(®) pods. When architecture=standalone and useStatefulSet=false, | `RollingUpdate` | +| `podManagementPolicy` | Pod management policy for MongoDB(®) | `OrderedReady` | +| `podAffinityPreset` | MongoDB(®) Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | MongoDB(®) Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | MongoDB(®) Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | MongoDB(®) Node label key to match Ignored if `affinity` is set. | `""` | +| `nodeAffinityPreset.values` | MongoDB(®) Node label values to match. Ignored if `affinity` is set. | `[]` | +| `affinity` | MongoDB(®) Affinity for pod assignment | `{}` | +| `nodeSelector` | MongoDB(®) Node labels for pod assignment | `{}` | +| `tolerations` | MongoDB(®) Tolerations for pod assignment | `[]` | +| `topologySpreadConstraints` | MongoDB(®) Spread Constraints for Pods | `[]` | +| `lifecycleHooks` | LifecycleHook for the MongoDB(®) container(s) to automate configuration before or after startup | `{}` | +| `terminationGracePeriodSeconds` | MongoDB(®) Termination Grace Period | `""` | +| `podLabels` | MongoDB(®) pod labels | `{}` | +| `podAnnotations` | MongoDB(®) Pod annotations | `{}` | +| `priorityClassName` | Name of the existing priority class to be used by MongoDB(®) pod(s) | `""` | +| `runtimeClassName` | Name of the runtime class to be used by MongoDB(®) pod(s) | `""` | +| `podSecurityContext.enabled` | Enable MongoDB(®) pod(s)' Security Context | `true` | +| `podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `podSecurityContext.fsGroup` | Group ID for the volumes of the MongoDB(®) pod(s) | `1001` | +| `podSecurityContext.sysctls` | sysctl settings of the MongoDB(®) pod(s)' | `[]` | +| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` | +| `resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `containerPorts.mongodb` | MongoDB(®) container port | `27017` | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `20` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `10` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `customLivenessProbe` | Override default liveness probe for MongoDB(®) containers | `{}` | +| `customReadinessProbe` | Override default readiness probe for MongoDB(®) containers | `{}` | +| `customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `initContainers` | Add additional init containers for the hidden node pod(s) | `[]` | +| `sidecars` | Add additional sidecar containers for the MongoDB(®) pod(s) | `[]` | +| `extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the MongoDB(®) container(s) | `[]` | +| `extraVolumes` | Optionally specify extra list of additional volumes to the MongoDB(®) statefulset | `[]` | +| `pdb.create` | Enable/disable a Pod Disruption Budget creation for MongoDB(®) pod(s) | `false` | +| `pdb.minAvailable` | Minimum number/percentage of MongoDB(®) pods that must still be available after the eviction | `1` | +| `pdb.maxUnavailable` | Maximum number/percentage of MongoDB(®) pods that may be made unavailable after the eviction | `""` | + +### Traffic exposure parameters + +| Name | Description | Value | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| `service.nameOverride` | MongoDB(®) service name | `""` | +| `service.type` | Kubernetes Service type (only for standalone architecture) | `ClusterIP` | +| `service.portName` | MongoDB(®) service port name (only for standalone architecture) | `mongodb` | +| `service.ports.mongodb` | MongoDB(®) service port. | `27017` | +| `service.nodePorts.mongodb` | Port to bind to for NodePort and LoadBalancer service types (only for standalone architecture) | `""` | +| `service.clusterIP` | MongoDB(®) service cluster IP (only for standalone architecture) | `""` | +| `service.externalIPs` | Specify the externalIP value ClusterIP service type (only for standalone architecture) | `[]` | +| `service.loadBalancerIP` | loadBalancerIP for MongoDB(®) Service (only for standalone architecture) | `""` | +| `service.loadBalancerClass` | loadBalancerClass for MongoDB(®) Service (only for standalone architecture) | `""` | +| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer (only for standalone architecture) | `[]` | +| `service.allocateLoadBalancerNodePorts` | Wheter to allocate node ports when service type is LoadBalancer | `true` | +| `service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `service.annotations` | Provide any additional annotations that may be required | `{}` | +| `service.externalTrafficPolicy` | service external traffic policy (only for standalone architecture) | `Local` | +| `service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `service.headless.annotations` | Annotations for the headless service. | `{}` | +| `externalAccess.enabled` | Enable Kubernetes external cluster access to MongoDB(®) nodes (only for replicaset architecture) | `false` | +| `externalAccess.autoDiscovery.enabled` | Enable using an init container to auto-detect external IPs by querying the K8s API | `false` | +| `externalAccess.autoDiscovery.image.registry` | Init container auto-discovery image registry | `REGISTRY_NAME` | +| `externalAccess.autoDiscovery.image.repository` | Init container auto-discovery image repository | `REPOSITORY_NAME/kubectl` | +| `externalAccess.autoDiscovery.image.digest` | Init container auto-discovery image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `externalAccess.autoDiscovery.image.pullPolicy` | Init container auto-discovery image pull policy | `IfNotPresent` | +| `externalAccess.autoDiscovery.image.pullSecrets` | Init container auto-discovery image pull secrets | `[]` | +| `externalAccess.autoDiscovery.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). | `nano` | +| `externalAccess.autoDiscovery.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `externalAccess.externalMaster.enabled` | Use external master for bootstrapping | `false` | +| `externalAccess.externalMaster.host` | External master host to bootstrap from | `""` | +| `externalAccess.externalMaster.port` | Port for MongoDB(®) service external master host | `27017` | +| `externalAccess.service.type` | Kubernetes Service type for external access. Allowed values: NodePort, LoadBalancer or ClusterIP | `LoadBalancer` | +| `externalAccess.service.portName` | MongoDB(®) port name used for external access when service type is LoadBalancer | `mongodb` | +| `externalAccess.service.ports.mongodb` | MongoDB(®) port used for external access when service type is LoadBalancer | `27017` | +| `externalAccess.service.loadBalancerIPs` | Array of load balancer IPs for MongoDB(®) nodes | `[]` | +| `externalAccess.service.loadBalancerClass` | loadBalancerClass when service type is LoadBalancer | `""` | +| `externalAccess.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | +| `externalAccess.service.allocateLoadBalancerNodePorts` | Wheter to allocate node ports when service type is LoadBalancer | `true` | +| `externalAccess.service.externalTrafficPolicy` | MongoDB(®) service external traffic policy | `Local` | +| `externalAccess.service.nodePorts` | Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort | `[]` | +| `externalAccess.service.domain` | Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort | `""` | +| `externalAccess.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `externalAccess.service.annotations` | Service annotations for external access | `{}` | +| `externalAccess.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `externalAccess.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `externalAccess.hidden.enabled` | Enable Kubernetes external cluster access to MongoDB(®) hidden nodes | `false` | +| `externalAccess.hidden.service.type` | Kubernetes Service type for external access. Allowed values: NodePort or LoadBalancer | `LoadBalancer` | +| `externalAccess.hidden.service.portName` | MongoDB(®) port name used for external access when service type is LoadBalancer | `mongodb` | +| `externalAccess.hidden.service.ports.mongodb` | MongoDB(®) port used for external access when service type is LoadBalancer | `27017` | +| `externalAccess.hidden.service.loadBalancerIPs` | Array of load balancer IPs for MongoDB(®) nodes | `[]` | +| `externalAccess.hidden.service.loadBalancerClass` | loadBalancerClass when service type is LoadBalancer | `""` | +| `externalAccess.hidden.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | +| `externalAccess.hidden.service.allocateLoadBalancerNodePorts` | Wheter to allocate node ports when service type is LoadBalancer | `true` | +| `externalAccess.hidden.service.externalTrafficPolicy` | MongoDB(®) service external traffic policy | `Local` | +| `externalAccess.hidden.service.nodePorts` | Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort. Length must be the same as replicaCount | `[]` | +| `externalAccess.hidden.service.domain` | Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort | `""` | +| `externalAccess.hidden.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `externalAccess.hidden.service.annotations` | Service annotations for external access | `{}` | +| `externalAccess.hidden.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `externalAccess.hidden.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | + +### Network policy parameters + +| Name | Description | Value | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolice | `[]` | +| `networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces | `{}` | +| `persistence.enabled` | Enable MongoDB(®) data persistence using PVC | `true` | +| `persistence.name` | Name of the PVC and mounted volume | `datadir` | +| `persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `persistence.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `persistence.storageClass` | PVC Storage Class for MongoDB(®) data volume | `""` | +| `persistence.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `persistence.size` | PVC Storage Request for MongoDB(®) data volume | `8Gi` | +| `persistence.annotations` | PVC annotations | `{}` | +| `persistence.mountPath` | Path to mount the volume at | `/bitnami/mongodb` | +| `persistence.subPath` | Subdirectory of the volume to mount at | `""` | +| `persistence.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | +| `persistence.volumeClaimTemplates.requests` | Custom PVC requests attributes | `{}` | +| `persistence.volumeClaimTemplates.dataSource` | Add dataSource to the VolumeClaimTemplate | `{}` | +| `persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for MongoDB(®) Statefulset | `false` | +| `persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### Backup parameters + +| Name | Description | Value | +| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `backup.enabled` | Enable the logical dump of the database "regularly" | `false` | +| `backup.cronjob.schedule` | Set the cronjob parameter schedule | `@daily` | +| `backup.cronjob.concurrencyPolicy` | Set the cronjob parameter concurrencyPolicy | `Allow` | +| `backup.cronjob.failedJobsHistoryLimit` | Set the cronjob parameter failedJobsHistoryLimit | `1` | +| `backup.cronjob.successfulJobsHistoryLimit` | Set the cronjob parameter successfulJobsHistoryLimit | `3` | +| `backup.cronjob.startingDeadlineSeconds` | Set the cronjob parameter startingDeadlineSeconds | `""` | +| `backup.cronjob.ttlSecondsAfterFinished` | Set the cronjob parameter ttlSecondsAfterFinished | `""` | +| `backup.cronjob.restartPolicy` | Set the cronjob parameter restartPolicy | `OnFailure` | +| `backup.cronjob.backoffLimit` | Set the cronjob parameter backoffLimit | `6` | +| `backup.cronjob.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `backup.cronjob.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `backup.cronjob.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `backup.cronjob.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `backup.cronjob.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `backup.cronjob.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `backup.cronjob.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `backup.cronjob.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `backup.cronjob.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `backup.cronjob.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `backup.cronjob.command` | Set backup container's command to run | `[]` | +| `backup.cronjob.labels` | Set the cronjob labels | `{}` | +| `backup.cronjob.annotations` | Set the cronjob annotations | `{}` | +| `backup.cronjob.storage.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `backup.cronjob.storage.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `backup.cronjob.storage.storageClass` | PVC Storage Class for the backup data volume | `""` | +| `backup.cronjob.storage.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `backup.cronjob.storage.size` | PVC Storage Request for the backup data volume | `8Gi` | +| `backup.cronjob.storage.annotations` | PVC annotations | `{}` | +| `backup.cronjob.storage.mountPath` | Path to mount the volume at | `/backup/mongodb` | +| `backup.cronjob.storage.subPath` | Subdirectory of the volume to mount at | `""` | +| `backup.cronjob.storage.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | + +### RBAC parameters + +| Name | Description | Value | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable creation of ServiceAccount for MongoDB(®) pods | `true` | +| `serviceAccount.name` | Name of the created serviceAccount | `""` | +| `serviceAccount.annotations` | Additional Service Account annotations | `{}` | +| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `false` | +| `rbac.create` | Whether to create & use RBAC resources or not | `false` | +| `rbac.rules` | Custom rules to create following the role specification | `[]` | +| `podSecurityPolicy.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | +| `podSecurityPolicy.allowPrivilegeEscalation` | Enable privilege escalation | `false` | +| `podSecurityPolicy.privileged` | Allow privileged | `false` | +| `podSecurityPolicy.spec` | Specify the full spec to use for Pod Security Policy | `{}` | + +### Volume Permissions parameters + +| Name | Description | Value | +| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.securityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.securityContext.runAsUser` | User ID for the volumePermissions container | `0` | + +### Arbiter parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `arbiter.enabled` | Enable deploying the arbiter | `true` | +| `arbiter.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `arbiter.hostAliases` | Add deployment host aliases | `[]` | +| `arbiter.configuration` | Arbiter configuration file to be used | `""` | +| `arbiter.existingConfigmap` | Name of existing ConfigMap with Arbiter configuration | `""` | +| `arbiter.command` | Override default container command (useful when using custom images) | `[]` | +| `arbiter.args` | Override default container args (useful when using custom images) | `[]` | +| `arbiter.extraFlags` | Arbiter additional command line flags | `[]` | +| `arbiter.extraEnvVars` | Extra environment variables to add to Arbiter pods | `[]` | +| `arbiter.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `arbiter.extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | +| `arbiter.annotations` | Additional labels to be added to the Arbiter statefulset | `{}` | +| `arbiter.labels` | Annotations to be added to the Arbiter statefulset | `{}` | +| `arbiter.topologySpreadConstraints` | MongoDB(®) Spread Constraints for arbiter Pods | `[]` | +| `arbiter.lifecycleHooks` | LifecycleHook for the Arbiter container to automate configuration before or after startup | `{}` | +| `arbiter.terminationGracePeriodSeconds` | Arbiter Termination Grace Period | `""` | +| `arbiter.updateStrategy.type` | Strategy that will be employed to update Pods in the StatefulSet | `RollingUpdate` | +| `arbiter.podManagementPolicy` | Pod management policy for MongoDB(®) | `OrderedReady` | +| `arbiter.schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `arbiter.podAffinityPreset` | Arbiter Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `arbiter.podAntiAffinityPreset` | Arbiter Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `arbiter.nodeAffinityPreset.type` | Arbiter Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `arbiter.nodeAffinityPreset.key` | Arbiter Node label key to match Ignored if `affinity` is set. | `""` | +| `arbiter.nodeAffinityPreset.values` | Arbiter Node label values to match. Ignored if `affinity` is set. | `[]` | +| `arbiter.affinity` | Arbiter Affinity for pod assignment | `{}` | +| `arbiter.nodeSelector` | Arbiter Node labels for pod assignment | `{}` | +| `arbiter.tolerations` | Arbiter Tolerations for pod assignment | `[]` | +| `arbiter.podLabels` | Arbiter pod labels | `{}` | +| `arbiter.podAnnotations` | Arbiter Pod annotations | `{}` | +| `arbiter.priorityClassName` | Name of the existing priority class to be used by Arbiter pod(s) | `""` | +| `arbiter.runtimeClassName` | Name of the runtime class to be used by Arbiter pod(s) | `""` | +| `arbiter.podSecurityContext.enabled` | Enable Arbiter pod(s)' Security Context | `true` | +| `arbiter.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `arbiter.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `arbiter.podSecurityContext.fsGroup` | Group ID for the volumes of the Arbiter pod(s) | `1001` | +| `arbiter.podSecurityContext.sysctls` | sysctl settings of the Arbiter pod(s)' | `[]` | +| `arbiter.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `arbiter.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `arbiter.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `arbiter.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `arbiter.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `arbiter.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `arbiter.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `arbiter.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `arbiter.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `arbiter.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `arbiter.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if arbiter.resources is set (arbiter.resources is recommended for production). | `small` | +| `arbiter.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `arbiter.containerPorts.mongodb` | MongoDB(®) arbiter container port | `27017` | +| `arbiter.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `arbiter.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `arbiter.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `arbiter.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `arbiter.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `arbiter.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `arbiter.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `arbiter.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `arbiter.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `20` | +| `arbiter.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `arbiter.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `arbiter.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `arbiter.startupProbe.enabled` | Enable startupProbe | `false` | +| `arbiter.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `arbiter.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `arbiter.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `arbiter.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `arbiter.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `arbiter.customLivenessProbe` | Override default liveness probe for Arbiter containers | `{}` | +| `arbiter.customReadinessProbe` | Override default readiness probe for Arbiter containers | `{}` | +| `arbiter.customStartupProbe` | Override default startup probe for Arbiter containers | `{}` | +| `arbiter.initContainers` | Add additional init containers for the Arbiter pod(s) | `[]` | +| `arbiter.sidecars` | Add additional sidecar containers for the Arbiter pod(s) | `[]` | +| `arbiter.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Arbiter container(s) | `[]` | +| `arbiter.extraVolumes` | Optionally specify extra list of additional volumes to the Arbiter statefulset | `[]` | +| `arbiter.pdb.create` | Enable/disable a Pod Disruption Budget creation for Arbiter pod(s) | `false` | +| `arbiter.pdb.minAvailable` | Minimum number/percentage of Arbiter pods that should remain scheduled | `1` | +| `arbiter.pdb.maxUnavailable` | Maximum number/percentage of Arbiter pods that may be made unavailable | `""` | +| `arbiter.service.nameOverride` | The arbiter service name | `""` | +| `arbiter.service.ports.mongodb` | MongoDB(®) service port | `27017` | +| `arbiter.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `arbiter.service.annotations` | Provide any additional annotations that may be required | `{}` | +| `arbiter.service.headless.annotations` | Annotations for the headless service. | `{}` | + +### Hidden Node parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `hidden.enabled` | Enable deploying the hidden nodes | `false` | +| `hidden.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `hidden.hostAliases` | Add deployment host aliases | `[]` | +| `hidden.configuration` | Hidden node configuration file to be used | `""` | +| `hidden.existingConfigmap` | Name of existing ConfigMap with Hidden node configuration | `""` | +| `hidden.command` | Override default container command (useful when using custom images) | `[]` | +| `hidden.args` | Override default container args (useful when using custom images) | `[]` | +| `hidden.extraFlags` | Hidden node additional command line flags | `[]` | +| `hidden.extraEnvVars` | Extra environment variables to add to Hidden node pods | `[]` | +| `hidden.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `hidden.extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | +| `hidden.annotations` | Additional labels to be added to thehidden node statefulset | `{}` | +| `hidden.labels` | Annotations to be added to the hidden node statefulset | `{}` | +| `hidden.topologySpreadConstraints` | MongoDB(®) Spread Constraints for hidden Pods | `[]` | +| `hidden.lifecycleHooks` | LifecycleHook for the Hidden container to automate configuration before or after startup | `{}` | +| `hidden.replicaCount` | Number of hidden nodes (only when `architecture=replicaset`) | `1` | +| `hidden.terminationGracePeriodSeconds` | Hidden Termination Grace Period | `""` | +| `hidden.updateStrategy.type` | Strategy that will be employed to update Pods in the StatefulSet | `RollingUpdate` | +| `hidden.podManagementPolicy` | Pod management policy for hidden node | `OrderedReady` | +| `hidden.schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `hidden.podAffinityPreset` | Hidden node Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `hidden.podAntiAffinityPreset` | Hidden node Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `hidden.nodeAffinityPreset.type` | Hidden Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `hidden.nodeAffinityPreset.key` | Hidden Node label key to match Ignored if `affinity` is set. | `""` | +| `hidden.nodeAffinityPreset.values` | Hidden Node label values to match. Ignored if `affinity` is set. | `[]` | +| `hidden.affinity` | Hidden node Affinity for pod assignment | `{}` | +| `hidden.nodeSelector` | Hidden node Node labels for pod assignment | `{}` | +| `hidden.tolerations` | Hidden node Tolerations for pod assignment | `[]` | +| `hidden.podLabels` | Hidden node pod labels | `{}` | +| `hidden.podAnnotations` | Hidden node Pod annotations | `{}` | +| `hidden.priorityClassName` | Name of the existing priority class to be used by hidden node pod(s) | `""` | +| `hidden.runtimeClassName` | Name of the runtime class to be used by hidden node pod(s) | `""` | +| `hidden.podSecurityContext.enabled` | Enable Hidden pod(s)' Security Context | `true` | +| `hidden.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `hidden.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `hidden.podSecurityContext.fsGroup` | Group ID for the volumes of the Hidden pod(s) | `1001` | +| `hidden.podSecurityContext.sysctls` | sysctl settings of the Hidden pod(s)' | `[]` | +| `hidden.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `hidden.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `hidden.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `hidden.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `hidden.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `hidden.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `hidden.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `hidden.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `hidden.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `hidden.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `hidden.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if hidden.resources is set (hidden.resources is recommended for production). | `micro` | +| `hidden.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `hidden.containerPorts.mongodb` | MongoDB(®) hidden container port | `27017` | +| `hidden.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `hidden.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `hidden.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `hidden.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `hidden.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `hidden.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `hidden.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `hidden.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `hidden.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `20` | +| `hidden.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `hidden.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `hidden.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `hidden.startupProbe.enabled` | Enable startupProbe | `false` | +| `hidden.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `hidden.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `hidden.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `hidden.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `hidden.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `hidden.customLivenessProbe` | Override default liveness probe for hidden node containers | `{}` | +| `hidden.customReadinessProbe` | Override default readiness probe for hidden node containers | `{}` | +| `hidden.customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `hidden.initContainers` | Add init containers to the MongoDB(®) Hidden pods. | `[]` | +| `hidden.sidecars` | Add additional sidecar containers for the hidden node pod(s) | `[]` | +| `hidden.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the hidden node container(s) | `[]` | +| `hidden.extraVolumes` | Optionally specify extra list of additional volumes to the hidden node statefulset | `[]` | +| `hidden.pdb.create` | Enable/disable a Pod Disruption Budget creation for hidden node pod(s) | `false` | +| `hidden.pdb.minAvailable` | Minimum number/percentage of hidden node pods that should remain scheduled | `1` | +| `hidden.pdb.maxUnavailable` | Maximum number/percentage of hidden node pods that may be made unavailable | `""` | +| `hidden.persistence.enabled` | Enable hidden node data persistence using PVC | `true` | +| `hidden.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `hidden.persistence.storageClass` | PVC Storage Class for hidden node data volume | `""` | +| `hidden.persistence.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `hidden.persistence.size` | PVC Storage Request for hidden node data volume | `8Gi` | +| `hidden.persistence.annotations` | PVC annotations | `{}` | +| `hidden.persistence.mountPath` | The path the volume will be mounted at, useful when using different MongoDB(®) images. | `/bitnami/mongodb` | +| `hidden.persistence.subPath` | The subdirectory of the volume to mount to, useful in dev environments | `""` | +| `hidden.persistence.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | +| `hidden.persistence.volumeClaimTemplates.requests` | Custom PVC requests attributes | `{}` | +| `hidden.persistence.volumeClaimTemplates.dataSource` | Set volumeClaimTemplate dataSource | `{}` | +| `hidden.service.portName` | MongoDB(®) service port name | `mongodb` | +| `hidden.service.ports.mongodb` | MongoDB(®) service port | `27017` | +| `hidden.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `hidden.service.annotations` | Provide any additional annotations that may be required | `{}` | +| `hidden.service.headless.annotations` | Annotations for the headless service. | `{}` | + +### Metrics parameters + +| Name | Description | Value | +| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| `metrics.enabled` | Enable using a sidecar Prometheus exporter | `false` | +| `metrics.image.registry` | MongoDB(®) Prometheus exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | MongoDB(®) Prometheus exporter image repository | `REPOSITORY_NAME/mongodb-exporter` | +| `metrics.image.digest` | MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | MongoDB(®) Prometheus exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `metrics.username` | String with username for the metrics exporter | `""` | +| `metrics.password` | String with password for the metrics exporter | `""` | +| `metrics.compatibleMode` | Enables old style mongodb-exporter metrics | `true` | +| `metrics.collector.all` | Enable all collectors. Same as enabling all individual metrics | `false` | +| `metrics.collector.diagnosticdata` | Boolean Enable collecting metrics from getDiagnosticData | `true` | +| `metrics.collector.replicasetstatus` | Boolean Enable collecting metrics from replSetGetStatus | `true` | +| `metrics.collector.dbstats` | Boolean Enable collecting metrics from dbStats | `false` | +| `metrics.collector.topmetrics` | Boolean Enable collecting metrics from top admin command | `false` | +| `metrics.collector.indexstats` | Boolean Enable collecting metrics from $indexStats | `false` | +| `metrics.collector.collstats` | Boolean Enable collecting metrics from $collStats | `false` | +| `metrics.collector.collstatsColls` | List of \.\ to get $collStats | `[]` | +| `metrics.collector.indexstatsColls` | List - List of \.\ to get $indexStats | `[]` | +| `metrics.collector.collstatsLimit` | Number - Disable collstats, dbstats, topmetrics and indexstats collector if there are more than \ collections. 0=No limit | `0` | +| `metrics.extraFlags` | String with extra flags to the metrics exporter | `""` | +| `metrics.command` | Override default container command (useful when using custom images) | `[]` | +| `metrics.args` | Override default container args (useful when using custom images) | `[]` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.containerPort` | Port of the Prometheus metrics container | `9216` | +| `metrics.service.annotations` | Annotations for Prometheus Exporter pods. Evaluated as a template. | `{}` | +| `metrics.service.type` | Type of the Prometheus metrics service | `ClusterIP` | +| `metrics.service.ports.metrics` | Port of the Prometheus metrics service | `9216` | +| `metrics.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `15` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.startupProbe.enabled` | Enable startupProbe | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.customLivenessProbe` | Override default liveness probe for MongoDB(®) containers | `{}` | +| `metrics.customReadinessProbe` | Override default readiness probe for MongoDB(®) containers | `{}` | +| `metrics.customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `metrics.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the metrics container(s) | `[]` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using Prometheus Operator | `false` | +| `metrics.serviceMonitor.namespace` | Namespace which Prometheus is running in | `""` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | Specify the timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricsRelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.serviceMonitor.labels` | Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with | `{}` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.prometheusRule.enabled` | Set this to true to create prometheusRules for Prometheus operator | `false` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so prometheusRules will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.namespace` | Namespace where prometheusRules resource should be created | `""` | +| `metrics.prometheusRule.rules` | Rules to be created, check values for an example | `[]` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.rootPassword=secretpassword,auth.username=my-user,auth.password=my-password,auth.database=my-database \ + oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the MongoDB(®) `root` account password to `secretpassword`. Additionally, it creates a standard database user named `my-user`, with the password `my-password`, who has access to a database named `my-database`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +helm install my-release -f values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/mongodb/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +If authentication is enabled, it's necessary to set the `auth.rootPassword` (also `auth.replicaSetKey` when using a replicaset architecture) when upgrading for readiness/liveness probes to work properly. When you install this chart for the first time, some notes will be displayed providing the credentials you must use under the 'Credentials' section. Please note down the password, and run the command below to upgrade your chart: + +```console +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb --set auth.rootPassword=[PASSWORD] (--set auth.replicaSetKey=[REPLICASETKEY]) +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders [PASSWORD] and [REPLICASETKEY] with the values obtained in the installation notes. + +### To 15.0.0 + +This major bump changes the following security defaults: + +- `runAsGroup` is changed from `0` to `1001` +- `readOnlyRootFilesystem` is set to `true` +- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case). +- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`. + +This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones. + +### To 12.0.0 + +This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +Affected values: + +- `strategyType` is replaced by `updateStrategy` +- `service.port` is renamed to `service.ports.mongodb` +- `service.nodePort` is renamed to `service.nodePorts.mongodb` +- `externalAccess.service.port` is renamed to `externalAccess.hidden.service.ports.mongodb` +- `rbac.role.rules` is renamed to `rbac.rules` +- `externalAccess.hidden.service.port` is renamed ot `externalAccess.hidden.service.ports.mongodb` +- `hidden.strategyType` is replaced by `hidden.updateStrategy` +- `metrics.serviceMonitor.relabellings` is renamed to `metrics.serviceMonitor.relabelings`(typo fixed) +- `metrics.serviceMonitor.additionalLabels` is renamed to `metrics.serviceMonitor.labels` + +Additionally also updates the MongoDB image dependency to it newest major, 5.0 + +### To 11.0.0 + +In this version, the mongodb-exporter bundled as part of this Helm chart was updated to a new version which, even it is not a major change, can contain breaking changes (from `0.11.X` to `0.30.X`). +Please visit the release notes from the upstream project at + +### To 10.0.0 + +[On November 13, 2020, Helm v2 support formally ended](https://github.com/helm/charts#status-of-the-project). This major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +### To 9.0.0 + +MongoDB(®) container images were updated to `4.4.x` and it can affect compatibility with older versions of MongoDB(®). Refer to the following guides to upgrade your applications: + +- [Standalone](https://docs.mongodb.com/manual/release-notes/4.4-upgrade-standalone/) +- [Replica Set](https://docs.mongodb.com/manual/release-notes/4.4-upgrade-replica-set/) + +### To 8.0.0 + +- Architecture used to configure MongoDB(®) as a replicaset was completely refactored. Now, both primary and secondary nodes are part of the same statefulset. +- Chart labels were adapted to follow the Helm charts best practices. +- This version introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. +- Several parameters were renamed or disappeared in favor of new ones on this major version. These are the most important ones: + - `replicas` is renamed to `replicaCount`. + - Authentication parameters are reorganized under the `auth.*` parameter: + - `usePassword` is renamed to `auth.enabled`. + - `mongodbRootPassword`, `mongodbUsername`, `mongodbPassword`, `mongodbDatabase`, and `replicaSet.key` are now `auth.rootPassword`, `auth.username`, `auth.password`, `auth.database`, and `auth.replicaSetKey` respectively. + - `securityContext.*` is deprecated in favor of `podSecurityContext` and `containerSecurityContext`. + - Parameters prefixed with `mongodb` are renamed removing the prefix. E.g. `mongodbEnableIPv6` is renamed to `enableIPv6`. + - Parameters affecting Arbiter nodes are reorganized under the `arbiter.*` parameter. + +Consequences: + +- Backwards compatibility is not guaranteed. To upgrade to `8.0.0`, install a new release of the MongoDB(®) chart, and migrate your data by creating a backup of the database, and restoring it on the new release. + +### To 7.0.0 + +From this version, the way of setting the ingress rules has changed. Instead of using `ingress.paths` and `ingress.hosts` as separate objects, you should now define the rules as objects inside the `ingress.hosts` value, for example: + +```yaml +ingress: + hosts: + - name: mongodb.local + path: / +``` + +### To 6.0.0 + +From this version, `mongodbEnableIPv6` is set to `false` by default in order to work properly in most k8s clusters, if you want to use IPv6 support, you need to set this variable to `true` by adding `--set mongodbEnableIPv6=true` to your `helm` command. +You can find more information in the [`bitnami/mongodb` image README](https://github.com/bitnami/containers/tree/main/bitnami/mongodb#readme). + +### To 5.0.0 + +When enabling replicaset configuration, backwards compatibility is not guaranteed unless you modify the labels used on the chart's statefulsets. +Use the workaround below to upgrade from versions previous to 5.0.0. The following example assumes that the release name is `my-release`: + +```console +kubectl delete statefulset my-release-mongodb-arbiter my-release-mongodb-primary my-release-mongodb-secondary --cascade=false +``` + +### Add extra deployment options + +To add extra deployments (useful for advanced features like sidecars), use the `extraDeploy` property. + +In the example below, you can find how to use a example here for a [MongoDB replica set pod labeler sidecar](https://github.com/combor/k8s-mongo-labeler-sidecar) to identify the primary pod and dynamically label it as the primary node: + +```yaml +extraDeploy: + - apiVersion: v1 + kind: Service + metadata: + name: mongodb-primary + namespace: default + labels: + app.kubernetes.io/component: mongodb + app.kubernetes.io/instance: mongodb + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: mongodb + spec: + type: NodePort + externalTrafficPolicy: Cluster + ports: + - name: mongodb-primary + port: 30001 + nodePort: 30001 + protocol: TCP + targetPort: mongodb + selector: + app.kubernetes.io/component: mongodb + app.kubernetes.io/instance: mongodb + app.kubernetes.io/name: mongodb + primary: "true" +``` + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/.helmignore b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/.helmignore new file mode 100644 index 0000000..7c7c21d --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# img folder +img/ diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/Chart.yaml b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/Chart.yaml new file mode 100644 index 0000000..8d0e546 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.19.1 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: VMware, Inc. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts +type: library +version: 2.19.1 diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/README.md b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/README.md new file mode 100644 index 0000000..0d01a1e --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/README.md @@ -0,0 +1,235 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://registry-1.docker.io/bitnamicharts +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +Looking to use our applications in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog. + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2024 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_affinities.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..e85b1df --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_affinities.tpl @@ -0,0 +1,139 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_capabilities.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..115674a --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_capabilities.tpl @@ -0,0 +1,229 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- if .Values.global }} + {{- if .Values.global.kubeVersion }} + {{- .Values.global.kubeVersion -}} + {{- else }} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} + {{- end -}} +{{- else }} +{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- if semverCompare "<1.7-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if .Values.ingress -}} +{{- if .Values.ingress.apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- if semverCompare "<1.10-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- if semverCompare ">=1.23-0" (include "common.capabilities.kubeVersion" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}} +{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_compatibility.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..17665d5 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_compatibility.tpl @@ -0,0 +1,39 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} +{{- if .context.Values.global.compatibility -}} + {{- if .context.Values.global.compatibility.openshift -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_errors.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..07ded6f --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_errors.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_images.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_images.tpl new file mode 100644 index 0000000..1bcb779 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_images.tpl @@ -0,0 +1,117 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := .imageRoot.registry -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = .global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- if .global }} + {{- range .global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- if $context.Values.global }} + {{- range $context.Values.global.imagePullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_ingress.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..efa5b85 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_ingress.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_labels.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..d90a6cd --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_names.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_names.tpl new file mode 100644 index 0000000..a222924 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_names.tpl @@ -0,0 +1,71 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_resources.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..030fa1a --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "1024Mi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "375m" "memory" "384Mi" "ephemeral-storage" "1024Mi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "1024Mi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "1024Mi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "1024Mi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.5" "memory" "4096Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "1024Mi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.5" "memory" "4096Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "1024Mi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_secrets.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..84dbe38 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_secrets.tpl @@ -0,0 +1,182 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- else if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} + {{- end -}} +{{- else if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString }} +{{- else }} + + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_storage.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..16405a0 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_storage.tpl @@ -0,0 +1,28 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} + +{{- $storageClass := .persistence.storageClass -}} +{{- if .global -}} + {{- if .global.storageClass -}} + {{- $storageClass = .global.storageClass -}} + {{- end -}} +{{- end -}} + +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} + +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_tplvalues.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a8ed763 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,38 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_utils.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..bfbddf0 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_warnings.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..0f763cd --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/_warnings.tpl @@ -0,0 +1,82 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/tutorials/understand-rolling-tags-containers +{{- end }} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_cassandra.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..eda9aad --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Cassandra required passwords are not empty. + +Usage: +{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret" + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.cassandra.passwords" -}} + {{- $existingSecret := include "common.cassandra.values.existingSecret" . -}} + {{- $enabled := include "common.cassandra.values.enabled" . -}} + {{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}} + {{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mariadb.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..17d83a2 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mongodb.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..bbb445b --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,113 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MongoDB® required passwords are not empty. + +Usage: +{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MongoDB® values are stored, e.g: "mongodb-passwords-secret" + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mongodb.passwords" -}} + {{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mongodb.values.enabled" . -}} + {{- $authPrefix := include "common.mongodb.values.key.auth" . -}} + {{- $architecture := include "common.mongodb.values.architecture" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyDatabase := printf "%s.database" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}} + {{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}} + + {{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }} + {{- if and $valueUsername $valueDatabase -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replicaset") -}} + {{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mysql.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..ca3953f --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MySQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mysql.passwords" -}} + {{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mysql.values.enabled" . -}} + {{- $architecture := include "common.mysql.values.architecture" . -}} + {{- $authPrefix := include "common.mysql.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_postgresql.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..8c9aa57 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,134 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate PostgreSQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_redis.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..fc0d208 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,81 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Redis® required passwords are not empty. + +Usage: +{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret" + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.redis.passwords" -}} + {{- $enabled := include "common.redis.values.enabled" . -}} + {{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}} + {{- $standarizedVersion := include "common.redis.values.standarized.version" . }} + + {{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }} + {{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }} + + {{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }} + {{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}} + {{- if eq $useAuth "true" -}} + {{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_validations.tpl b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..31ceda8 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/charts/common/values.yaml b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/values.yaml new file mode 100644 index 0000000..9abe0e1 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/NOTES.txt b/utils/assets/charts/mongo-express/charts/mongodb/templates/NOTES.txt new file mode 100644 index 0000000..3354c61 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/NOTES.txt @@ -0,0 +1,170 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ .Release.Namespace }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + +{{- else }} + +{{- $replicaCount := int .Values.replicaCount }} +{{- $portNumber := int .Values.service.ports.mongodb }} +{{- $fullname := include "mongodb.fullname" . }} +{{- $releaseNamespace := include "mongodb.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- $mongoList := list }} +{{- range $e, $i := until $replicaCount }} +{{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $portNumber) }} +{{- end }} + +{{- if and (or (and (eq .Values.architecture "standalone") (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort"))) (and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled)) (not .Values.auth.enabled) }} +------------------------------------------------------------------------------- + WARNING + + By not enabling "mongodb.auth.enabled" you have most likely exposed the + MongoDB® service externally without any authentication mechanism. + + For security reasons, we strongly suggest that you enable authentication + setting the "mongodb.auth.enabled" parameter to "true". + +------------------------------------------------------------------------------- +{{- end }} + +** Please be patient while the chart is being deployed ** + +MongoDB® can be accessed on the following DNS name(s) and ports from within your cluster: + +{{- if eq .Values.architecture "replicaset" }} +{{ join "\n" $mongoList | nindent 4 }} +{{- else }} + + {{ $fullname }}.{{ $releaseNamespace }}.svc.{{ .Values.clusterDomain }} + +{{- end }} + +{{- if .Values.auth.enabled }} + +To get the root password run: + + export MONGODB_ROOT_PASSWORD=$(kubectl get secret --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.secretName" . }} -o jsonpath="{.data.mongodb-root-password}" | base64 -d) + +{{- end }} +{{- $customUsers := include "mongodb.customUsers" . -}} +{{- $customDatabases := include "mongodb.customDatabases" . -}} +{{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} +{{- $customUsersList := splitList "," $customUsers }} +{{- range $index, $user := $customUsersList }} + +To get the password for "{{ $user }}" run: + + export MONGODB_PASSWORD=$(kubectl get secret --namespace {{ include "mongodb.namespace" $ }} {{ include "mongodb.secretName" $ }} -o jsonpath="{.data.mongodb-passwords}" | base64 -d | awk -F',' '{print ${{ add 1 $index }}}') + +{{- end }} + +To connect to your database, create a MongoDB® client container: + + kubectl run --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.fullname" . }}-client --rm --tty -i --restart='Never' --env="MONGODB_ROOT_PASSWORD=$MONGODB_ROOT_PASSWORD" --image {{ template "mongodb.image" . }} --command -- bash + +Then, run the following command: + + {{- if eq .Values.architecture "replicaset" }} + mongosh admin --host "{{ join "," $mongoList }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }} + {{- else }} + mongosh admin --host "{{ template "mongodb.service.nameOverride" . }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }} + {{- end }} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled }} + +To connect to your database nodes from outside, you need to add both primary and secondary nodes hostnames/IPs to your Mongo client. To obtain them, follow the instructions below: + +{{- if eq "NodePort" .Values.externalAccess.service.type }} +{{- if .Values.externalAccess.service.domain }} + + MongoDB® nodes domain: Use your provided hostname to reach MongoDB® nodes, {{ .Values.externalAccess.service.domain }} + +{{- else }} + + MongoDB® nodes domain: you can reach MongoDB® nodes on any of the K8s nodes external IPs. + + kubectl get nodes -o wide + +{{- end }} + + MongoDB® nodes port: You will have a different node port for each MongoDB® node. You can get the list of configured node ports using the command below: + + echo "$(kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -o jsonpath='{.items[*].spec.ports[0].nodePort}' | tr ' ' '\n')" + +{{- else if contains "LoadBalancer" .Values.externalAccess.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IPs to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -w' + + MongoDB® nodes domain: You will have a different external IP for each MongoDB® node. You can get the list of external IPs using the command below: + + echo "$(kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -o jsonpath='{.items[*].status.loadBalancer.ingress[0].ip}' | tr ' ' '\n')" + + MongoDB® nodes port: {{ .Values.externalAccess.service.ports.mongodb }} + +{{- end }} + +{{- else if eq .Values.architecture "standalone" }} + +To connect to your database from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ template "mongodb.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ template "mongodb.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "mongodb.service.nameOverride" . }}) + mongo --host $NODE_IP --port $NODE_PORT {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- else if contains "LoadBalancer" .Values.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ template "mongodb.namespace" . }} -w {{ template "mongodb.service.nameOverride" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.service.nameOverride" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + mongosh --host $SERVICE_IP --port {{ $portNumber }} {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- else if contains "ClusterIP" .Values.service.type }} + + kubectl port-forward --namespace {{ template "mongodb.namespace" . }} svc/{{ template "mongodb.service.nameOverride" . }} {{ $portNumber }}:{{ $portNumber }} & + mongosh --host 127.0.0.1 {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- end }} +{{- end }} +{{- end }} + +{{- if .Values.metrics.enabled }} + +To access the MongoDB® Prometheus metrics, get the MongoDB® Prometheus URL by running: + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ printf "%s-metrics" (include "mongodb.fullname" .) }} {{ .Values.metrics.service.ports.metrics }}:{{ .Values.metrics.service.ports.metrics }} & + echo "Prometheus Metrics URL: http://127.0.0.1:{{ .Values.metrics.service.ports.metrics }}/metrics" + +Then, open the obtained URL in a browser. + +{{- end }} +{{- end }} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "common.warnings.rollingTag" .Values.externalAccess.autoDiscovery.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "common.warnings.rollingTag" .Values.tls.image }} +{{- include "mongodb.validateValues" . }} +{{- include "common.warnings.resources" (dict "sections" (list "arbiter" "externalAccess.autoDiscovery" "hidden" "metrics" "" "tls" "volumePermissions") "context" $) }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/_helpers.tpl b/utils/assets/charts/mongo-express/charts/mongodb/templates/_helpers.tpl new file mode 100644 index 0000000..952305f --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/_helpers.tpl @@ -0,0 +1,538 @@ +{{/* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "mongodb.name" -}} +{{- include "common.names.name" . -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongodb.fullname" -}} +{{- include "common.names.fullname" . -}} +{{- end -}} + +{{/* +Create a default mongo service name which can be overridden. +*/}} +{{- define "mongodb.service.nameOverride" -}} + {{- if and .Values.service .Values.service.nameOverride -}} + {{- print .Values.service.nameOverride -}} + {{- else -}} + {{- if eq .Values.architecture "replicaset" -}} + {{- printf "%s-headless" (include "mongodb.fullname" .) -}} + {{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Create a default mongo arbiter service name which can be overridden. +*/}} +{{- define "mongodb.arbiter.service.nameOverride" -}} + {{- if and .Values.arbiter.service .Values.arbiter.service.nameOverride -}} + {{- print .Values.arbiter.service.nameOverride -}} + {{- else -}} + {{- printf "%s-arbiter-headless" (include "mongodb.fullname" .) -}} + {{- end }} +{{- end }} + +{{/* +Return the proper MongoDB® image name +*/}} +{{- define "mongodb.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "mongodb.metrics.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "mongodb.volumePermissions.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container auto-discovery image) +*/}} +{{- define "mongodb.externalAccess.autoDiscovery.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.externalAccess.autoDiscovery.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the TLS Certs image) +*/}} +{{- define "mongodb.tls.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.tls.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "mongodb.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image .Values.tls.image) "context" $) -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "mongodb.namespace" -}} + {{- if and .Values.global .Values.global.namespaceOverride -}} + {{- print .Values.global.namespaceOverride -}} + {{- else -}} + {{- print .Release.Namespace -}} + {{- end }} +{{- end -}} +{{- define "mongodb.serviceMonitor.namespace" -}} + {{- if .Values.metrics.serviceMonitor.namespace -}} + {{- print .Values.metrics.serviceMonitor.namespace -}} + {{- else -}} + {{- include "mongodb.namespace" . -}} + {{- end }} +{{- end -}} +{{- define "mongodb.prometheusRule.namespace" -}} + {{- if .Values.metrics.prometheusRule.namespace -}} + {{- print .Values.metrics.prometheusRule.namespace -}} + {{- else -}} + {{- include "mongodb.namespace" . -}} + {{- end }} +{{- end -}} + +{{/* +Returns the proper service account name depending if an explicit service account name is set +in the values file. If the name is not set it will default to either mongodb.fullname if serviceAccount.create +is true or default otherwise. +*/}} +{{- define "mongodb.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{- default (include "mongodb.fullname" .) (print .Values.serviceAccount.name) -}} + {{- else -}} + {{- default "default" (print .Values.serviceAccount.name) -}} + {{- end -}} +{{- end -}} + +{{/* +Return the list of custom users to create during the initialization (string format) +*/}} +{{- define "mongodb.customUsers" -}} + {{- $customUsers := list -}} + {{- if .Values.auth.username -}} + {{- $customUsers = append $customUsers .Values.auth.username }} + {{- end }} + {{- range .Values.auth.usernames }} + {{- $customUsers = append $customUsers . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customUsers)) -}} +{{- end -}} + +{{/* +Return the list of passwords for the custom users (string format) +*/}} +{{- define "mongodb.customPasswords" -}} + {{- $customPasswords := list -}} + {{- if .Values.auth.password -}} + {{- $customPasswords = append $customPasswords .Values.auth.password }} + {{- end }} + {{- range .Values.auth.passwords }} + {{- $customPasswords = append $customPasswords . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customPasswords)) -}} +{{- end -}} + +{{/* +Return the list of custom databases to create during the initialization (string format) +*/}} +{{- define "mongodb.customDatabases" -}} + {{- $customDatabases := list -}} + {{- if .Values.auth.database -}} + {{- $customDatabases = append $customDatabases .Values.auth.database }} + {{- end }} + {{- range .Values.auth.databases }} + {{- $customDatabases = append $customDatabases . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customDatabases)) -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration +*/}} +{{- define "mongodb.configmapName" -}} +{{- if .Values.existingConfigmap -}} + {{- printf "%s" (tpl .Values.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® +*/}} +{{- define "mongodb.createConfigmap" -}} +{{- if and .Values.configuration (not .Values.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret with MongoDB® credentials +*/}} +{{- define "mongodb.secretName" -}} + {{- if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} + {{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for MongoDB® +*/}} +{{- define "mongodb.createSecret" -}} +{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "mongodb.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} +{{- printf "%s" .Values.initdbScriptsConfigMap -}} +{{- else -}} +{{- printf "%s-init-scripts" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if the Arbiter should be deployed +*/}} +{{- define "mongodb.arbiter.enabled" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.arbiter.enabled }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration for the Arbiter +*/}} +{{- define "mongodb.arbiter.configmapName" -}} +{{- if .Values.arbiter.existingConfigmap -}} + {{- printf "%s" (tpl .Values.arbiter.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-arbiter" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® Arbiter +*/}} +{{- define "mongodb.arbiter.createConfigmap" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.arbiter.enabled .Values.arbiter.configuration (not .Values.arbiter.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if the Hidden should be deployed +*/}} +{{- define "mongodb.hidden.enabled" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.hidden.enabled }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration for the Hidden +*/}} +{{- define "mongodb.hidden.configmapName" -}} +{{- if .Values.hidden.existingConfigmap -}} + {{- printf "%s" (tpl .Values.hidden.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-hidden" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® Hidden +*/}} +{{- define "mongodb.hidden.createConfigmap" -}} +{{- if and (include "mongodb.hidden.enabled" .) .Values.hidden.enabled .Values.hidden.configuration (not .Values.hidden.existingConfigmap) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "mongodb.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "mongodb.validateValues.pspAndRBAC" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.architecture" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.customUsersDBs" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.customUsersDBsLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessServiceType" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.loadBalancerIPsListLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.nodePortListLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessAutoDiscoveryRBAC" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessAutoDiscoverySA" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.replicaset.existingSecrets" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.hidden.existingSecrets" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate RBAC is created when using PSP */}} +{{- define "mongodb.validateValues.pspAndRBAC" -}} +{{- if and (.Values.podSecurityPolicy.create) (not .Values.rbac.create) -}} +mongodb: podSecurityPolicy.create, rbac.create + Both podSecurityPolicy.create and rbac.create must be true, if you want + to create podSecurityPolicy +{{- end -}} +{{- end -}} + +{{/* Validate values of MongoDB® - must provide a valid architecture */}} +{{- define "mongodb.validateValues.architecture" -}} +{{- if and (ne .Values.architecture "standalone") (ne .Values.architecture "replicaset") -}} +mongodb: architecture + Invalid architecture selected. Valid values are "standalone" and + "replicaset". Please set a valid architecture (--set mongodb.architecture="xxxx") +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - both auth.usernames and auth.databases are necessary +to create a custom user and database during 1st initialization +*/}} +{{- define "mongodb.validateValues.customUsersDBs" -}} +{{- $customUsers := include "mongodb.customUsers" . -}} +{{- $customDatabases := include "mongodb.customDatabases" . -}} +{{- if or (and (empty $customUsers) (not (empty $customDatabases))) (and (not (empty $customUsers)) (empty $customDatabases)) }} +mongodb: auth.usernames, auth.databases + Both auth.usernames and auth.databases must be provided to create + custom users and databases during 1st initialization. + Please set both of them (--set auth.usernames[0]="xxxx",auth.databases[0]="yyyy") +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - both auth.usernames and auth.databases arrays should have the same length +to create a custom user and database during 1st initialization +*/}} +{{- define "mongodb.validateValues.customUsersDBsLength" -}} +{{- if ne (len .Values.auth.usernames) (len .Values.auth.databases) }} +mongodb: auth.usernames, auth.databases + Both auth.usernames and auth.databases arrays should have the same length +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - service type for external access +*/}} +{{- define "mongodb.validateValues.externalAccessServiceType" -}} +{{- if and (eq .Values.architecture "replicaset") (not (eq .Values.externalAccess.service.type "NodePort")) (not (eq .Values.externalAccess.service.type "LoadBalancer")) (not (eq .Values.externalAccess.service.type "ClusterIP")) -}} +mongodb: externalAccess.service.type + Available service type for external access are NodePort, LoadBalancer or ClusterIP. +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - number of replicas must be the same than LoadBalancer IPs list +*/}} +{{- define "mongodb.validateValues.loadBalancerIPsListLength" -}} +{{- $replicaCount := int .Values.replicaCount }} +{{- $loadBalancerListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "LoadBalancer") -}} +{{- if and (not .Values.externalAccess.autoDiscovery.enabled) (eq $loadBalancerListLength 0) -}} +mongodb: .Values.externalAccess.service.loadBalancerIPs + externalAccess.service.loadBalancerIPs or externalAccess.autoDiscovery.enabled are required when externalAccess is enabled. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerListLength )) -}} +mongodb: .Values.externalAccess.service.loadBalancerIPs + Number of replicas ({{ $replicaCount }}) and loadBalancerIPs ({{ $loadBalancerListLength }}) array length must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - number of replicas must be the same than NodePort list +*/}} +{{- define "mongodb.validateValues.nodePortListLength" -}} +{{- $replicaCount := int .Values.replicaCount }} +{{- $nodePortListLength := len .Values.externalAccess.service.nodePorts }} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "NodePort") -}} +{{- if and (not .Values.externalAccess.autoDiscovery.enabled) (eq $nodePortListLength 0) -}} +mongodb: .Values.externalAccess.service.loadBalancerIPs + externalAccess.service.loadBalancerIPs or externalAccess.autoDiscovery.enabled are required when externalAccess is enabled. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $nodePortListLength )) -}} +mongodb: .Values.externalAccess.service.nodePorts + Number of replicas ({{ $replicaCount }}) and nodePorts ({{ $nodePortListLength }}) array length must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - RBAC should be enabled when autoDiscovery is enabled +*/}} +{{- define "mongodb.validateValues.externalAccessAutoDiscoveryRBAC" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (not .Values.rbac.create ) }} +mongodb: rbac.create + By specifying "externalAccess.enabled=true" and "externalAccess.autoDiscovery.enabled=true" + an initContainer will be used to autodetect the external IPs/ports by querying the + K8s API. Please note this initContainer requires specific RBAC resources. You can create them + by specifying "--set rbac.create=true". +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - automountServiceAccountToken should be enabled when autoDiscovery is enabled +*/}} +{{- define "mongodb.validateValues.externalAccessAutoDiscoverySA" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (not .Values.automountServiceAccountToken ) }} +mongodb: automountServiceAccountToken + By specifying "externalAccess.enabled=true" and "externalAccess.autoDiscovery.enabled=true" + an initContainer will be used to autodetect the external IPs/ports by querying the + K8s API. Please note this initContainer requires a service account to access K8S API. + You can attach it to the pod by specifying "--set automountServiceAccountToken=true". +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - Number of replicaset secrets must be the same than number of replicaset nodes. +*/}} +{{- define "mongodb.validateValues.replicaset.existingSecrets" -}} +{{- if and .Values.tls.enabled (eq .Values.architecture "replicaset") (not (empty .Values.tls.replicaset.existingSecrets)) }} +{{- $nbSecrets := len .Values.tls.replicaset.existingSecrets -}} +{{- if not (eq $nbSecrets (int .Values.replicaCount)) }} +mongodb: tls.replicaset.existingSecrets + tls.replicaset.existingSecrets Number of secrets and number of replicaset nodes must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - Number of hidden secrets must be the same than number of hidden nodes. +*/}} +{{- define "mongodb.validateValues.hidden.existingSecrets" -}} +{{- if and .Values.tls.enabled (include "mongodb.hidden.enabled" .) (not (empty .Values.tls.hidden.existingSecrets)) }} +{{- $nbSecrets := len .Values.tls.hidden.existingSecrets -}} +{{- if not (eq $nbSecrets (int .Values.hidden.replicaCount)) }} +mongodb: tls.hidden.existingSecrets + tls.hidden.existingSecrets Number of secrets and number of hidden nodes must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® exporter URI string - auth.enabled and/or tls.enabled must be enabled or it defaults +*/}} +{{- define "mongodb.mongodb_exporter.uri" -}} + {{- $tlsEnabled := .Values.tls.enabled -}} + {{- $mTlsEnabled := and $tlsEnabled .Values.tls.mTLS.enabled -}} + {{- $tlsArgs := "" -}} + {{- if $tlsEnabled -}} + {{- $tlsCertKeyFile := ternary "&tlsCertificateKeyFile=/certs/mongodb.pem" "" $mTlsEnabled -}} + {{- $tlsArgs = printf "tls=true%s&tlsCAFile=/certs/mongodb-ca-cert" $tlsCertKeyFile -}} + {{- end -}} + {{- if .Values.metrics.username -}} + {{- $uriAuth := ternary "$(echo $MONGODB_METRICS_USERNAME | sed -r \"s/@/%40/g;s/:/%3A/g\"):$(echo $MONGODB_METRICS_PASSWORD | sed -r \"s/@/%40/g;s/:/%3A/g\")@" "" .Values.auth.enabled -}} + {{- printf "mongodb://%slocalhost:%d/admin?%s" $uriAuth (int .Values.containerPorts.mongodb) $tlsArgs -}} + {{- else -}} + {{- $uriAuth := ternary "$MONGODB_ROOT_USER:$(echo $MONGODB_ROOT_PASSWORD | sed -r \"s/@/%40/g;s/:/%3A/g\")@" "" .Values.auth.enabled -}} + {{- printf "mongodb://%slocalhost:%d/admin?%s" $uriAuth (int .Values.containerPorts.mongodb) $tlsArgs -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiGroup for PodSecurityPolicy. +*/}} +{{- define "podSecurityPolicy.apiGroup" -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy" -}} +{{- else -}} +{{- print "extensions" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "mongodb.createTlsSecret" -}} +{{- if and .Values.tls.enabled (not .Values.tls.existingSecret) (include "mongodb.autoGenerateCerts" .) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing MongoDB® TLS certificates +*/}} +{{- define "mongodb.tlsSecretName" -}} +{{- $secretName := .Values.tls.existingSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-ca" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if certificates must be auto generated +*/}} +{{- define "mongodb.autoGenerateCerts" -}} +{{- $standalone := (eq .Values.architecture "standalone") | ternary (not .Values.tls.standalone.existingSecret) true -}} +{{- $replicaset := (eq .Values.architecture "replicaset") | ternary (empty .Values.tls.replicaset.existingSecrets) true -}} +{{- $arbiter := (eq (include "mongodb.arbiter.enabled" .) "true") | ternary (not .Values.tls.arbiter.existingSecret) true -}} +{{- $hidden := (eq (include "mongodb.hidden.enabled" .) "true") | ternary (empty .Values.tls.hidden.existingSecrets) true -}} +{{- if and $standalone $replicaset $arbiter $hidden -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Generate argument list for mongodb-exporter +reference: https://github.com/percona/mongodb_exporter/blob/main/REFERENCE.md +*/}} +{{- define "mongodb.exporterArgs" -}} +{{- with .Values.metrics.collector -}} +{{- ternary " --collect-all" "" .all -}} +{{- ternary " --collector.diagnosticdata" "" .diagnosticdata -}} +{{- ternary " --collector.replicasetstatus" "" .replicasetstatus -}} +{{- ternary " --collector.dbstats" "" .dbstats -}} +{{- ternary " --collector.topmetrics" "" .topmetrics -}} +{{- ternary " --collector.indexstats" "" .indexstats -}} +{{- ternary " --collector.collstats" "" .collstats -}} +{{- if .collstatsColls -}} +{{- " --mongodb.collstats-colls=" -}} +{{- join "," .collstatsColls -}} +{{- end -}} +{{- if .indexstatsColls -}} +{{- " --mongodb.indexstats-colls=" -}} +{{- join "," .indexstatsColls -}} +{{- end -}} +{{- $limitArg := print " --collector.collstats-limit=" .collstatsLimit -}} +{{- ne (print .collstatsLimit) "0" | ternary $limitArg "" -}} +{{- end -}} +{{- ternary " --compatible-mode" "" .Values.metrics.compatibleMode -}} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/configmap.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/configmap.yaml new file mode 100644 index 0000000..79fbfe5 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/headless-svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/headless-svc.yaml new file mode 100644 index 0000000..003bebb --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/headless-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.enabled" .) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.arbiter.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if or .Values.arbiter.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-mongodb + port: {{ .Values.arbiter.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.arbiter.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/pdb.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/pdb.yaml new file mode 100644 index 0000000..37b5c19 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.arbiter.enabled" .) .Values.arbiter.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.arbiter.pdb.minAvailable }} + minAvailable: {{ .Values.arbiter.pdb.minAvailable }} + {{- end }} + {{- if .Values.arbiter.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.arbiter.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: arbiter +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/statefulset.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/statefulset.yaml new file mode 100644 index 0000000..8ccfa67 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/arbiter/statefulset.yaml @@ -0,0 +1,313 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.enabled" .) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if or .Values.arbiter.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.arbiter.service.nameOverride" . }} + podManagementPolicy: {{ .Values.arbiter.podManagementPolicy }} + {{- if .Values.arbiter.updateStrategy }} + updateStrategy: {{- toYaml .Values.arbiter.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: arbiter + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: arbiter + {{- if or (include "mongodb.arbiter.createConfigmap" .) .Values.arbiter.podAnnotations }} + annotations: + {{- if (include "mongodb.arbiter.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/arbiter/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.arbiter.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.arbiter.schedulerName }} + schedulerName: {{ .Values.arbiter.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + {{- if .Values.arbiter.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.arbiter.podAffinityPreset "component" "arbiter" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.arbiter.podAntiAffinityPreset "component" "arbiter" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.arbiter.nodeAffinityPreset.type "key" .Values.arbiter.nodeAffinityPreset.key "values" .Values.arbiter.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.arbiter.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.nodeSelector "context" $) | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.arbiter.automountServiceAccountToken }} + {{- if .Values.arbiter.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.priorityClassName }} + priorityClassName: {{ .Values.arbiter.priorityClassName }} + {{- end }} + {{- if .Values.arbiter.runtimeClassName }} + runtimeClassName: {{ .Values.arbiter.runtimeClassName }} + {{- end }} + {{- if .Values.arbiter.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.arbiter.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.arbiter.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.arbiter.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.arbiter.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.arbiter.service.nameOverride" . }} + {{- end }} + containers: + - name: mongodb-arbiter + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.arbiter.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.arbiter.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.arbiter.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.arbiter.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.arbiter.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_SERVICE_NAME + value: "{{ include "mongodb.arbiter.service.nameOverride" . }}" + - name: MONGODB_REPLICA_SET_MODE + value: "arbiter" + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ printf "%s-0.%s.$(MY_POD_NAMESPACE).svc.%s" (include "mongodb.fullname" .) (include "mongodb.service.nameOverride" .) .Values.clusterDomain }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + - name: MONGODB_PORT_NUMBER + value: {{ .Values.arbiter.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_INITIAL_PRIMARY_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- $extraFlags := .Values.arbiter.extraFlags | join " " -}} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.arbiter.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.arbiter.extraEnvVarsCM .Values.arbiter.extraEnvVarsSecret }} + envFrom: + {{- if .Values.arbiter.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.arbiter.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.arbiter.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.arbiter.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.arbiter.containerPorts.mongodb }} + name: mongodb + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.arbiter.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: mongodb + {{- end }} + {{- if .Values.arbiter.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.readinessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: mongodb + {{- end }} + {{- if .Values.arbiter.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: mongodb + {{- end }} + {{- end }} + {{- if .Values.arbiter.resources }} + resources: {{- toYaml .Values.arbiter.resources | nindent 12 }} + {{- else if ne .Values.arbiter.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.arbiter.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /bitnami/mongodb + subPath: app-volume-dir + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.arbiter.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.arbiter.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap .Values.arbiter.extraVolumes .Values.tls.enabled }} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0555 + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.arbiter.configmapName" . }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.arbiter.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if .Values.arbiter.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/backup/cronjob.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/backup/cronjob.yaml new file mode 100644 index 0000000..fdae36d --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/backup/cronjob.yaml @@ -0,0 +1,207 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.backup.enabled }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "mongodb.fullname" . }}-mongodump + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + schedule: {{ quote .Values.backup.cronjob.schedule }} + concurrencyPolicy: {{ .Values.backup.cronjob.concurrencyPolicy }} + failedJobsHistoryLimit: {{ .Values.backup.cronjob.failedJobsHistoryLimit }} + successfulJobsHistoryLimit: {{ .Values.backup.cronjob.successfulJobsHistoryLimit }} + {{- if .Values.backup.cronjob.startingDeadlineSeconds }} + startingDeadlineSeconds: {{ .Values.backup.cronjob.startingDeadlineSeconds }} + {{- end }} + jobTemplate: + spec: + {{- if .Values.backup.cronjob.backoffLimit }} + backoffLimit: {{ .Values.backup.cronjob.backoffLimit }} + {{- end }} + {{- if .Values.backup.cronjob.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.backup.cronjob.ttlSecondsAfterFinished }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" . | nindent 12 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 10 }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- if .Values.tls.enabled }} + initContainers: + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if .Values.tls.extraDnsNames }} + - -n {{ join "," .Values.tls.extraDnsNames }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- toYaml .Values.tls.resources | nindent 16 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 16 }} + {{- end }} + {{- end }} + containers: + - name: {{ include "mongodb.fullname" . }}-mongodump + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + env: + {{- if .Values.auth.enabled }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + - name: MONGODB_SERVICE_NAME + value: {{ include "mongodb.service.nameOverride" . }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODUMP_DIR + value: {{ .Values.backup.cronjob.storage.mountPath }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --ssl --sslPEMKeyFile=/certs/mongodb.pem --sslCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.backup.cronjob.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.command "context" $) | nindent 14 }} + {{- else }} + command: + - /bin/sh + - -c + - "mongodump {{- if .Values.auth.enabled }} --username=${MONGODB_ROOT_USER} --password=${MONGODB_ROOT_PASSWORD} --authenticationDatabase=admin {{- end }} --host=${MONGODB_SERVICE_NAME} --port=${MONGODB_PORT_NUMBER} ${MONGODB_CLIENT_EXTRA_FLAGS} {{- if (eq $.Values.architecture "replicaset") }}--oplog{{- end }} --gzip --archive=${MONGODUMP_DIR}/mongodump-$(date '+%Y-%m-%d-%H-%M').gz" + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + {{- end }} + - name: datadir + mountPath: {{ .Values.backup.cronjob.storage.mountPath }} + subPath: {{ .Values.backup.cronjob.storage.subPath }} + {{- if .Values.backup.cronjob.containerSecurityContext.enabled }} + securityContext: + {{- include "common.tplvalues.render" ( dict "value" ( omit .Values.backup.cronjob.containerSecurityContext "enabled" ) "context" $) | nindent 14 }} + {{- end }} + restartPolicy: {{ .Values.backup.cronjob.restartPolicy }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.standalone.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if .Values.backup.cronjob.storage.existingClaim }} + - name: datadir + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.backup.cronjob.storage.existingClaim .) }} + {{- else }} + - name: datadir + persistentVolumeClaim: + claimName: {{ include "mongodb.fullname" . }}-mongodump + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/backup/pvc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/backup/pvc.yaml new file mode 100644 index 0000000..caefc05 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/backup/pvc.yaml @@ -0,0 +1,41 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.backup.enabled (not .Values.backup.cronjob.storage.existingClaim) -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "mongodb.fullname" . }}-mongodump + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations .Values.backup.cronjob.storage.resourcePolicy}} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.backup.cronjob.storage.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.backup.cronjob.storage.resourcePolicy | quote }} + {{- end }} + {{- end }} +spec: + accessModes: + {{- range .Values.backup.cronjob.storage.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backup.cronjob.storage.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.backup.cronjob.storage "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/common-scripts-cm.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/common-scripts-cm.yaml new file mode 100644 index 0000000..bf5fead --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/common-scripts-cm.yaml @@ -0,0 +1,146 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- $fullname := include "mongodb.fullname" . }} + startup-probe.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert--tlsAllowInvalidHostnames' + {{- end }} + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval 'if (!(db.hello().isWritablePrimary || db.hello().secondary)) { throw new Error("Not ready") }' + readiness-probe.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + # Run the proper check depending on the version + [[ $(mongod -version | grep "db version") =~ ([0-9]+\.[0-9]+\.[0-9]+) ]] && VERSION=${BASH_REMATCH[1]} + . /opt/bitnami/scripts/libversion.sh + VERSION_MAJOR="$(get_sematic_version "$VERSION" 1)" + VERSION_MINOR="$(get_sematic_version "$VERSION" 2)" + VERSION_PATCH="$(get_sematic_version "$VERSION" 3)" + readiness_test='db.isMaster().ismaster || db.isMaster().secondary' + if [[ ( "$VERSION_MAJOR" -ge 5 ) || ( "$VERSION_MAJOR" -ge 4 && "$VERSION_MINOR" -ge 4 && "$VERSION_PATCH" -ge 2 ) ]]; then + readiness_test='db.hello().isWritablePrimary || db.hello().secondary' + fi + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval "if (!(${readiness_test})) { throw new Error(\"Not ready\") }" + ping-mongodb.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval "db.adminCommand('ping')" + {{- if .Values.tls.enabled }} + generate-certs.sh: | + #!/bin/bash + {{- if (include "mongodb.autoGenerateCerts" .) }} + additional_ips=() + additional_names=() + while getopts "i:n:s:" flag + do + case "${flag}" in + i) read -a additional_ips <<< ${OPTARG//,/ } ;; + n) read -a additional_names <<< ${OPTARG//,/ } ;; + s) svc=${OPTARG// /} ;; + \?) exit 1 ;; + esac + done + + my_hostname=$(hostname) + cp /certs/CAs/* /certs/ + cat >/certs/openssl.cnf <>/certs/openssl.cnf <>/certs/openssl.cnf < /certs/mongodb.pem + cd /certs/ + shopt -s extglob + rm -rf !(mongodb-ca-cert|mongodb.pem|CAs|openssl.cnf) + chmod 0600 mongodb-ca-cert mongodb.pem + {{- else }} + {{- if eq .Values.architecture "standalone" }} + ID="0" + {{- else }} + if [[ "$MY_POD_NAME" =~ "arbiter-0"$ ]]; then + ID="0" + elif [[ "$MY_POD_NAME" =~ "hidden-"[0-9]{1,}$ ]]; then + ID="${MY_POD_NAME#"{{ printf "%s-hidden-" $fullname }}"}" + else + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + fi + {{- end }} + + {{- if .Values.tls.pemChainIncluded }} + #Split the pem chain by the END CERTIFICATE string and store in files /certs/xx00, /certs/xx01 etc. + cat /certs-${ID}/tls.crt | csplit - -s -z '/\-*END CERTIFICATE\-*/+1' '{*}' -f /certs/xx + + #Use first certificate as leaf node and combine with key to store in pem file + cat "/certs/xx00" "/certs-${ID}/tls.key" > "/certs/mongodb.pem" + + #Use remaining intermediate certificates for ca.crt + echo $(find /certs/ -not -name 'xx00' -name 'xx*') | sort | xargs cat > "/certs/mongodb-ca-cert" + + rm -rf /certs/xx* + {{- else }} + cat "/certs-${ID}/tls.crt" "/certs-${ID}/tls.key" > "/certs/mongodb.pem" + cp "/certs-${ID}/ca.crt" "/certs/mongodb-ca-cert" + {{- end }} + + chmod 0600 /certs/mongodb-ca-cert /certs/mongodb.pem + {{- end }} + {{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/configmap.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/configmap.yaml new file mode 100644 index 0000000..7d11e08 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/extra-list.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/extra-list.yaml new file mode 100644 index 0000000..2d35a58 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/configmap.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/configmap.yaml new file mode 100644 index 0000000..a830873 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/external-access-svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/external-access-svc.yaml new file mode 100644 index 0000000..6cbbb40 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/external-access-svc.yaml @@ -0,0 +1,69 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.hidden.enabled" .) .Values.externalAccess.hidden.enabled }} +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.hidden.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-hidden-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-hidden-%d-external" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + pod: {{ $targetPod }} + {{- if or $root.Values.externalAccess.hidden.service.annotations $root.Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.externalAccess.hidden.service.annotations $root.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ $root.Values.externalAccess.hidden.service.type }} + {{- if eq $root.Values.externalAccess.hidden.service.type "LoadBalancer" }} + {{- if not (empty $root.Values.externalAccess.hidden.service.loadBalancerIPs) }} + loadBalancerIP: {{ index $root.Values.externalAccess.hidden.service.loadBalancerIPs $i }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.loadBalancerClass }} + loadBalancerClass: {{ $root.Values.externalAccess.hidden.service.loadBalancerClass }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.hidden.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + allocateLoadBalancerNodePorts: {{ $root.Values.externalAccess.hidden.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if (or (eq $root.Values.externalAccess.hidden.service.type "LoadBalancer") (eq $root.Values.externalAccess.hidden.service.type "NodePort")) }} + externalTrafficPolicy: {{ $root.Values.externalAccess.hidden.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.sessionAffinity }} + sessionAffinity: {{ $root.Values.externalAccess.hidden.service.sessionAffinity }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.hidden.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + publishNotReadyAddresses: true + ports: + - name: {{ $root.Values.externalAccess.hidden.service.portName | quote }} + port: {{ $root.Values.externalAccess.hidden.service.ports.mongodb }} + {{- if not (empty $root.Values.externalAccess.hidden.service.nodePorts) }} + {{- $nodePort := index $root.Values.externalAccess.hidden.service.nodePorts $i }} + nodePort: {{ $nodePort }} + {{- else }} + nodePort: null + {{- end }} + targetPort: mongodb + {{- if $root.Values.externalAccess.hidden.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.hidden.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.hidden.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/headless-svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/headless-svc.yaml new file mode 100644 index 0000000..49b6845 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/headless-svc.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.enabled" .) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-hidden-headless" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if or .Values.hidden.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: {{ .Values.hidden.service.portName | quote }} + port: {{ .Values.hidden.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.hidden.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/pdb.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/pdb.yaml new file mode 100644 index 0000000..5420a93 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.hidden.enabled" .) .Values.hidden.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" . )}} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.hidden.pdb.minAvailable }} + minAvailable: {{ .Values.hidden.pdb.minAvailable }} + {{- end }} + {{- if .Values.hidden.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.hidden.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: hidden +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/statefulset.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/statefulset.yaml new file mode 100644 index 0000000..e442a58 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/hidden/statefulset.yaml @@ -0,0 +1,601 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.enabled" .) }} +{{- $replicaCount := int .Values.hidden.replicaCount }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.hidden.service.loadBalancerIPs }} +{{- if not (and .Values.externalAccess.hidden.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.hidden.service.type "LoadBalancer")) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if or .Values.hidden.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ printf "%s-hidden-headless" (include "mongodb.fullname" .) }} + podManagementPolicy: {{ .Values.hidden.podManagementPolicy }} + replicas: {{ .Values.hidden.replicaCount }} + {{- if .Values.hidden.updateStrategy }} + updateStrategy: {{- toYaml .Values.hidden.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: hidden + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: hidden + {{- if or (include "mongodb.hidden.createConfigmap" .) .Values.hidden.podAnnotations }} + annotations: + {{- if (include "mongodb.hidden.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/hidden/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.hidden.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.hidden.schedulerName }} + schedulerName: {{ .Values.hidden.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.hidden.automountServiceAccountToken }} + {{- if .Values.hidden.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.hidden.podAffinityPreset "component" "hidden" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.hidden.podAntiAffinityPreset "component" "hidden" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.hidden.nodeAffinityPreset.type "key" .Values.hidden.nodeAffinityPreset.key "values" .Values.hidden.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.hidden.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.priorityClassName }} + priorityClassName: {{ .Values.hidden.priorityClassName }} + {{- end }} + {{- if .Values.hidden.runtimeClassName }} + runtimeClassName: {{ .Values.hidden.runtimeClassName }} + {{- end }} + {{- if .Values.hidden.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.hidden.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.hidden.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.hidden.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- if or .Values.hidden.initContainers (and .Values.volumePermissions.enabled .Values.hidden.persistence.enabled) (and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled) .Values.tls.enabled }} + initContainers: + {{- if .Values.hidden.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.hidden.persistence.enabled }} + - name: volume-permissions + image: {{ include "mongodb.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p {{ printf "%s/%s" .Values.hidden.persistence.mountPath (default "" .Values.hidden.persistence.subPath) }} + chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ printf "%s/%s" .Values.hidden.persistence.mountPath (default "" .Values.hidden.persistence.subPath) }} + find {{ printf "%s/%s" .Values.hidden.persistence.mountPath (default "" .Values.hidden.persistence.subPath) }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: datadir + mountPath: {{ .Values.hidden.persistence.mountPath }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + {{- range $index, $_ := .Values.tls.hidden.existingSecrets }} + - name: mongodb-certs-{{ $index }} + mountPath: /certs-{{ $index }} + {{- end }} + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ printf "%s-hidden-headless" (include "mongodb.fullname" .) }} + {{- if .Values.externalAccess.hidden.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.hidden.service.loadBalancerIPs }} + {{- end }} + {{- if .Values.tls.extraDnsNames }} + - -n {{ join "," .Values.tls.extraDnsNames }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- toYaml .Values.tls.resources | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: auto-discovery + image: {{ include "mongodb.externalAccess.autoDiscovery.image" . }} + imagePullPolicy: {{ .Values.externalAccess.autoDiscovery.image.pullPolicy | quote }} + command: + - /scripts/auto-discovery.sh + # We need the service account token for contacting the k8s API + automountServiceAccountToken: true + env: + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SHARED_FILE + value: "/shared/info.txt" + {{- if .Values.externalAccess.autoDiscovery.resources }} + resources: {{- toYaml .Values.externalAccess.autoDiscovery.resources | nindent 12 }} + {{- else if ne .Values.externalAccess.autoDiscovery.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.externalAccess.autoDiscovery.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: shared + mountPath: /shared + - name: scripts + mountPath: /scripts/auto-discovery.sh + subPath: auto-discovery.sh + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.hidden.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.hidden.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.hidden.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.command "context" $) | nindent 12 }} + {{- else }} + command: + - /scripts/setup-hidden.sh + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.hidden.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.hidden.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: SHARED_FILE + value: "/shared/info.txt" + {{- end }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_SERVICE_NAME + value: "{{ include "mongodb.service.nameOverride" . }}" + - name: K8S_HIDDEN_NODE_SERVICE_NAME + value: "{{ include "mongodb.fullname" . }}-hidden-headless" + - name: MONGODB_REPLICA_SET_MODE + value: "hidden" + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ printf "%s-0.$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.%s" (include "mongodb.fullname" .) .Values.clusterDomain }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + {{- if and .Values.replicaSetHostnames (not .Values.externalAccess.hidden.enabled) }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).$(K8S_HIDDEN_NODE_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + {{- end }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.hidden.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.hidden.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.hidden.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.hidden.extraEnvVarsCM .Values.hidden.extraEnvVarsSecret }} + envFrom: + {{- if .Values.hidden.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.hidden.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.hidden.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.hidden.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.hidden.containerPorts.mongodb }} + name: mongodb + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.hidden.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- if .Values.hidden.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- if .Values.hidden.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.hidden.resources }} + resources: {{- toYaml .Values.hidden.resources | nindent 12 }} + {{- else if ne .Values.hidden.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.hidden.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: datadir + mountPath: {{ .Values.hidden.persistence.mountPath }} + subPath: {{ .Values.hidden.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.hidden.configuration .Values.hidden.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + - name: scripts + mountPath: /scripts/setup-hidden.sh + subPath: setup-hidden.sh + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: shared + mountPath: /shared + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + {{- if .Values.hidden.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + - name: empty-dir + mountPath: /opt/bitnami/redis-cluster/tmp + subPath: app-tmp-dir + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9216 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.hidden.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0555 + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.hidden.configuration .Values.hidden.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.hidden.configmapName" . }} + {{- end }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: shared + emptyDir: {} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0755 + {{- if .Values.hidden.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + {{- range $index, $secret := .Values.tls.hidden.existingSecrets }} + - name: mongodb-certs-{{ $index }} + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" $secret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- if not .Values.hidden.persistence.enabled }} + - name: datadir + {{- if .Values.hidden.persistence.medium }} + emptyDir: + medium: {{ .Values.hidden.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + volumeClaimTemplates: + - metadata: + name: datadir + {{- if .Values.hidden.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.hidden.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.hidden.persistence.size | quote }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.requests }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.requests "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.hidden.persistence "global" .Values.global) }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/initialization-configmap.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/initialization-configmap.yaml new file mode 100644 index 0000000..7086e0b --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/initialization-configmap.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.initdbScripts (not .Values.initdbScriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- include "common.tplvalues.render" (dict "value" .Values.initdbScripts "context" .) | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/metrics-svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/metrics-svc.yaml new file mode 100644 index 0000000..f21401e --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/metrics-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + ports: + - port: {{ .Values.metrics.service.ports.metrics }} + targetPort: metrics + protocol: TCP + name: http-metrics + {{- if .Values.metrics.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/networkpolicy.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/networkpolicy.yaml new file mode 100644 index 0000000..aa99058 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/networkpolicy.yaml @@ -0,0 +1,98 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotation }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + policyTypes: + - Ingress + - Egress + {{- if .Values.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow connection to other cluster pods + - ports: + - port: {{ .Values.containerPorts.mongodb }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if (and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled) }} + {{- $kubernetesEndpoints := lookup "v1" "Endpoints" (include "common.names.namespace" .) "kubernetes" }} + {{- range $kubernetesEndpoints.subsets }} + # Allow connection to API server, required by auto-discovery containers + - ports: + {{- range .ports }} + - port: {{ .port }} + {{- end }} + to: + {{- range .addresses }} + - ipBlock: + cidr: {{ printf "%s/32" .ip }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rts.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.containerPorts.mongodb }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPort }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: mongodb + {{- $ingressNSMatchLabels := coalesce .Values.networkPolicy.ingressNSMatchLabels .Values.networkPolicy.namespaceSelector }} + {{- if $ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: + {{- range $key, $value := $ingressNSMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- $ingressNSPodMatchLabels := coalesce .Values.networkPolicy.ingressNSPodMatchLabels .Values.networkPolicy.podSelector }} + {{- if $ingressNSPodMatchLabels }} + podSelector: + matchLabels: + {{- range $key, $value := $ingressNSPodMatchLabels }} + {{ $key | quote }}: {{ $value | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- $extraIngress := coalesce .Values.networkPolicy.extraIngress .Values.networkPolicy.customRules }} + {{- if $extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" $extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/prometheusrule.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/prometheusrule.yaml new file mode 100644 index 0000000..00df349 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.prometheusRule.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "mongodb.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/psp.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/psp.yaml new file mode 100644 index 0000000..61c452b --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/psp.yaml @@ -0,0 +1,51 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: +{{- if .Values.podSecurityPolicy.spec }} +{{ include "common.tplvalues.render" ( dict "value" .Values.podSecurityPolicy.spec "context" $ ) | nindent 2 }} +{{- else }} + allowPrivilegeEscalation: {{ .Values.podSecurityPolicy.allowPrivilegeEscalation }} + fsGroup: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.podSecurityContext.fsGroup }} + max: {{ .Values.podSecurityContext.fsGroup }} + hostIPC: false + hostNetwork: false + hostPID: false + privileged: {{ .Values.podSecurityPolicy.privileged }} + readOnlyRootFilesystem: false + requiredDropCapabilities: + - ALL + runAsUser: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.containerSecurityContext.runAsUser }} + max: {{ .Values.containerSecurityContext.runAsUser }} + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.containerSecurityContext.runAsUser }} + max: {{ .Values.containerSecurityContext.runAsUser }} + volumes: + - 'configMap' + - 'secret' + - 'emptyDir' + - 'persistentVolumeClaim' +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/external-access-svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/external-access-svc.yaml new file mode 100644 index 0000000..3bc9900 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/external-access-svc.yaml @@ -0,0 +1,69 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (not (eq .Values.externalAccess.service.type "ClusterIP")) }} +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%d-external" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + pod: {{ $targetPod }} + {{- if or $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ $root.Values.externalAccess.service.type }} + {{- if eq $root.Values.externalAccess.service.type "LoadBalancer" }} + {{- if not (empty $root.Values.externalAccess.service.loadBalancerIPs) }} + loadBalancerIP: {{ index $root.Values.externalAccess.service.loadBalancerIPs $i }} + {{- end }} + {{- if and (eq $root.Values.externalAccess.service.type "LoadBalancer") $root.Values.externalAccess.service.loadBalancerClass }} + loadBalancerClass: {{ $root.Values.externalAccess.service.loadBalancerClass }} + {{- end }} + {{- if $root.Values.externalAccess.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + allocateLoadBalancerNodePorts: {{ $root.Values.externalAccess.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if (or (eq $root.Values.externalAccess.service.type "LoadBalancer") (eq $root.Values.externalAccess.service.type "NodePort")) }} + externalTrafficPolicy: {{ $root.Values.externalAccess.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if $root.Values.externalAccess.service.sessionAffinity }} + sessionAffinity: {{ $root.Values.externalAccess.service.sessionAffinity }} + {{- end }} + {{- if $root.Values.externalAccess.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + publishNotReadyAddresses: true + ports: + - name: {{ $root.Values.externalAccess.service.portName | quote }} + port: {{ $root.Values.externalAccess.service.ports.mongodb }} + {{- if not (empty $root.Values.externalAccess.service.nodePorts) }} + {{- $nodePort := index $root.Values.externalAccess.service.nodePorts $i }} + nodePort: {{ $nodePort }} + {{- else }} + nodePort: null + {{- end }} + targetPort: mongodb + {{- if $root.Values.externalAccess.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/headless-svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/headless-svc.yaml new file mode 100644 index 0000000..bf7a3d9 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/headless-svc.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.commonAnnotations .Values.service.headless.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/pdb.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/pdb.yaml new file mode 100644 index 0000000..5bbd310 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if .Values.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/scripts-configmap.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/scripts-configmap.yaml new file mode 100644 index 0000000..00b2502 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/scripts-configmap.yaml @@ -0,0 +1,317 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- if and .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + auto-discovery.sh: |- + #!/bin/bash + + SVC_NAME="${MY_POD_NAME}-external" + + # Auxiliary functions + retry_while() { + local -r cmd="${1:?cmd is missing}" + local -r retries="${2:-12}" + local -r sleep_time="${3:-5}" + local return_value=1 + + read -r -a command <<< "$cmd" + for ((i = 1 ; i <= retries ; i+=1 )); do + "${command[@]}" && return_value=0 && break + sleep "$sleep_time" + done + return $return_value + } + k8s_svc_lb_ip() { + local namespace=${1:?namespace is missing} + local service=${2:?service is missing} + local service_ip=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].ip}") + local service_hostname=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].hostname}") + + if [[ -n ${service_ip} ]]; then + echo "${service_ip}" + else + echo "${service_hostname}" + fi + } + k8s_svc_lb_ip_ready() { + local namespace=${1:?namespace is missing} + local service=${2:?service is missing} + [[ -n "$(k8s_svc_lb_ip "$namespace" "$service")" ]] + } + # Wait until LoadBalancer IP is ready + retry_while "k8s_svc_lb_ip_ready {{ $releaseNamespace }} $SVC_NAME" || exit 1 + # Obtain LoadBalancer external IP + k8s_svc_lb_ip "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE" + {{- end }} + setup.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/mongodb-env.sh + . /opt/bitnami/scripts/libfs.sh + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libvalidations.sh + + {{- if .Values.externalAccess.enabled }} + {{- if eq .Values.externalAccess.service.type "LoadBalancer" }} + {{- if .Values.externalAccess.autoDiscovery.enabled }} + export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})" + {{- else }} + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ .Values.externalAccess.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + {{- end }} + {{- else if eq .Values.externalAccess.service.type "NodePort" }} + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + fi + {{- if .Values.externalAccess.service.domain }} + export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.service.domain }} + {{- else }} + export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.replicaSetConfigurationSettings.enabled }} + # placed here before root password env is overwritten + # makes no assumption about starting state + # ensures that any stepDown or non-default starting state is handled + /scripts/replicaSetConfigurationSettings.sh & + {{- end }} + + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER="$MONGODB_PORT_NUMBER" + fi + + info "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME" + info "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER" + + # Check for existing replica set in case there is no data in the PVC + # This is for cases where the PVC is lost or for MongoDB caches without + # persistence + current_primary="" + if is_dir_empty "${MONGODB_DATA_DIR}/db"; then + info "Data dir empty, checking if the replica set already exists" + {{- $replicaCount := int .Values.replicaCount }} + {{- $portNumber := int .Values.service.ports.mongodb }} + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} + {{- $mongoList := list }} + {{- range $e, $i := until $replicaCount }} + {{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $portNumber) }} + {{- end }} + + {{- if .Values.externalAccess.externalMaster.enabled }} + current_primary={{ printf "%s:%d" (.Values.externalAccess.externalMaster.host) ( int .Values.externalAccess.externalMaster.port) }} + {{- else }} + current_primary=$(mongosh admin --host "{{ join "," $mongoList }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }}{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} --eval 'db.runCommand("ismaster")' | awk -F\' '/primary/ {print $2}') + {{- end }} + if ! is_empty_value "$current_primary"; then + info "Detected existing primary: ${current_primary}" + fi + fi + + if ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" == "$current_primary" ]]; then + info "Advertised name matches current primary, configuring node as a primary" + export MONGODB_REPLICA_SET_MODE="primary" + elif ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" != "$current_primary" ]]; then + info "Current primary is different from this node. Configuring the node as replica of ${current_primary}" + export MONGODB_REPLICA_SET_MODE="secondary" + export MONGODB_INITIAL_PRIMARY_HOST="${current_primary%:*}" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="${current_primary#*:}" + export MONGODB_SET_SECONDARY_OK="yes" + elif [[ "$MY_POD_NAME" = "{{ $fullname }}-0" ]]; then + info "Pod name matches initial primary pod name, configuring node as a primary" + export MONGODB_REPLICA_SET_MODE="primary" + else + info "Pod name doesn't match initial primary pod name, configuring node as a secondary" + export MONGODB_REPLICA_SET_MODE="secondary" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER" + fi + + if [[ "$MONGODB_REPLICA_SET_MODE" == "secondary" ]]; then + export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER" + export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD" + export MONGODB_ROOT_PASSWORD="" + export MONGODB_EXTRA_USERNAMES="" + export MONGODB_EXTRA_DATABASES="" + export MONGODB_EXTRA_PASSWORDS="" + export MONGODB_ROOT_PASSWORD_FILE="" + export MONGODB_EXTRA_USERNAMES_FILE="" + export MONGODB_EXTRA_DATABASES_FILE="" + export MONGODB_EXTRA_PASSWORDS_FILE="" + fi + + exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + setup-hidden.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/mongodb-env.sh + + {{- if .Values.externalAccess.hidden.enabled }} + {{- if eq .Values.externalAccess.hidden.service.type "LoadBalancer" }} + {{- if .Values.externalAccess.autoDiscovery.enabled }} + export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})" + {{- else }} + ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}" + export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ .Values.externalAccess.hidden.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + {{- end }} + {{- else if eq .Values.externalAccess.hidden.service.type "NodePort" }} + ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}" + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + fi + {{- if .Values.externalAccess.hidden.service.domain }} + export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.hidden.service.domain }} + {{- else }} + export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.replicaSetConfigurationSettings.enabled }} + # placed here before root password env is overwritten + # makes no assumption about starting state + # ensures that any stepDown or non-default starting state is handled + /scripts/replicaSetConfigurationSettings.sh & + {{- end }} + + echo "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME" + echo "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER" + echo "Configuring node as a hidden node" + export MONGODB_REPLICA_SET_MODE="hidden" + export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER" + export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER" + export MONGODB_ROOT_PASSWORD="" + export MONGODB_EXTRA_USERNAMES="" + export MONGODB_EXTRA_DATABASES="" + export MONGODB_EXTRA_PASSWORDS="" + export MONGODB_ROOT_PASSWORD_FILE="" + export MONGODB_EXTRA_USERNAMES_FILE="" + export MONGODB_EXTRA_DATABASES_FILE="" + export MONGODB_EXTRA_PASSWORDS_FILE="" + exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + {{- if .Values.replicaSetConfigurationSettings.enabled }} + replicaSetConfigurationSettings.sh: |- + #!/bin/bash + # This script to be called when pod starts. + # This script sets rs settings which can not be applied via conf file + + function logger () + #$1 is the line to be logged + { + echo "replicaSetConfigurationSettings.sh -- ${1}" >&1 + } + + SLEEP_PERIOD=10 + + {{- if and .Values.auth.enabled .Values.auth.rootPassword }} + usernameAndPassword="{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} -u ${MONGODB_ROOT_USER} -p ${MONGODB_ROOT_PASSWORD}" + {{- else }} + usernameAndPassword="" + {{- end }} + + # load Values.replicaSetConfigurationSettings.configuration into associtive array which makes iterating and string manipulation easy + declare -A desiredRsConf + {{ range $setting, $value := .Values.replicaSetConfigurationSettings.configuration -}} + {{ printf "desiredRsConf[%s]='%v'" $setting $value }} + {{ end }} + + rsConfWriteAttempts=0 + rs_conf_configured_ok=unknown + + while [[ "${rs_conf_configured_ok}" != "true" ]]; do + + # give the rs setup a chance to succeed before attempting to read or configure + sleep ${SLEEP_PERIOD} + + counter=0 + while ! mongosh ${usernameAndPassword} --eval 'rs.conf()'; do + counter=$((${counter} +1)) + logger "not yet able to read rs.conf settings from the currently running rs (after ${counter} attempts)" + sleep ${SLEEP_PERIOD} + done + counter=$((${counter} +1)) + logger "rs.conf settings have been read from the currently running rs (after ${counter} attempts)" + + # read rs.conf again and store it. settings format is '"" : ,' + currentRsConf=$(mongosh ${usernameAndPassword} --eval 'rs.conf()') + + desiredEqualsactual=unknown + settingsToConfigure="" + for key in ${!desiredRsConf[@]}; do + value=${desiredRsConf[$key]} + if ! $(echo "\"${currentRsConf}"\" | grep -q -e "${key}: ${value},"); then + if [[ $key =~ ^members\[[0-9]+\]\..+ ]]; then + memberIndex=$(echo $key | grep -o -E '[0-9]+') + nodeConfigKey=${key#*.} + settingsToConfigure="${settingsToConfigure}cfg.members[${memberIndex}].${nodeConfigKey} = ${value}; " + else + # General rs settings + settingsToConfigure="${settingsToConfigure}cfg.settings.${key} = ${value}; " + fi + desiredEqualsactual=false + else + logger "rs conf: ${key} is already at desired value: ${value}" + fi + done + + if [[ "${desiredEqualsactual}" != "false" ]]; then + logger "replicaSetConfigurationSettings match the settings of the currently running rs" + desiredEqualsactual=true + rs_conf_configured_ok=true + logger "Current settings match desired settings (There have been ${rsConfWriteAttempts} attempts to write to mongoDB rs configuration)" + exit + fi + + # apply the settings only if this member is currently the mongo replicaset PRIMARY + # it might take a little time before any pod is PRIMARY + isMaster=unknown + if ! mongosh ${usernameAndPassword} --eval 'rs.isMaster()' | grep -q "ismaster: true"; then + isMaster=false + logger "This node is not yet PRIMARY - replicaSetConfigurationSettings will only be set on the member that is currently PRIMARY" + else + isMaster=true + logger "This node is PRIMARY" + fi + + if [[ "${isMaster}" == "true" ]]; then + logger "This node is currently PRIMARY - will apply rs.conf settings" + + # avoiding tricky string substitution with single quotes by making the eval string a set of vars + rsconf="cfg = rs.conf();" + rsreconf="rs.reconfig(cfg);" + rsCommand="${rsconf} ${settingsToConfigure} ${rsreconf}" + + mongosh ${usernameAndPassword} --eval "${rsCommand}" + if [ $? -ne 0 ]; then + logger "Failed to apply mongodb cfg.settings configuration" + else + logger "mongodb replicaset cfg.settings configuration applied" + logger "Will check rs conf" + # don't exit just yet - the settings will be checked in the next loop + fi + rsConfWriteAttempts=$((${rsConfWriteAttempts} + 1 )) + fi + done + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/statefulset.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/statefulset.yaml new file mode 100644 index 0000000..f90bd16 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/statefulset.yaml @@ -0,0 +1,606 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +{{- $replicaCount := int .Values.replicaCount }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- if not (and .Values.externalAccess.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.service.type "LoadBalancer")) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.service.nameOverride" . }} + podManagementPolicy: {{ .Values.podManagementPolicy }} + replicas: {{ .Values.replicaCount }} + {{- if .Values.updateStrategy }} + updateStrategy: {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: mongodb + {{- if or (include "mongodb.createConfigmap" .) .Values.podAnnotations }} + annotations: + {{- if (include "mongodb.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- if or .Values.initContainers (and .Values.volumePermissions.enabled .Values.persistence.enabled) (and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled) .Values.tls.enabled }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + - name: volume-permissions + image: {{ include "mongodb.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + find {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: datadir + mountPath: {{ .Values.persistence.mountPath }} + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + {{- range $index, $_ := .Values.tls.replicaset.existingSecrets }} + - name: mongodb-certs-{{ $index }} + mountPath: /certs-{{ $index }} + {{- end }} + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if .Values.tls.extraDnsNames }} + - -n {{ join "," .Values.tls.extraDnsNames }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- toYaml .Values.tls.resources | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: auto-discovery + image: {{ include "mongodb.externalAccess.autoDiscovery.image" . }} + imagePullPolicy: {{ .Values.externalAccess.autoDiscovery.image.pullPolicy | quote }} + # We need the service account token for contacting the k8s API + automountServiceAccountToken: true + command: + - /scripts/auto-discovery.sh + env: + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SHARED_FILE + value: "/shared/info.txt" + {{- if .Values.externalAccess.autoDiscovery.resources }} + resources: {{- toYaml .Values.externalAccess.autoDiscovery.resources | nindent 12 }} + {{- else if ne .Values.externalAccess.autoDiscovery.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.externalAccess.autoDiscovery.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: shared + mountPath: /shared + - name: scripts + mountPath: /scripts/auto-discovery.sh + subPath: auto-discovery.sh + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- else }} + command: + - /scripts/setup.sh + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: SHARED_FILE + value: "/shared/info.txt" + {{- end }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: K8S_SERVICE_NAME + value: "{{ include "mongodb.service.nameOverride" . }}" + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ printf "%s-0.$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.%s" (include "mongodb.fullname" .) .Values.clusterDomain }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + {{- if and .Values.replicaSetHostnames (not .Values.externalAccess.enabled) }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + {{- end }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - name: mongodb + containerPort: {{ .Values.containerPorts.mongodb }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: datadir + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + - name: scripts + mountPath: /scripts/setup.sh + subPath: setup.sh + {{ if .Values.replicaSetConfigurationSettings.enabled }} + - name: scripts + mountPath: /scripts/replicaSetConfigurationSettings.sh + subPath: replicaSetConfigurationSettings.sh + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: shared + mountPath: /shared + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --web.listen-address ":{{ .Values.metrics.containerPort }}" --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPort }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.configmapName" . }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: shared + emptyDir: {} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0755 + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + {{- range $index, $secret := .Values.tls.replicaset.existingSecrets }} + - name: mongodb-certs-{{ $index }} + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" $secret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: datadir + {{- if .Values.persistence.medium }} + emptyDir: + medium: {{ .Values.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: datadir + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.volumeClaimTemplates.requests }} + {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.requests "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.persistence.volumeClaimTemplates.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/svc.yaml new file mode 100644 index 0000000..d955043 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/replicaset/svc.yaml @@ -0,0 +1,41 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "ClusterIP") }} + +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%d" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or $root.Values.service.annotations $root.Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.service.annotations $root.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - name: {{ $root.Values.service.portName | quote }} + port: {{ $root.Values.service.ports.mongodb }} + targetPort: mongodb + {{- if $root.Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/role.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/role.yaml new file mode 100644 index 0000000..b37d192 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/role.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch +{{- if .Values.rbac.rules }} +{{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} +{{- end -}} +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} + - apiGroups: ['{{ template "podSecurityPolicy.apiGroup" . }}'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ include "mongodb.fullname" . }}] +{{- end -}} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/rolebinding.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/rolebinding.yaml new file mode 100644 index 0000000..c6a76e6 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/rolebinding.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +roleRef: + kind: Role + name: {{ include "mongodb.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ include "mongodb.serviceAccountName" . }} + namespace: {{ include "mongodb.namespace" . | quote }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/secrets-ca.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/secrets-ca.yaml new file mode 100644 index 0000000..e1387ae --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/secrets-ca.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.createTlsSecret" .) }} +{{- $secretName := printf "%s" (include "mongodb.tlsSecretName" .) }} +{{- $fullname := include "mongodb.fullname" . }} +{{- $releaseNamespace := .Release.Namespace }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $cn := printf "%s.%s.svc.%s" $fullname .Release.Namespace $clusterDomain }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ template "mongodb.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if or .Values.tls.caCert .Values.tls.caKey (not .Values.tls.autoGenerated) }} + {{- $ca := buildCustomCert (required "A valid .Values.tls.caCert is required!" .Values.tls.caCert) (required "A valid .Values.tls.caKey is required!" .Values.tls.caKey) }} + mongodb-ca-cert: {{ b64enc $ca.Cert }} + mongodb-ca-key: {{ b64enc $ca.Key }} + {{- else }} + {{- $ca := genCA "myMongo-ca" 3650 }} + mongodb-ca-cert: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "mongodb-ca-cert" "defaultValue" $ca.Cert "context" $) }} + mongodb-ca-key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "mongodb-ca-key" "defaultValue" $ca.Key "context" $) }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/secrets.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/secrets.yaml new file mode 100644 index 0000000..004f2f3 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/secrets.yaml @@ -0,0 +1,128 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.auth.enabled }} +{{- $replicaCount := int .Values.replicaCount }} +{{- $port := .Values.service.ports.mongodb }} +{{- $host := include "mongodb.service.nameOverride" . }} +{{- $hostForURI := printf "%s:%s" (include "mongodb.service.nameOverride" .) (print $port) }} +{{- if (eq .Values.architecture "replicaset") }} + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $mongoList := list }} + {{- $mongoOnlyHostList := list }} + {{- range $e, $i := until $replicaCount }} + {{- $mongoOnlyHostList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s" $fullname $i $fullname $releaseNamespace $clusterDomain) }} + {{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%s" $fullname $i $fullname $releaseNamespace $clusterDomain (print $port)) }} + {{- end }} + {{- $host = (join "," $mongoOnlyHostList) }} + {{- $hostForURI = (join "," $mongoList) }} +{{- end }} + +{{/* Root user section. */}} +{{- $rootPassword := include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.secretName" .) "key" "mongodb-root-password" "providedValues" (list "auth.rootPassword" ) "context" $) | trimAll "\"" | b64dec }} + +{{/* Custom user section. This chart allows creating multiple users */}} +{{- $customUsers := include "mongodb.customUsers" . }} +{{- $customDatabases := include "mongodb.customDatabases" . }} +{{- $customPasswords := include "mongodb.customPasswords" . }} +{{- $passwords := "" }} +{{- $passwordList := list -}} +{{- $customUsersList := list }} +{{- $customDatabasesList := list }} +{{- $customPasswordsList := list }} +{{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} +{{- $customUsersList = splitList "," $customUsers }} +{{- $customDatabasesList = splitList "," $customDatabases }} +{{- if not (empty $customPasswords) }} +{{- $passwordList = $customPasswords }} +{{- $customPasswordsList = splitList "," $customPasswords }} +{{- else }} +{{- range $customUsersList }} +{{- $customPasswordsList = append $customPasswordsList (randAlphaNum 10) }} +{{- end -}} +{{- $passwordList = (join "," $customPasswordsList) }} +{{- end }} +{{- $passwords = include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.secretName" .) "key" "mongodb-passwords" "providedValues" (list "mongodbPasswords") "context" (set (deepCopy $) "Values" (dict "mongodbPasswords" $passwordList))) | trimAll "\"" | b64dec }} +{{- end }} + +{{- if (include "mongodb.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ template "mongodb.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + mongodb-root-password: {{ print $rootPassword | b64enc | quote }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + mongodb-passwords: {{ print $passwords | b64enc | quote }} + {{- end }} + {{- if .Values.metrics.username }} + mongodb-metrics-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.fullname" .) "key" "mongodb-metrics-password" "providedValues" (list "metrics.password" ) "context" $) }} + {{- end }} + {{- if eq .Values.architecture "replicaset" }} + mongodb-replica-set-key: {{ include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.fullname" .) "key" "mongodb-replica-set-key" "providedValues" (list "auth.replicaSetKey" ) "context" $) }} + {{- end }} +{{- end }} +{{- if .Values.serviceBindings.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind-root + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mongodb +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mongodb" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print .Values.auth.rootUser | b64enc | quote }} + password: {{ print $rootPassword | b64enc | quote }} + database: {{ print "admin" | b64enc | quote }} + uri: {{ printf "mongodb://%s:%s@%s/admin" .Values.auth.rootUser $rootPassword $hostForURI | b64enc | quote }} +{{- range $e, $i := until (len $customUsersList) }} +--- +{{- $currentSecret := printf "%s-svcbind-%d" (include "common.names.fullname" $) $i }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $currentSecret }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mongodb +data: + {{- $currentUser := index $customUsersList $i }} + {{- $currentDatabase := last $customDatabasesList }} + {{- if gt (len $customDatabasesList) $i }} + {{- $currentDatabase = index $customDatabasesList $i }} + {{- end }} + {{- $currentProvidedPassword := index $customPasswordsList $i }} + {{- $currentPassword := include "common.secrets.lookup" (dict "secret" $currentSecret "key" "password" "defaultValue" $currentProvidedPassword "context" $) | b64dec }} + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mongodb" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print $currentUser | b64enc | quote }} + password: {{ print $currentPassword | b64enc | quote }} + database: {{ print $currentDatabase | b64enc | quote }} + uri: {{ printf "mongodb://%s:%s@%s/%s" $currentUser $currentPassword $hostForURI $currentDatabase | b64enc | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/serviceaccount.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/serviceaccount.yaml new file mode 100644 index 0000000..0154a99 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongodb.serviceAccountName" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +secrets: + - name: {{ include "mongodb.secretName" . }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/servicemonitor.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/servicemonitor.yaml new file mode 100644 index 0000000..8273e4b --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/servicemonitor.yaml @@ -0,0 +1,48 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.serviceMonitor.namespace" . }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: metrics + endpoints: + - port: http-metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + namespaceSelector: + matchNames: + - "{{ include "mongodb.namespace" . }}" +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/dep-sts.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/dep-sts.yaml new file mode 100644 index 0000000..cbe9917 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/dep-sts.yaml @@ -0,0 +1,520 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not (eq .Values.architecture "replicaset") }} +apiVersion: {{ if .Values.useStatefulSet }}{{ include "common.capabilities.statefulset.apiVersion" . }}{{- else }}{{ include "common.capabilities.deployment.apiVersion" . }}{{- end }} +kind: {{ if .Values.useStatefulSet }}StatefulSet{{- else }}Deployment{{- end }} +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ gt (.Values.replicaCount | int) 1 | ternary 1 .Values.replicaCount }} + {{- if .Values.useStatefulSet }} + serviceName: {{ include "mongodb.service.nameOverride" . }} + {{- end }} + {{- if .Values.updateStrategy}} + {{- if .Values.useStatefulSet }} + updateStrategy: + {{- else }} + strategy: + {{- end }} + {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end}} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: mongodb + {{- if or (include "mongodb.createConfigmap" .) .Values.podAnnotations }} + annotations: + {{- if (include "mongodb.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- if or .Values.initContainers (and .Values.volumePermissions.enabled .Values.persistence.enabled) .Values.tls.enabled }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + - name: volume-permissions + image: {{ include "mongodb.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + find {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if .Values.tls.extraDnsNames }} + - -n {{ join "," .Values.tls.extraDnsNames }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- toYaml .Values.tls.resources | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - name: mongodb + containerPort: {{ .Values.containerPorts.mongodb }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --web.listen-address ":{{ .Values.metrics.containerPort }}" --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPort }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.configmapName" . }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.standalone.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: {{ .Values.persistence.name | default "datadir" }} + {{- if .Values.persistence.medium }} + emptyDir: + medium: {{ .Values.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.persistence.existingClaim }} + - name: {{ .Values.persistence.name | default "datadir" }} + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }} + {{- else if not .Values.useStatefulSet }} + - name: {{ .Values.persistence.name | default "datadir" }} + persistentVolumeClaim: + claimName: {{ template "mongodb.fullname" . }} + {{- else }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: {{ .Values.persistence.name | default "datadir" }} + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/pvc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/pvc.yaml new file mode 100644 index 0000000..d59bad9 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/pvc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (not (eq .Values.architecture "replicaset")) (not .Values.useStatefulSet) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + annotations: + {{- if .Values.persistence.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.persistence.resourcePolicy | quote }} + {{- end }} + {{- if or .Values.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/svc.yaml b/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/svc.yaml new file mode 100644 index 0000000..5d0d03f --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/templates/standalone/svc.yaml @@ -0,0 +1,62 @@ +{{- /* +Copyright VMware, Inc. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not (eq .Values.architecture "replicaset") }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.service.loadBalancerClass }} + {{- end }} + {{- if .Values.service.externalIPs }} + externalIPs: {{ toYaml .Values.service.externalIPs | nindent 4 }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if (eq .Values.service.type "LoadBalancer") }} + allocateLoadBalancerNodePorts: {{ .Values.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- if (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.mongodb }} + targetPort: mongodb + {{- if and (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) .Values.service.nodePorts.mongodb }} + nodePort: {{ .Values.service.nodePorts.mongodb }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/values.schema.json b/utils/assets/charts/mongo-express/charts/mongodb/values.schema.json new file mode 100644 index 0000000..3eb6a64 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/values.schema.json @@ -0,0 +1,232 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "MongoDB® architecture", + "form": true, + "description": "Allowed values: `standalone` or `replicaset`" + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Authentication", + "form": true + }, + "rootUser": { + "type": "string", + "title": "MongoDB® admin user", + "form": true, + "description": "Name of the admin user. Default is root" + }, + "rootPassword": { + "type": "string", + "title": "MongoDB® admin password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + }, + "database": { + "type": "string", + "title": "MongoDB® custom database", + "description": "Name of the custom database to be created during the 1st initialization of MongoDB®", + "form": true + }, + "username": { + "type": "string", + "title": "MongoDB® custom user", + "description": "Name of the custom user to be created during the 1st initialization of MongoDB®. This user only has permissions on the MongoDB® custom database", + "form": true + }, + "password": { + "type": "string", + "title": "Password for MongoDB® custom user", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + }, + "replicaSetKey": { + "type": "string", + "title": "Key used for replica set authentication", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of MongoDB® replicas", + "hidden": { + "value": "standalone", + "path": "architecture" + } + }, + "configuration": { + "type": "string", + "title": "MongoDB® Custom Configuration", + "form": true, + "render": "textArea" + }, + "arbiter": { + "type": "object", + "title": "Arbiter configuration", + "form": true, + "properties": { + "configuration": { + "type": "string", + "title": "Arbiter Custom Configuration", + "form": true, + "render": "textArea", + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "networkPolicy": { + "type": "object", + "title": "Network policy configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable network policy", + "description": "Enable network policy using Kubernetes native NP", + "hidden": { + "value": false, + "path": "networkPolicy/enabled" + } + }, + "ingress": { + "type": "object", + "properties": { + "namespaceSelector": { + "type": "object", + "title": "Namespace selector label that is allowed to access this instance", + "hidden": { + "value": {}, + "path": "networkPolicy/ingress/namespaceSelector" + } + }, + "podSelector": { + "type": "object", + "title": "Pod selector label that is allowed to access this instance", + "hidden": { + "value": {}, + "path": "networkPolicy/ingress/podSelector" + } + }, + "customRules": { + "type": "array", + "title": "Custom rules for ingress network policy", + "hidden": { + "value": [], + "path": "networkPolicy/ingress/customRules" + } + } + } + }, + "egress": { + "type": "object", + "properties": { + "customRules": { + "type": "array", + "title": "Custom rules for egress network policy", + "hidden": { + "value": [], + "path": "networkPolicy/egress/customRules" + } + } + } + } + } + }, + "persistence": { + "type": "object", + "title": "Persistence configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "persistence/enabled" + } + } + } + }, + "volumePermissions": { + "type": "object", + "hidden": { + "value": false, + "path": "persistence/enabled" + }, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus metrics exporter", + "description": "Create a side-car container to expose Prometheus metrics", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/utils/assets/charts/mongo-express/charts/mongodb/values.yaml b/utils/assets/charts/mongo-express/charts/mongodb/values.yaml new file mode 100644 index 0000000..ea8ecf5 --- /dev/null +++ b/utils/assets/charts/mongo-express/charts/mongodb/values.yaml @@ -0,0 +1,2426 @@ +# Copyright VMware, Inc. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## @param global.namespaceOverride Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + namespaceOverride: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto +## @section Common parameters +## + +## @param nameOverride String to partially override mongodb.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override mongodb.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param clusterDomain Default Kubernetes cluster domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## extraDeploy: +## This needs to be uncommented and added to 'extraDeploy' in order to use the replicaset 'mongo-labeler' sidecar +## for dynamically discovering the mongodb primary pod +## suggestion is to use a hard-coded and predictable TCP port for the primary mongodb pod (here is 30001, choose your own) +## - apiVersion: v1 +## kind: Service +## metadata: +## name: mongodb-primary +## namespace: the-mongodb-namespace +## labels: +## app.kubernetes.io/component: mongodb +## app.kubernetes.io/instance: mongodb +## app.kubernetes.io/managed-by: Helm +## app.kubernetes.io/name: mongodb +## spec: +## type: NodePort +## externalTrafficPolicy: Cluster +## ports: +## - name: mongodb +## port: 30001 +## nodePort: 30001 +## protocol: TCP +## targetPort: mongodb +## selector: +## app.kubernetes.io/component: mongodb +## app.kubernetes.io/instance: mongodb +## app.kubernetes.io/name: mongodb +## primary: "true" +## +extraDeploy: [] +## @param commonLabels Add labels to all the deployed resources (sub-charts are not considered). Evaluated as a template +## +commonLabels: {} +## @param commonAnnotations Common annotations to add to all Mongo resources (sub-charts are not considered). Evaluated as a template +## +commonAnnotations: {} +## @param topologyKey Override common lib default topology key. If empty - "kubernetes.io/hostname" is used +## i.e. topologyKey: topology.kubernetes.io/zone +## +topologyKey: "" +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false +## @param enableServiceLinks Whether information about services should be injected into pod's environment variable +## The environment variables injected by service links are not used, but can lead to slow boot times or slow running of the scripts when there are many services in the current namespace. +## If you experience slow pod startups or slow running of the scripts you probably want to set this to `false`. +## +enableServiceLinks: true +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity +## @section MongoDB(®) parameters +## + +## Bitnami MongoDB(®) image +## ref: https://hub.docker.com/r/bitnami/mongodb/tags/ +## @param image.registry [default: REGISTRY_NAME] MongoDB(®) image registry +## @param image.repository [default: REPOSITORY_NAME/mongodb] MongoDB(®) image registry +## @skip image.tag MongoDB(®) image tag (immutable tags are recommended) +## @param image.digest MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy MongoDB(®) image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Set to true if you would like to see extra information on logs +## +image: + registry: docker.io + repository: bitnami/mongodb + tag: 7.0.8-debian-12-r2 + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false +## @param schedulerName Name of the scheduler (other than default) to dispatch pods +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param architecture MongoDB(®) architecture (`standalone` or `replicaset`) +## +architecture: standalone +## @param useStatefulSet Set to true to use a StatefulSet instead of a Deployment (only when `architecture=standalone`) +## +useStatefulSet: false +## MongoDB(®) Authentication parameters +## +auth: + ## @param auth.enabled Enable authentication + ## ref: https://docs.mongodb.com/manual/tutorial/enable-authentication/ + ## + enabled: true + ## @param auth.rootUser MongoDB(®) root user + ## + rootUser: root + ## @param auth.rootPassword MongoDB(®) root password + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#setting-the-root-user-and-password-on-first-run + ## + rootPassword: "" + ## MongoDB(®) custom users and databases + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#creating-a-user-and-database-on-first-run + ## @param auth.usernames List of custom users to be created during the initialization + ## @param auth.passwords List of passwords for the custom users set at `auth.usernames` + ## @param auth.databases List of custom databases to be created during the initialization + ## + usernames: [] + passwords: [] + databases: [] + ## @param auth.username DEPRECATED: use `auth.usernames` instead + ## @param auth.password DEPRECATED: use `auth.passwords` instead + ## @param auth.database DEPRECATED: use `auth.databases` instead + ## + username: "" + password: "" + database: "" + ## @param auth.replicaSetKey Key used for authentication in the replicaset (only when `architecture=replicaset`) + ## + replicaSetKey: "" + ## @param auth.existingSecret Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) + ## NOTE: When it's set the previous parameters are ignored. + ## + existingSecret: "" +tls: + ## @param tls.enabled Enable MongoDB(®) TLS support between nodes in the cluster as well as between mongo clients and nodes + ## + enabled: false + mTLS: + ## @param tls.mTLS.enabled IF TLS support is enabled, require clients to provide certificates + enabled: true + ## @param tls.autoGenerated Generate a custom CA and self-signed certificates + ## + autoGenerated: true + ## @param tls.existingSecret Existing secret with TLS certificates (keys: `mongodb-ca-cert`, `mongodb-ca-key`) + ## NOTE: When it's set it will disable secret creation. + ## + existingSecret: "" + ## Add Custom CA certificate + ## @param tls.caCert Custom CA certificated (base64 encoded) + ## @param tls.caKey CA certificate private key (base64 encoded) + ## + caCert: "" + caKey: "" + ## @param tls.pemChainIncluded Flag to denote that the Certificate Authority (CA) certificates are bundled with the endpoint cert. + ## Certificates must be in proper order, where the top certificate is the leaf and the bottom certificate is the top-most intermediate CA. + ## + pemChainIncluded: false + standalone: + ## @param tls.standalone.existingSecret Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecret: "" + replicaset: + ## @param tls.replicaset.existingSecrets Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## existingSecrets: + ## - "mySecret-0" + ## - "mySecret-1" + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecrets: [] + hidden: + ## @param tls.hidden.existingSecrets Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## existingSecrets: + ## - "mySecret-0" + ## - "mySecret-1" + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecrets: [] + arbiter: + ## @param tls.arbiter.existingSecret Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecret: "" + ## Bitnami Nginx image + ## @param tls.image.registry [default: REGISTRY_NAME] Init container TLS certs setup image registry + ## @param tls.image.repository [default: REPOSITORY_NAME/nginx] Init container TLS certs setup image repository + ## @skip tls.image.tag Init container TLS certs setup image tag (immutable tags are recommended) + ## @param tls.image.digest Init container TLS certs setup image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param tls.image.pullPolicy Init container TLS certs setup image pull policy + ## @param tls.image.pullSecrets Init container TLS certs specify docker-registry secret names as an array + ## @param tls.extraDnsNames Add extra dns names to the CA, can solve x509 auth issue for pod clients + ## + image: + registry: docker.io + repository: bitnami/nginx + tag: 1.25.4-debian-12-r7 + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## e.g: + ## extraDnsNames + ## "DNS.6": "$my_host" + ## "DNS.7": "$test" + ## + extraDnsNames: [] + ## @param tls.mode Allows to set the tls mode which should be used when tls is enabled (options: `allowTLS`, `preferTLS`, `requireTLS`) + ## + mode: requireTLS + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param tls.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param tls.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init Container securityContext + ## ref: https://kubernetes.io/docs/concepts/security/pod-security-policy/ + ## @param tls.securityContext Init container generate-tls-cert Security context + ## + securityContext: {} + ## Example: + ## allowPrivilegeEscalation: false + ## capabilities: + ## drop: ["ALL"] + ## +## @param automountServiceAccountToken Mount Service Account token in pod +## +automountServiceAccountToken: false +## @param hostAliases Add deployment host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## @param replicaSetName Name of the replica set (only when `architecture=replicaset`) +## Ignored when mongodb.architecture=standalone +## +replicaSetName: rs0 +## @param replicaSetHostnames Enable DNS hostnames in the replicaset config (only when `architecture=replicaset`) +## Ignored when mongodb.architecture=standalone +## Ignored when externalAccess.enabled=true +## +replicaSetHostnames: true +## @param enableIPv6 Switch to enable/disable IPv6 on MongoDB(®) +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#enablingdisabling-ipv6 +## +enableIPv6: false +## @param directoryPerDB Switch to enable/disable DirectoryPerDB on MongoDB(®) +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#enablingdisabling-directoryperdb +## +directoryPerDB: false +## MongoDB(®) System Log configuration +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#configuring-system-log-verbosity-level +## @param systemLogVerbosity MongoDB(®) system log verbosity level +## @param disableSystemLog Switch to enable/disable MongoDB(®) system log +## +systemLogVerbosity: 0 +disableSystemLog: false +## @param disableJavascript Switch to enable/disable MongoDB(®) server-side JavaScript execution +## ref: https://docs.mongodb.com/manual/core/server-side-javascript/ +## +disableJavascript: false +## @param enableJournal Switch to enable/disable MongoDB(®) Journaling +## ref: https://docs.mongodb.com/manual/reference/configuration-options/#mongodb-setting-storage.journal.enabled +## +enableJournal: true +## @param configuration MongoDB(®) configuration file to be used for Primary and Secondary nodes +## For documentation of all options, see: http://docs.mongodb.org/manual/reference/configuration-options/ +## Example: +## configuration: |- +## # where and how to store data. +## storage: +## dbPath: /bitnami/mongodb/data/db +## journal: +## enabled: true +## directoryPerDB: false +## # where to write logging data +## systemLog: +## destination: file +## quiet: false +## logAppend: true +## logRotate: reopen +## path: /opt/bitnami/mongodb/logs/mongodb.log +## verbosity: 0 +## # network interfaces +## net: +## port: 27017 +## unixDomainSocket: +## enabled: true +## pathPrefix: /opt/bitnami/mongodb/tmp +## ipv6: false +## bindIpAll: true +## # replica set options +## #replication: +## #replSetName: replicaset +## #enableMajorityReadConcern: true +## # process management options +## processManagement: +## fork: false +## pidFilePath: /opt/bitnami/mongodb/tmp/mongodb.pid +## # set parameter options +## setParameter: +## enableLocalhostAuthBypass: true +## # security options +## security: +## authorization: disabled +## #keyFile: /opt/bitnami/mongodb/conf/keyfile +## +configuration: "" +## @section replicaSetConfigurationSettings settings applied during runtime (not via configuration file) +## If enabled, these are applied by a script which is called within setup.sh +## for documentation see https://docs.mongodb.com/manual/reference/replica-configuration/#replica-set-configuration-fields +## @param replicaSetConfigurationSettings.enabled Enable MongoDB(®) Switch to enable/disable configuring MongoDB(®) run time rs.conf settings +## @param replicaSetConfigurationSettings.configuration run-time rs.conf settings +## +replicaSetConfigurationSettings: + enabled: false + configuration: {} +## Custom configurations for individual replica set members. +## Use the prefix 'members[X].' to apply settings to the member X of the replica set. +## Example: 'members[0].priority: 3' sets the priority of the first replica set member to 3. +## The index X in 'members[X]' corresponds to the member's position in the replica set. +## members[0].priority: 3 +## chainingAllowed : false +## heartbeatTimeoutSecs : 10 +## heartbeatIntervalMillis : 2000 +## electionTimeoutMillis : 10000 +## catchUpTimeoutMillis : 30000 +## @param existingConfigmap Name of existing ConfigMap with MongoDB(®) configuration for Primary and Secondary nodes +## NOTE: When it's set the arbiter.configuration parameter is ignored +## +existingConfigmap: "" +## @param initdbScripts Dictionary of initdb scripts +## Specify dictionary of scripts to be run at first boot +## Example: +## initdbScripts: +## my_init_script.sh: | +## #!/bin/bash +## echo "Do something." +## +initdbScripts: {} +## @param initdbScriptsConfigMap Existing ConfigMap with custom initdb scripts +## +initdbScriptsConfigMap: "" +## Command and args for running the container (set to default if not set). Use array form +## @param command Override default container command (useful when using custom images) +## @param args Override default container args (useful when using custom images) +## +command: [] +args: [] +## @param extraFlags MongoDB(®) additional command line flags +## Example: +## extraFlags: +## - "--wiredTigerCacheSizeGB=2" +## +extraFlags: [] +## @param extraEnvVars Extra environment variables to add to MongoDB(®) pods +## E.g: +## extraEnvVars: +## - name: FOO +## value: BAR +## +extraEnvVars: [] +## @param extraEnvVarsCM Name of existing ConfigMap containing extra env vars +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) +## +extraEnvVarsSecret: "" +## @section MongoDB(®) statefulset parameters +## + +## @param annotations Additional labels to be added to the MongoDB(®) statefulset. Evaluated as a template +## +annotations: {} +## @param labels Annotations to be added to the MongoDB(®) statefulset. Evaluated as a template +## +labels: {} +## @param replicaCount Number of MongoDB(®) nodes +## When `mongodb.architecture=replicaset`, the number of replicas is taken in account +## When `mongodb.architecture=standalone`, the number of replicas can only be 0 or 1 (value higher then 1 will not be taken in account) +## +replicaCount: 2 +## @param updateStrategy.type Strategy to use to replace existing MongoDB(®) pods. When architecture=standalone and useStatefulSet=false, +## this parameter will be applied on a deployment object. In other case it will be applied on a statefulset object +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +## Example: +## updateStrategy: +## type: RollingUpdate +## rollingUpdate: +## maxSurge: 25% +## maxUnavailable: 25% +## +updateStrategy: + type: RollingUpdate +## @param podManagementPolicy Pod management policy for MongoDB(®) +## Should be initialized one by one when building the replicaset for the first time +## +podManagementPolicy: OrderedReady +## @param podAffinityPreset MongoDB(®) Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset MongoDB(®) Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft +## Node affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type MongoDB(®) Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key MongoDB(®) Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param nodeAffinityPreset.values MongoDB(®) Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] +## @param affinity MongoDB(®) Affinity for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param nodeSelector MongoDB(®) Node labels for pod assignment +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ +## +nodeSelector: {} +## @param tolerations MongoDB(®) Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## @param topologySpreadConstraints MongoDB(®) Spread Constraints for Pods +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## +topologySpreadConstraints: [] +## @param lifecycleHooks LifecycleHook for the MongoDB(®) container(s) to automate configuration before or after startup +## +lifecycleHooks: {} +## @param terminationGracePeriodSeconds MongoDB(®) Termination Grace Period +## +terminationGracePeriodSeconds: "" +## @param podLabels MongoDB(®) pod labels +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations MongoDB(®) Pod annotations +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param priorityClassName Name of the existing priority class to be used by MongoDB(®) pod(s) +## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +priorityClassName: "" +## @param runtimeClassName Name of the runtime class to be used by MongoDB(®) pod(s) +## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ +## +runtimeClassName: "" +## MongoDB(®) pods' Security Context. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enable MongoDB(®) pod(s)' Security Context +## @param podSecurityContext.fsGroupChangePolicy Set filesystem group change policy +## @param podSecurityContext.supplementalGroups Set filesystem extra groups +## @param podSecurityContext.fsGroup Group ID for the volumes of the MongoDB(®) pod(s) +## @param podSecurityContext.sysctls sysctl settings of the MongoDB(®) pod(s)' +## +podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] +## MongoDB(®) containers' Security Context (main and metrics container). +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## @param containerSecurityContext.enabled Enabled containers' Security Context +## @param containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container +## @param containerSecurityContext.runAsUser Set containers' Security Context runAsUser +## @param containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup +## @param containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot +## @param containerSecurityContext.privileged Set container's Security Context privileged +## @param containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem +## @param containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation +## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## +containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +## MongoDB(®) containers' resource requests and limits. +## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ +## We usually recommend not to specify default resources and to leave this as a conscious +## choice for the user. This also increases chances charts run on environments with little +## resources, such as Minikube. If you do want to specify resources, uncomment the following +## lines, adjust them as necessary, and remove the curly braces after 'resources:'. +## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). +## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 +## +resourcesPreset: "small" +## @param resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) +## Example: +## resources: +## requests: +## cpu: 2 +## memory: 512Mi +## limits: +## cpu: 3 +## memory: 1024Mi +## +resources: {} +## @param containerPorts.mongodb MongoDB(®) container port +## +containerPorts: + mongodb: 27017 +## MongoDB(®) pods' liveness probe. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 +## MongoDB(®) pods' readiness probe. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 +## Slow starting containers can be protected through startup probes +## Startup probes are available in Kubernetes version 1.16 and above +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + successThreshold: 1 + failureThreshold: 30 +## @param customLivenessProbe Override default liveness probe for MongoDB(®) containers +## Ignored when livenessProbe.enabled=true +## +customLivenessProbe: {} +## @param customReadinessProbe Override default readiness probe for MongoDB(®) containers +## Ignored when readinessProbe.enabled=true +## +customReadinessProbe: {} +## @param customStartupProbe Override default startup probe for MongoDB(®) containers +## Ignored when startupProbe.enabled=true +## +customStartupProbe: {} +## @param initContainers Add additional init containers for the hidden node pod(s) +## Example: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: [] +## @param sidecars Add additional sidecar containers for the MongoDB(®) pod(s) +## Example: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## This is an optional 'mongo-labeler' sidecar container that tracks replica-set for the primary mongodb pod +## and labels it dynamically with ' primary: "true" ' in order for an extra-deployed service to always expose +## and attach to the primary pod, this needs to be uncommented along with the suggested 'extraDeploy' example +## and the suggested rbac example for the pod to be allowed adding labels to mongo replica pods +## search 'mongo-labeler' through this file to find the sections that needs to be uncommented to make it work +## +## - name: mongo-labeler +## image: korenlev/k8s-mongo-labeler-sidecar +## imagePullPolicy: Always +## env: +## - name: LABEL_SELECTOR +## value: "app.kubernetes.io/component=mongodb,app.kubernetes.io/instance=mongodb,app.kubernetes.io/name=mongodb" +## - name: NAMESPACE +## value: "the-mongodb-namespace" +## - name: DEBUG +## value: "true" +## +sidecars: [] +## @param extraVolumeMounts Optionally specify extra list of additional volumeMounts for the MongoDB(®) container(s) +## Examples: +## extraVolumeMounts: +## - name: extras +## mountPath: /usr/share/extras +## readOnly: true +## +extraVolumeMounts: [] +## @param extraVolumes Optionally specify extra list of additional volumes to the MongoDB(®) statefulset +## extraVolumes: +## - name: extras +## emptyDir: {} +## +extraVolumes: [] +## MongoDB(®) Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Enable/disable a Pod Disruption Budget creation for MongoDB(®) pod(s) + ## + create: false + ## @param pdb.minAvailable Minimum number/percentage of MongoDB(®) pods that must still be available after the eviction + ## + minAvailable: 1 + ## @param pdb.maxUnavailable Maximum number/percentage of MongoDB(®) pods that may be made unavailable after the eviction + ## + maxUnavailable: "" +## @section Traffic exposure parameters +## + +## Service parameters +## +service: + ## @param service.nameOverride MongoDB(®) service name + ## + nameOverride: "" + ## @param service.type Kubernetes Service type (only for standalone architecture) + ## + type: ClusterIP + ## @param service.portName MongoDB(®) service port name (only for standalone architecture) + ## + portName: mongodb + ## @param service.ports.mongodb MongoDB(®) service port. + ## + ports: + mongodb: 27017 + ## @param service.nodePorts.mongodb Port to bind to for NodePort and LoadBalancer service types (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mongodb: "" + ## @param service.clusterIP MongoDB(®) service cluster IP (only for standalone architecture) + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.externalIPs Specify the externalIP value ClusterIP service type (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + ## @param service.loadBalancerIP loadBalancerIP for MongoDB(®) Service (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerClass loadBalancerClass for MongoDB(®) Service (only for standalone architecture) + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer (only for standalone architecture) + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + loadBalancerSourceRanges: [] + ## @param service.allocateLoadBalancerNodePorts Wheter to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## @param service.externalTrafficPolicy service external traffic policy (only for standalone architecture) + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## External Access to MongoDB(®) nodes configuration +## +externalAccess: + ## @param externalAccess.enabled Enable Kubernetes external cluster access to MongoDB(®) nodes (only for replicaset architecture) + ## + enabled: false + ## External IPs auto-discovery configuration + ## An init container is used to auto-detect LB IPs or node ports by querying the K8s API + ## Note: RBAC might be required + ## + autoDiscovery: + ## @param externalAccess.autoDiscovery.enabled Enable using an init container to auto-detect external IPs by querying the K8s API + ## + enabled: false + ## Bitnami Kubectl image + ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ + ## @param externalAccess.autoDiscovery.image.registry [default: REGISTRY_NAME] Init container auto-discovery image registry + ## @param externalAccess.autoDiscovery.image.repository [default: REPOSITORY_NAME/kubectl] Init container auto-discovery image repository + ## @skip externalAccess.autoDiscovery.image.tag Init container auto-discovery image tag (immutable tags are recommended) + ## @param externalAccess.autoDiscovery.image.digest Init container auto-discovery image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param externalAccess.autoDiscovery.image.pullPolicy Init container auto-discovery image pull policy + ## @param externalAccess.autoDiscovery.image.pullSecrets Init container auto-discovery image pull secrets + ## + image: + registry: docker.io + repository: bitnami/kubectl + tag: 1.29.3-debian-12-r3 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param externalAccess.autoDiscovery.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param externalAccess.autoDiscovery.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Parameters to configure a set of Pods that connect to an existing MongoDB(®) deployment that lies outside of Kubernetes. + ## @param externalAccess.externalMaster.enabled Use external master for bootstrapping + ## @param externalAccess.externalMaster.host External master host to bootstrap from + ## @param externalAccess.externalMaster.port Port for MongoDB(®) service external master host + ## + externalMaster: + enabled: false + host: "" + port: 27017 + ## Parameters to configure K8s service(s) used to externally access MongoDB(®) + ## A new service per broker will be created + ## + service: + ## @param externalAccess.service.type Kubernetes Service type for external access. Allowed values: NodePort, LoadBalancer or ClusterIP + ## + type: LoadBalancer + ## @param externalAccess.service.portName MongoDB(®) port name used for external access when service type is LoadBalancer + ## + portName: "mongodb" + ## @param externalAccess.service.ports.mongodb MongoDB(®) port used for external access when service type is LoadBalancer + ## + ports: + mongodb: 27017 + ## @param externalAccess.service.loadBalancerIPs Array of load balancer IPs for MongoDB(®) nodes + ## Example: + ## loadBalancerIPs: + ## - X.X.X.X + ## - Y.Y.Y.Y + ## + loadBalancerIPs: [] + ## @param externalAccess.service.loadBalancerClass loadBalancerClass when service type is LoadBalancer + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param externalAccess.service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## Example: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param externalAccess.service.allocateLoadBalancerNodePorts Wheter to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param externalAccess.service.externalTrafficPolicy MongoDB(®) service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param externalAccess.service.nodePorts Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort + ## Example: + ## nodePorts: + ## - 30001 + ## - 30002 + ## + nodePorts: [] + ## @param externalAccess.service.domain Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort + ## If not specified, the container will try to get the kubernetes node external IP + ## e.g: + ## domain: mydomain.com + ## + domain: "" + ## @param externalAccess.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param externalAccess.service.annotations Service annotations for external access + ## + annotations: {} + ## @param externalAccess.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param externalAccess.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## External Access to MongoDB(®) Hidden nodes configuration + ## + hidden: + ## @param externalAccess.hidden.enabled Enable Kubernetes external cluster access to MongoDB(®) hidden nodes + ## + enabled: false + ## Parameters to configure K8s service(s) used to externally access MongoDB(®) + ## A new service per broker will be created + ## + service: + ## @param externalAccess.hidden.service.type Kubernetes Service type for external access. Allowed values: NodePort or LoadBalancer + ## + type: LoadBalancer + ## @param externalAccess.hidden.service.portName MongoDB(®) port name used for external access when service type is LoadBalancer + ## + portName: "mongodb" + ## @param externalAccess.hidden.service.ports.mongodb MongoDB(®) port used for external access when service type is LoadBalancer + ## + ports: + mongodb: 27017 + ## @param externalAccess.hidden.service.loadBalancerIPs Array of load balancer IPs for MongoDB(®) nodes + ## Example: + ## loadBalancerIPs: + ## - X.X.X.X + ## - Y.Y.Y.Y + ## + loadBalancerIPs: [] + ## @param externalAccess.hidden.service.loadBalancerClass loadBalancerClass when service type is LoadBalancer + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param externalAccess.hidden.service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## Example: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param externalAccess.hidden.service.allocateLoadBalancerNodePorts Wheter to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param externalAccess.hidden.service.externalTrafficPolicy MongoDB(®) service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param externalAccess.hidden.service.nodePorts Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort. Length must be the same as replicaCount + ## Example: + ## nodePorts: + ## - 30001 + ## - 30002 + ## + nodePorts: [] + ## @param externalAccess.hidden.service.domain Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort + ## If not specified, the container will try to get the kubernetes node external IP + ## e.g: + ## domain: mydomain.com + ## + domain: "" + ## @param externalAccess.hidden.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param externalAccess.hidden.service.annotations Service annotations for external access + ## + annotations: {} + ## @param externalAccess.hidden.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param externalAccess.hidden.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} +## @section Network policy parameters +## + +## Network Policies +## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolice + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces + ## @param networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} +persistence: + ## @param persistence.enabled Enable MongoDB(®) data persistence using PVC + ## + enabled: true + ## @param persistence.name Name of the PVC and mounted volume + ## + name: "datadir" + ## @param persistence.medium Provide a medium for `emptyDir` volumes. + ## Requires persistence.enabled: false + ## + medium: "" + ## @param persistence.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## Requires persistence.enabled: true + ## If defined, PVC must be created manually before volume will be bound + ## Ignored when mongodb.architecture=replicaset + ## + existingClaim: "" + ## @param persistence.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param persistence.storageClass PVC Storage Class for MongoDB(®) data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + storageClass: "" + ## @param persistence.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size PVC Storage Request for MongoDB(®) data volume + ## + size: 8Gi + ## @param persistence.annotations PVC annotations + ## + annotations: {} + ## @param persistence.mountPath Path to mount the volume at + ## MongoDB(®) images. + ## + mountPath: /bitnami/mongodb + ## @param persistence.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param persistence.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param persistence.volumeClaimTemplates.requests Custom PVC requests attributes + ## Sometime cloud providers use additional requests attributes to provision custom storage instance + ## See https://cloud.ibm.com/docs/containers?topic=containers-file_storage#file_dynamic_statefulset + ## + requests: {} + ## @param persistence.volumeClaimTemplates.dataSource Add dataSource to the VolumeClaimTemplate + ## + dataSource: {} +## Persistent Volume Claim Retention Policy +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention +## +persistentVolumeClaimRetentionPolicy: + ## @param persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for MongoDB(®) Statefulset + ## + enabled: false + ## @param persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain +## @section Backup parameters +## This section implements a trivial logical dump cronjob of the database. +## This only comes with the consistency guarantees of the dump program. +## This is not a snapshot based roll forward/backward recovery backup. +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ +## +backup: + ## @param backup.enabled Enable the logical dump of the database "regularly" + ## + enabled: false + ## Fine tuning cronjob's config + ## + cronjob: + ## @param backup.cronjob.schedule Set the cronjob parameter schedule + ## + schedule: "@daily" + ## @param backup.cronjob.concurrencyPolicy Set the cronjob parameter concurrencyPolicy + ## + concurrencyPolicy: Allow + ## @param backup.cronjob.failedJobsHistoryLimit Set the cronjob parameter failedJobsHistoryLimit + ## + failedJobsHistoryLimit: 1 + ## @param backup.cronjob.successfulJobsHistoryLimit Set the cronjob parameter successfulJobsHistoryLimit + ## + successfulJobsHistoryLimit: 3 + ## @param backup.cronjob.startingDeadlineSeconds Set the cronjob parameter startingDeadlineSeconds + ## + startingDeadlineSeconds: "" + ## @param backup.cronjob.ttlSecondsAfterFinished Set the cronjob parameter ttlSecondsAfterFinished + ## + ttlSecondsAfterFinished: "" + ## @param backup.cronjob.restartPolicy Set the cronjob parameter restartPolicy + ## + restartPolicy: OnFailure + ## @param backup.cronjob.backoffLimit Set the cronjob parameter backoffLimit + backoffLimit: 6 + ## backup container's Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param backup.cronjob.containerSecurityContext.enabled Enabled containers' Security Context + ## @param backup.cronjob.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param backup.cronjob.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param backup.cronjob.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param backup.cronjob.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param backup.cronjob.containerSecurityContext.privileged Set container's Security Context privileged + ## @param backup.cronjob.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param backup.cronjob.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param backup.cronjob.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param backup.cronjob.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## @param backup.cronjob.command Set backup container's command to run + ## + command: [] + ## @param backup.cronjob.labels Set the cronjob labels + ## + labels: {} + ## @param backup.cronjob.annotations Set the cronjob annotations + ## + annotations: {} + ## Backup container's + ## + storage: + ## @param backup.cronjob.storage.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## If defined, PVC must be created manually before volume will be bound + ## + existingClaim: "" + ## @param backup.cronjob.storage.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param backup.cronjob.storage.storageClass PVC Storage Class for the backup data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + storageClass: "" + ## @param backup.cronjob.storage.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param backup.cronjob.storage.size PVC Storage Request for the backup data volume + ## + size: 8Gi + ## @param backup.cronjob.storage.annotations PVC annotations + ## + annotations: {} + ## @param backup.cronjob.storage.mountPath Path to mount the volume at + ## + mountPath: /backup/mongodb + ## @param backup.cronjob.storage.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param backup.cronjob.storage.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} +## @section RBAC parameters +## + +## ServiceAccount +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable creation of ServiceAccount for MongoDB(®) pods + ## + create: true + ## @param serviceAccount.name Name of the created serviceAccount + ## If not set and create is true, a name is generated using the mongodb.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional Service Account annotations + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created + ## Can be set to false if pods using this serviceAccount do not need to use K8s API + ## + automountServiceAccountToken: false +## Role Based Access +## ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## @param rbac.create Whether to create & use RBAC resources or not + ## binding MongoDB(®) ServiceAccount to a role + ## that allows MongoDB(®) pods querying the K8s API + ## this needs to be set to 'true' to enable the mongo-labeler sidecar primary mongodb discovery + ## + create: false + ## @param rbac.rules Custom rules to create following the role specification + ## The example below needs to be uncommented to use the 'mongo-labeler' sidecar for dynamic discovery of the primary mongodb pod: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## - watch + ## - update + ## + rules: [] +## PodSecurityPolicy configuration +## Be sure to also set rbac.create to true, otherwise Role and RoleBinding won't be created. +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + ## @param podSecurityPolicy.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later + ## + create: false + ## @param podSecurityPolicy.allowPrivilegeEscalation Enable privilege escalation + ## Either use predefined policy with some adjustments or use `podSecurityPolicy.spec` + ## + allowPrivilegeEscalation: false + ## @param podSecurityPolicy.privileged Allow privileged + ## + privileged: false + ## @param podSecurityPolicy.spec Specify the full spec to use for Pod Security Policy + ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## Defining a spec ignores the above values. + ## + spec: {} + ## Example: + ## allowPrivilegeEscalation: false + ## fsGroup: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## hostIPC: false + ## hostNetwork: false + ## hostPID: false + ## privileged: false + ## readOnlyRootFilesystem: true + ## requiredDropCapabilities: + ## - ALL + ## runAsUser: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## seLinux: + ## rule: 'RunAsAny' + ## supplementalGroups: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## volumes: + ## - 'configMap' + ## - 'secret' + ## - 'emptyDir' + ## - 'persistentVolumeClaim' + ## +## @section Volume Permissions parameters +## +## Init Container parameters +## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component +## values from the securityContext section of the component +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: 12-debian-12-r18 + digest: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## Init container Security Context + ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser + ## and not the below volumePermissions.securityContext.runAsUser + ## When runAsUser is set to special value "auto", init container will try to chwon the + ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). + ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with + ## podSecurityContext.enabled=false,containerSecurityContext.enabled=false and shmVolume.chmod.enabled=false + ## @param volumePermissions.securityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.securityContext.runAsUser User ID for the volumePermissions container + ## + securityContext: + seLinuxOptions: {} + runAsUser: 0 +## @section Arbiter parameters +## +arbiter: + ## @param arbiter.enabled Enable deploying the arbiter + ## https://docs.mongodb.com/manual/tutorial/add-replica-set-arbiter/ + ## + enabled: true + ## @param arbiter.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param arbiter.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param arbiter.configuration Arbiter configuration file to be used + ## http://docs.mongodb.org/manual/reference/configuration-options/ + ## + configuration: "" + ## @param arbiter.existingConfigmap Name of existing ConfigMap with Arbiter configuration + ## NOTE: When it's set the arbiter.configuration parameter is ignored + ## + existingConfigmap: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param arbiter.command Override default container command (useful when using custom images) + ## @param arbiter.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## @param arbiter.extraFlags Arbiter additional command line flags + ## Example: + ## extraFlags: + ## - "--wiredTigerCacheSizeGB=2" + ## + extraFlags: [] + ## @param arbiter.extraEnvVars Extra environment variables to add to Arbiter pods + ## E.g: + ## extraEnvVars: + ## - name: FOO + ## value: BAR + ## + extraEnvVars: [] + ## @param arbiter.extraEnvVarsCM Name of existing ConfigMap containing extra env vars + ## + extraEnvVarsCM: "" + ## @param arbiter.extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param arbiter.annotations Additional labels to be added to the Arbiter statefulset + ## + annotations: {} + ## @param arbiter.labels Annotations to be added to the Arbiter statefulset + ## + labels: {} + ## @param arbiter.topologySpreadConstraints MongoDB(®) Spread Constraints for arbiter Pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + ## @param arbiter.lifecycleHooks LifecycleHook for the Arbiter container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param arbiter.terminationGracePeriodSeconds Arbiter Termination Grace Period + ## + terminationGracePeriodSeconds: "" + ## @param arbiter.updateStrategy.type Strategy that will be employed to update Pods in the StatefulSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param arbiter.podManagementPolicy Pod management policy for MongoDB(®) + ## Should be initialized one by one when building the replicaset for the first time + ## + podManagementPolicy: OrderedReady + ## @param arbiter.schedulerName Name of the scheduler (other than default) to dispatch pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param arbiter.podAffinityPreset Arbiter Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param arbiter.podAntiAffinityPreset Arbiter Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param arbiter.nodeAffinityPreset.type Arbiter Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param arbiter.nodeAffinityPreset.key Arbiter Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param arbiter.nodeAffinityPreset.values Arbiter Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param arbiter.affinity Arbiter Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: arbiter.podAffinityPreset, arbiter.podAntiAffinityPreset, and arbiter.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param arbiter.nodeSelector Arbiter Node labels for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param arbiter.tolerations Arbiter Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param arbiter.podLabels Arbiter pod labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param arbiter.podAnnotations Arbiter Pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param arbiter.priorityClassName Name of the existing priority class to be used by Arbiter pod(s) + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param arbiter.runtimeClassName Name of the runtime class to be used by Arbiter pod(s) + ## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ + ## + runtimeClassName: "" + ## MongoDB(®) Arbiter pods' Security Context. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param arbiter.podSecurityContext.enabled Enable Arbiter pod(s)' Security Context + ## @param arbiter.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param arbiter.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param arbiter.podSecurityContext.fsGroup Group ID for the volumes of the Arbiter pod(s) + ## @param arbiter.podSecurityContext.sysctls sysctl settings of the Arbiter pod(s)' + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] + ## MongoDB(®) Arbiter containers' Security Context (only main container). + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param arbiter.containerSecurityContext.enabled Enabled containers' Security Context + ## @param arbiter.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param arbiter.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param arbiter.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param arbiter.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param arbiter.containerSecurityContext.privileged Set container's Security Context privileged + ## @param arbiter.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param arbiter.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param arbiter.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param arbiter.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MongoDB(®) Arbiter containers' resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param arbiter.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if arbiter.resources is set (arbiter.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "small" + ## @param arbiter.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param arbiter.containerPorts.mongodb MongoDB(®) arbiter container port + ## + containerPorts: + mongodb: 27017 + ## MongoDB(®) Arbiter pods' liveness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.livenessProbe.enabled Enable livenessProbe + ## @param arbiter.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param arbiter.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param arbiter.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param arbiter.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param arbiter.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Arbiter pods' readiness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.readinessProbe.enabled Enable readinessProbe + ## @param arbiter.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param arbiter.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param arbiter.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param arbiter.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param arbiter.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Arbiter pods' startup probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.startupProbe.enabled Enable startupProbe + ## @param arbiter.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param arbiter.startupProbe.periodSeconds Period seconds for startupProbe + ## @param arbiter.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param arbiter.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param arbiter.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param arbiter.customLivenessProbe Override default liveness probe for Arbiter containers + ## Ignored when arbiter.livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param arbiter.customReadinessProbe Override default readiness probe for Arbiter containers + ## Ignored when arbiter.readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param arbiter.customStartupProbe Override default startup probe for Arbiter containers + ## Ignored when arbiter.startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param arbiter.initContainers Add additional init containers for the Arbiter pod(s) + ## Example: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + initContainers: [] + ## @param arbiter.sidecars Add additional sidecar containers for the Arbiter pod(s) + ## Example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param arbiter.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Arbiter container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## @param arbiter.extraVolumes Optionally specify extra list of additional volumes to the Arbiter statefulset + ## extraVolumes: + ## - name: extras + ## emptyDir: {} + ## + extraVolumes: [] + ## MongoDB(®) Arbiter Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param arbiter.pdb.create Enable/disable a Pod Disruption Budget creation for Arbiter pod(s) + ## + create: false + ## @param arbiter.pdb.minAvailable Minimum number/percentage of Arbiter pods that should remain scheduled + ## + minAvailable: 1 + ## @param arbiter.pdb.maxUnavailable Maximum number/percentage of Arbiter pods that may be made unavailable + ## + maxUnavailable: "" + ## MongoDB(®) Arbiter service parameters + ## + service: + ## @param arbiter.service.nameOverride The arbiter service name + ## + nameOverride: "" + ## @param arbiter.service.ports.mongodb MongoDB(®) service port + ## + ports: + mongodb: 27017 + ## @param arbiter.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param arbiter.service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## Headless service properties + ## + headless: + ## @param arbiter.service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## @section Hidden Node parameters +## +hidden: + ## @param hidden.enabled Enable deploying the hidden nodes + ## https://docs.mongodb.com/manual/tutorial/configure-a-hidden-replica-set-member/ + ## + enabled: false + ## @param hidden.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param hidden.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param hidden.configuration Hidden node configuration file to be used + ## http://docs.mongodb.org/manual/reference/configuration-options/ + ## + configuration: "" + ## @param hidden.existingConfigmap Name of existing ConfigMap with Hidden node configuration + ## NOTE: When it's set the hidden.configuration parameter is ignored + ## + existingConfigmap: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param hidden.command Override default container command (useful when using custom images) + ## @param hidden.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## @param hidden.extraFlags Hidden node additional command line flags + ## Example: + ## extraFlags: + ## - "--wiredTigerCacheSizeGB=2" + ## + extraFlags: [] + ## @param hidden.extraEnvVars Extra environment variables to add to Hidden node pods + ## E.g: + ## extraEnvVars: + ## - name: FOO + ## value: BAR + ## + extraEnvVars: [] + ## @param hidden.extraEnvVarsCM Name of existing ConfigMap containing extra env vars + ## + extraEnvVarsCM: "" + ## @param hidden.extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param hidden.annotations Additional labels to be added to thehidden node statefulset + ## + annotations: {} + ## @param hidden.labels Annotations to be added to the hidden node statefulset + ## + labels: {} + ## @param hidden.topologySpreadConstraints MongoDB(®) Spread Constraints for hidden Pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + ## @param hidden.lifecycleHooks LifecycleHook for the Hidden container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param hidden.replicaCount Number of hidden nodes (only when `architecture=replicaset`) + ## Ignored when mongodb.architecture=standalone + ## + replicaCount: 1 + ## @param hidden.terminationGracePeriodSeconds Hidden Termination Grace Period + ## + terminationGracePeriodSeconds: "" + ## @param hidden.updateStrategy.type Strategy that will be employed to update Pods in the StatefulSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param hidden.podManagementPolicy Pod management policy for hidden node + ## + podManagementPolicy: OrderedReady + ## @param hidden.schedulerName Name of the scheduler (other than default) to dispatch pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param hidden.podAffinityPreset Hidden node Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param hidden.podAntiAffinityPreset Hidden node Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## Allowed values: soft, hard + ## + nodeAffinityPreset: + ## @param hidden.nodeAffinityPreset.type Hidden Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param hidden.nodeAffinityPreset.key Hidden Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param hidden.nodeAffinityPreset.values Hidden Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param hidden.affinity Hidden node Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param hidden.nodeSelector Hidden node Node labels for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param hidden.tolerations Hidden node Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param hidden.podLabels Hidden node pod labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param hidden.podAnnotations Hidden node Pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param hidden.priorityClassName Name of the existing priority class to be used by hidden node pod(s) + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param hidden.runtimeClassName Name of the runtime class to be used by hidden node pod(s) + ## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ + ## + runtimeClassName: "" + ## MongoDB(®) Hidden pods' Security Context. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param hidden.podSecurityContext.enabled Enable Hidden pod(s)' Security Context + ## @param hidden.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param hidden.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param hidden.podSecurityContext.fsGroup Group ID for the volumes of the Hidden pod(s) + ## @param hidden.podSecurityContext.sysctls sysctl settings of the Hidden pod(s)' + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] + ## MongoDB(®) Hidden containers' Security Context (only main container). + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param hidden.containerSecurityContext.enabled Enabled containers' Security Context + ## @param hidden.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param hidden.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param hidden.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param hidden.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param hidden.containerSecurityContext.privileged Set container's Security Context privileged + ## @param hidden.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param hidden.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param hidden.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param hidden.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MongoDB(®) Hidden containers' resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param hidden.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if hidden.resources is set (hidden.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param hidden.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param hidden.containerPorts.mongodb MongoDB(®) hidden container port + ## + containerPorts: + mongodb: 27017 + ## MongoDB(®) Hidden pods' liveness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param hidden.livenessProbe.enabled Enable livenessProbe + ## @param hidden.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param hidden.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param hidden.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param hidden.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param hidden.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Hidden pods' readiness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param hidden.readinessProbe.enabled Enable readinessProbe + ## @param hidden.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param hidden.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param hidden.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param hidden.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param hidden.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## Slow starting containers can be protected through startup probes + ## Startup probes are available in Kubernetes version 1.16 and above + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + ## @param hidden.startupProbe.enabled Enable startupProbe + ## @param hidden.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param hidden.startupProbe.periodSeconds Period seconds for startupProbe + ## @param hidden.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param hidden.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param hidden.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param hidden.customLivenessProbe Override default liveness probe for hidden node containers + ## Ignored when hidden.livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param hidden.customReadinessProbe Override default readiness probe for hidden node containers + ## Ignored when hidden.readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param hidden.customStartupProbe Override default startup probe for MongoDB(®) containers + ## Ignored when hidden.startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param hidden.initContainers Add init containers to the MongoDB(®) Hidden pods. + ## Example: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + initContainers: [] + ## @param hidden.sidecars Add additional sidecar containers for the hidden node pod(s) + ## Example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param hidden.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the hidden node container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## @param hidden.extraVolumes Optionally specify extra list of additional volumes to the hidden node statefulset + ## extraVolumes: + ## - name: extras + ## emptyDir: {} + ## + extraVolumes: [] + ## MongoDB(®) Hidden Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param hidden.pdb.create Enable/disable a Pod Disruption Budget creation for hidden node pod(s) + ## + create: false + ## @param hidden.pdb.minAvailable Minimum number/percentage of hidden node pods that should remain scheduled + ## + minAvailable: 1 + ## @param hidden.pdb.maxUnavailable Maximum number/percentage of hidden node pods that may be made unavailable + ## + maxUnavailable: "" + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ + ## + persistence: + ## @param hidden.persistence.enabled Enable hidden node data persistence using PVC + ## + enabled: true + ## @param hidden.persistence.medium Provide a medium for `emptyDir` volumes. + ## Requires hidden.persistence.enabled: false + ## + medium: "" + ## @param hidden.persistence.storageClass PVC Storage Class for hidden node data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + storageClass: "" + ## @param hidden.persistence.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param hidden.persistence.size PVC Storage Request for hidden node data volume + ## + size: 8Gi + ## @param hidden.persistence.annotations PVC annotations + ## + annotations: {} + ## @param hidden.persistence.mountPath The path the volume will be mounted at, useful when using different MongoDB(®) images. + ## + mountPath: /bitnami/mongodb + ## @param hidden.persistence.subPath The subdirectory of the volume to mount to, useful in dev environments + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param hidden.persistence.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param hidden.persistence.volumeClaimTemplates.requests Custom PVC requests attributes + ## Sometime cloud providers use additional requests attributes to provision custom storage instance + ## See https://cloud.ibm.com/docs/containers?topic=containers-file_storage#file_dynamic_statefulset + ## + requests: {} + ## @param hidden.persistence.volumeClaimTemplates.dataSource Set volumeClaimTemplate dataSource + ## + dataSource: {} + service: + ## @param hidden.service.portName MongoDB(®) service port name + ## + portName: "mongodb" + ## @param hidden.service.ports.mongodb MongoDB(®) service port + ## + ports: + mongodb: 27017 + ## @param hidden.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param hidden.service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## Headless service properties + ## + headless: + ## @param hidden.service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## @section Metrics parameters +## +metrics: + ## @param metrics.enabled Enable using a sidecar Prometheus exporter + ## + enabled: false + ## Bitnami MongoDB(®) Promtheus Exporter image + ## ref: https://hub.docker.com/r/bitnami/mongodb-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] MongoDB(®) Prometheus exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/mongodb-exporter] MongoDB(®) Prometheus exporter image repository + ## @skip metrics.image.tag MongoDB(®) Prometheus exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy MongoDB(®) Prometheus exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: docker.io + repository: bitnami/mongodb-exporter + tag: 0.40.0-debian-12-r15 + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.username String with username for the metrics exporter + ## If undefined the root user will be used for the metrics exporter + ## + username: "" + ## @param metrics.password String with password for the metrics exporter + ## If undefined but metrics.username is defined, a random password will be generated + ## + password: "" + ## @param metrics.compatibleMode Enables old style mongodb-exporter metrics + compatibleMode: true + collector: + ## @param metrics.collector.all Enable all collectors. Same as enabling all individual metrics + ## Enabling all metrics will cause significant CPU load on mongod + all: false + ## @param metrics.collector.diagnosticdata Boolean Enable collecting metrics from getDiagnosticData + diagnosticdata: true + ## @param metrics.collector.replicasetstatus Boolean Enable collecting metrics from replSetGetStatus + replicasetstatus: true + ## @param metrics.collector.dbstats Boolean Enable collecting metrics from dbStats + dbstats: false + ## @param metrics.collector.topmetrics Boolean Enable collecting metrics from top admin command + topmetrics: false + ## @param metrics.collector.indexstats Boolean Enable collecting metrics from $indexStats + indexstats: false + ## @param metrics.collector.collstats Boolean Enable collecting metrics from $collStats + collstats: false + ## @param metrics.collector.collstatsColls List of \.\ to get $collStats + collstatsColls: [] + ## @param metrics.collector.indexstatsColls List - List of \.\ to get $indexStats + indexstatsColls: [] + ## @param metrics.collector.collstatsLimit Number - Disable collstats, dbstats, topmetrics and indexstats collector if there are more than \ collections. 0=No limit + collstatsLimit: 0 + ## @param metrics.extraFlags String with extra flags to the metrics exporter + ## ref: https://github.com/percona/mongodb_exporter/blob/main/main.go + ## + extraFlags: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param metrics.command Override default container command (useful when using custom images) + ## @param metrics.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## Metrics exporter container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param metrics.containerPort Port of the Prometheus metrics container + ## + containerPort: 9216 + ## Prometheus Exporter service configuration + ## + service: + ## @param metrics.service.annotations [object] Annotations for Prometheus Exporter pods. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.ports.metrics }}" + prometheus.io/path: "/metrics" + ## @param metrics.service.type Type of the Prometheus metrics service + ## + type: ClusterIP + ## @param metrics.service.ports.metrics Port of the Prometheus metrics service + ## + ports: + metrics: 9216 + ## @param metrics.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## Metrics exporter liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param metrics.livenessProbe.enabled Enable livenessProbe + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 15 + periodSeconds: 5 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + ## Metrics exporter readiness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param metrics.readinessProbe.enabled Enable readinessProbe + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + ## Slow starting containers can be protected through startup probes + ## Startup probes are available in Kubernetes version 1.16 and above + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + ## @param metrics.startupProbe.enabled Enable startupProbe + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param metrics.customLivenessProbe Override default liveness probe for MongoDB(®) containers + ## Ignored when livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Override default readiness probe for MongoDB(®) containers + ## Ignored when readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param metrics.customStartupProbe Override default startup probe for MongoDB(®) containers + ## Ignored when startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the metrics container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using Prometheus Operator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace which Prometheus is running in + ## + namespace: "" + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended + ## e.g: + ## scrapeTimeout: 30s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping. + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricsRelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.labels Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + labels: {} + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + selector: {} + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Set this to true to create prometheusRules for Prometheus operator + ## + enabled: false + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so prometheusRules will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.namespace Namespace where prometheusRules resource should be created + ## + namespace: "" + ## @param metrics.prometheusRule.rules Rules to be created, check values for an example + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#rulegroup + ## https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ + ## + ## This is an example of a rule, you should add the below code block under the "rules" param, removing the brackets + ## rules: + ## - alert: HighRequestLatency + ## expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 + ## for: 10m + ## labels: + ## severity: page + ## annotations: + ## summary: High request latency + ## + rules: [] diff --git a/utils/assets/charts/mongo-express/ci/default-values.yaml b/utils/assets/charts/mongo-express/ci/default-values.yaml new file mode 100644 index 0000000..6d233ad --- /dev/null +++ b/utils/assets/charts/mongo-express/ci/default-values.yaml @@ -0,0 +1,6 @@ +fullnameOverride: mongo-express +mongodb: + enabled: true + fullnameOverride: mongodb + auth: + enabled: false diff --git a/utils/assets/charts/mongo-express/templates/NOTES.txt b/utils/assets/charts/mongo-express/templates/NOTES.txt new file mode 100644 index 0000000..de9ad36 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/NOTES.txt @@ -0,0 +1,21 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mongo-express.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT{{ .Values.siteBaseUrl }} +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mongo-express.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mongo-express.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.ports.http }}{{ .Values.siteBaseUrl }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mongo-express.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8081{{ .Values.siteBaseUrl }} to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8081:{{ .Values.containerPorts.http }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/templates/_helpers.tpl b/utils/assets/charts/mongo-express/templates/_helpers.tpl new file mode 100644 index 0000000..638a256 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/_helpers.tpl @@ -0,0 +1,136 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "mongo-express.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongo-express.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mongo-express.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "mongo-express.labels" -}} +helm.sh/chart: {{ include "mongo-express.chart" . }} +{{ include "mongo-express.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "mongo-express.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mongo-express.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mongo-express.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "mongo-express.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the secret to use +*/}} +{{- define "mongo-express.secretName" -}} +{{- if .Values.existingSecret -}} + {{ .Values.existingSecret }} +{{- else -}} + {{ include "mongo-express.fullname" . }} +{{- end -}} +{{- end -}} + +{{/* +Key in Secret that contains administrator password +*/}} +{{- define "mongo-express.secretKeyMongodbAdminPassword" -}} +{{- if .Values.existingSecret -}} + {{ .Values.existingSecretKeyMongodbAdminPassword }} +{{- else -}} + mongodb-admin-password +{{- end -}} +{{- end -}} + +{{/* +Key in Secret that contains database password +*/}} +{{- define "mongo-express.secretKeyMongodbAuthPassword" -}} +{{- if .Values.existingSecret -}} + {{ .Values.existingSecretKeyMongodbAuthPassword }} +{{- else -}} + mongodb-auth-password +{{- end -}} +{{- end -}} + +{{/* +Key in Secret that contains string used by cookie-parser middleware to sign cookies +*/}} +{{- define "mongo-express.secretKeySiteCookieSecret" -}} +{{- if .Values.existingSecret -}} + {{ .Values.existingSecretKeySiteCookieSecret }} +{{- else -}} + site-cookie-secret +{{- end -}} +{{- end -}} + +{{/* +Key in Secret that contains string used to sign the session ID cookie by express-session middleware +*/}} +{{- define "mongo-express.secretKeySiteSessionSecret" -}} +{{- if .Values.existingSecret -}} + {{ .Values.existingSecretKeySiteSessionSecret }} +{{- else -}} + site-session-secret +{{- end -}} +{{- end -}} + +{{/* +Key in Secret that contains Mongo Express web login password +*/}} +{{- define "mongo-express.secretKeyBasicAuthPassword" -}} +{{- if .Values.existingSecret -}} + {{ .Values.existingSecretKeyBasicAuthPassword }} +{{- else -}} + basic-auth-password +{{- end -}} +{{- end -}} + +{{/* +Create the basic authentification HTTP header +*/}} +{{- define "mongo-express.basicAuthHttpHeader" -}} +Basic {{ printf "%s:%s" .Values.basicAuthUsername .Values.basicAuthPassword | b64enc }} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/templates/deployment.yaml b/utils/assets/charts/mongo-express/templates/deployment.yaml new file mode 100644 index 0000000..eeb3fbf --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/deployment.yaml @@ -0,0 +1,197 @@ +apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ include "mongo-express.fullname" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.deploymentAnnotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.deploymentAnnotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "mongo-express.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "mongo-express.selectorLabels" . | nindent 8 }} + {{- if .Values.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.podLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if not .Values.existingSecret }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- include "common.images.pullSecrets" ( dict "images" ( list .Values.image ) "global" .Values.global ) | nindent 6 }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName | quote }} + {{- end }} + serviceAccountName: {{ include "mongo-express.serviceAccountName" . }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: mongo-express + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ include "common.images.image" ( dict "imageRoot" .Values.image "global" .Values.global ) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.extraArgs }} + args: + {{- range $key, $value := .Values.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- end }} + env: + - name: PORT + value: {{ .Values.containerPorts.http | quote }} + - name: MONGODB_SERVER + value: {{ .Values.mongodbServer | quote }} + - name: MONGODB_PORT + value: {{ .Values.mongodbPort | quote }} + - name: ME_CONFIG_MONGODB_ENABLE_ADMIN + value: {{ .Values.mongodbEnableAdmin | quote }} + {{- if .Values.mongodbEnableAdmin }} + {{- if and .Values.mongodbAdminUsername .Values.mongodbAdminPassword}} + - name: MONGODB_USERNAME + value: {{ .Values.mongodbAdminUsername | quote }} + - name: MONGODB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongo-express.secretName" . }} + key: {{ include "mongo-express.secretKeyMongodbAdminPassword" . }} + - name: ME_CONFIG_MONGODB_URL + value: "mongodb://$(MONGODB_USERNAME):$(MONGODB_PASSWORD)@$(MONGODB_SERVER):$(MONGODB_PORT)/" + {{- else }} + - name: ME_CONFIG_MONGODB_URL + value: "mongodb://$(MONGODB_SERVER):$(MONGODB_PORT)/" + {{- end }} + {{- else }} + - name: MONGODB_DATABASE + value: {{ .Values.mongodbAuthDatabase | quote }} + {{- if and .Values.mongodbAuthUsername .Values.mongodbAuthPassword}} + - name: MONGODB_USERNAME + value: {{ .Values.mongodbAuthUsername | quote }} + - name: MONGODB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongo-express.secretName" . }} + key: {{ include "mongo-express.secretKeyMongodbAuthPassword" . }} + - name: ME_CONFIG_MONGODB_URL + value: "mongodb://$(MONGODB_USERNAME):$(MONGODB_PASSWORD)@$(MONGODB_SERVER):$(MONGODB_PORT)/$(MONGODB_DATABASE)" + {{- else }} + - name: ME_CONFIG_MONGODB_URL + value: "mongodb://$(MONGODB_SERVER):$(MONGODB_PORT)/$(MONGODB_DATABASE)" + {{- end }} + {{- end }} + - name: ME_CONFIG_SITE_BASEURL + value: {{ .Values.siteBaseUrl | quote }} + - name: ME_CONFIG_SITE_COOKIESECRET + valueFrom: + secretKeyRef: + name: {{ include "mongo-express.secretName" . }} + key: {{ include "mongo-express.secretKeySiteCookieSecret" . }} + - name: ME_CONFIG_SITE_SESSIONSECRET + valueFrom: + secretKeyRef: + name: {{ include "mongo-express.secretName" . }} + key: {{ include "mongo-express.secretKeySiteSessionSecret" . }} + {{- if and .Values.basicAuthUsername .Values.basicAuthPassword }} + - name: ME_CONFIG_BASICAUTH + value: "true" + - name: ME_CONFIG_BASICAUTH_USERNAME + value: {{ .Values.basicAuthUsername | quote }} + - name: ME_CONFIG_BASICAUTH_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongo-express.secretName" . }} + key: {{ include "mongo-express.secretKeyBasicAuthPassword" . }} + {{- else }} + - name: ME_CONFIG_BASICAUTH + value: "false" + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} + {{- end }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.containerPorts.http }} + protocol: TCP + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.siteBaseUrl | trimSuffix "/" }}/status + port: http + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.siteBaseUrl | trimSuffix "/" }}/status + port: http + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + {{- end }} + {{- if .Values.startupProbe.enabled }} + startupProbe: + httpGet: + path: {{ .Values.siteBaseUrl | trimSuffix "/" }}/status + port: http + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/mongo-express/templates/extra-list.yaml b/utils/assets/charts/mongo-express/templates/extra-list.yaml new file mode 100644 index 0000000..9ac65f9 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/extra-list.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/templates/ingress.yaml b/utils/assets/charts/mongo-express/templates/ingress.yaml new file mode 100644 index 0000000..ce2cf65 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ include "mongo-express.fullname" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.ingress.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.ingress.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ingressClassName (eq "true" (include "common.ingress.supportsIngressClassname" .)) }} + ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + {{- if eq "true" (include "common.ingress.supportsPathType" $) }} + pathType: {{ $.Values.ingress.pathType }} + {{- end }} + backend: + {{- include "common.ingress.backend" (dict "serviceName" (include "mongo-express.fullname" $) "servicePort" $.Values.service.ports.http "context" $) | nindent 14 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/templates/pdb.yaml b/utils/assets/charts/mongo-express/templates/pdb.yaml new file mode 100644 index 0000000..e9be325 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/pdb.yaml @@ -0,0 +1,25 @@ +{{- if .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mongo-express.fullname" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if .Values.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "mongo-express.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/templates/secret.yaml b/utils/assets/charts/mongo-express/templates/secret.yaml new file mode 100644 index 0000000..2952ceb --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/secret.yaml @@ -0,0 +1,27 @@ +{{- if not .Values.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "mongo-express.secretName" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if .Values.mongodbEnableAdmin }} + mongodb-admin-password: {{ .Values.mongodbAdminPassword | b64enc | quote }} + {{- else }} + mongodb-auth-password: {{ .Values.mongodbAuthPassword | b64enc | quote }} + {{- end }} + site-cookie-secret: {{ default (randAlphaNum 32) .Values.siteCookieSecret | b64enc | quote }} + site-session-secret: {{ default (randAlphaNum 32) .Values.siteSessionSecret | b64enc | quote }} + {{- if and .Values.basicAuthUsername .Values.basicAuthPassword }} + basic-auth-password: {{ .Values.basicAuthPassword | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongo-express/templates/service.yaml b/utils/assets/charts/mongo-express/templates/service.yaml new file mode 100644 index 0000000..c6ea705 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/service.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongo-express.fullname" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} + {{- end }} + ports: + - port: {{ .Values.service.ports.http }} + targetPort: http + protocol: TCP + name: http + {{- if and (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) .Values.service.nodePorts.http }} + nodePort: {{ .Values.service.nodePorts.http }} + {{- end }} + selector: + {{- include "mongo-express.selectorLabels" . | nindent 4 }} diff --git a/utils/assets/charts/mongo-express/templates/serviceaccount.yaml b/utils/assets/charts/mongo-express/templates/serviceaccount.yaml new file mode 100644 index 0000000..c285ead --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongo-express.serviceAccountName" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/templates/tests/_helpers.tpl b/utils/assets/charts/mongo-express/templates/tests/_helpers.tpl new file mode 100644 index 0000000..09d6db9 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/tests/_helpers.tpl @@ -0,0 +1,22 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Create a default fully qualified app name. +*/}} +{{- define "mongo-express.tests.fullname" -}} +{{- printf "%s-%s" (include "mongo-express.fullname" .) "tests" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Component labels +*/}} +{{- define "mongo-express.tests.componentLabels" -}} +app.kubernetes.io/component: tests +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "mongo-express.tests.labels" -}} +{{ include "mongo-express.labels" . }} +{{ include "mongo-express.tests.componentLabels" . }} +{{- end -}} diff --git a/utils/assets/charts/mongo-express/templates/tests/configmap.yaml b/utils/assets/charts/mongo-express/templates/tests/configmap.yaml new file mode 100644 index 0000000..dde1137 --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/tests/configmap.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mongo-express.tests.fullname" . }} + labels: + {{- include "mongo-express.tests.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + helm.sh/hook: test + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + test_all.py: | + import requests + + + def test_service_connection(): + url = "http://{{ include "mongo-express.fullname" . }}:{{ .Values.service.ports.http }}{{ .Values.siteBaseUrl }}" + + response = requests.get(url) + + assert response.status_code == 200 diff --git a/utils/assets/charts/mongo-express/templates/tests/pod.yaml b/utils/assets/charts/mongo-express/templates/tests/pod.yaml new file mode 100644 index 0000000..4be679e --- /dev/null +++ b/utils/assets/charts/mongo-express/templates/tests/pod.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Pod +metadata: + name: {{ include "mongo-express.tests.fullname" . }} + labels: + {{- include "mongo-express.tests.labels" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + helm.sh/hook: test + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- include "common.images.pullSecrets" ( dict "images" ( list .Values.tests.image ) "global" .Values.global ) | nindent 2 }} + containers: + - name: tests + image: {{ include "common.images.image" ( dict "imageRoot" .Values.tests.image "global" .Values.global ) }} + imagePullPolicy: {{ .Values.tests.image.pullPolicy }} + volumeMounts: + - name: tests + mountPath: /tests + readOnly: true + workingDir: /tests + restartPolicy: Never + volumes: + - name: tests + configMap: + name: {{ include "mongo-express.tests.fullname" . }} diff --git a/utils/assets/charts/mongo-express/values.yaml b/utils/assets/charts/mongo-express/values.yaml new file mode 100644 index 0000000..5c8656c --- /dev/null +++ b/utils/assets/charts/mongo-express/values.yaml @@ -0,0 +1,343 @@ +# Default values for mongo-express. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +## @section Global parameters + +global: + ## @param global.imageRegistry Global Docker image registry + imageRegistry: "" + + ## @param global.imagePullSecrets Global Docker registry secret names as an array + imagePullSecrets: [] + +## @section Common parameters + +## @param kubeVersion Override Kubernetes version +kubeVersion: "" + +## @param nameOverride Partially override `mongo-express.fullname` template with a string (will prepend the release name) +nameOverride: "" + +## @param fullnameOverride Fully override `mongo-express.fullname` template with a string +fullnameOverride: "" + +## @param commonAnnotations Annotations to add to all deployed objects +commonAnnotations: {} + +## @param commonLabels Labels to add to all deployed objects +commonLabels: {} + +## @param extraDeploy Array of extra objects to deploy with the release +extraDeploy: [] + +## @section Parameters + +## @param replicaCount Number of replicas +replicaCount: 1 + +image: + ## @param image.registry Image registry + registry: docker.io + + ## @param image.repository Image repository + repository: mongo-express + + ## @param image.tag Image tag + tag: 1.0.2 + + ## @param image.digest Image digest + digest: "" + + ## @param image.pullPolicy Image pull policy + pullPolicy: IfNotPresent + +pdb: + ## @param pdb.create Specifies whether a pod disruption budget should be created + create: false + + ## @param pdb.minAvailable Minimum number/percentage of pods that should remain scheduled + minAvailable: 1 + + ## @param pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable + maxUnavailable: + # maxUnavailable: 1 + +serviceAccount: + ## @param serviceAccount.create Specifies whether a service account should be created + create: true + + ## @param serviceAccount.annotations Service account annotations + annotations: {} + + ## @param serviceAccount.name The name of the service account to use (Generated using the `mongo-express.fullname` template if not set) + name: + +## @param deploymentAnnotations Additional deployment annotations +deploymentAnnotations: {} + +## @param podAnnotations Additional pod annotations +podAnnotations: {} + +## @param podLabels Additional pod labels +podLabels: {} + +## @param podSecurityContext Pod security context +podSecurityContext: {} + # fsGroup: 2000 + +## @param priorityClassName Priority class name +priorityClassName: +# priorityClassName : high-priority + +## @param runtimeClassName Runtime class name +runtimeClassName: "" + +## @param topologySpreadConstraints Topology Spread Constraints for pod assignment +topologySpreadConstraints: [] + +## @param securityContext Container security context +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +containerPorts: + ## @param containerPorts.http Container port for HTTP + http: 8081 + +livenessProbe: + ## @param livenessProbe.enabled Enable liveness probe + enabled: true + + ## @param livenessProbe.initialDelaySeconds Delay before the liveness probe is initiated + initialDelaySeconds: 0 + + ## @param livenessProbe.periodSeconds How often to perform the liveness probe + periodSeconds: 10 + + ## @param livenessProbe.timeoutSeconds When the liveness probe times out + timeoutSeconds: 1 + + ## @param livenessProbe.failureThreshold Minimum consecutive failures for the liveness probe to be considered failed after having succeeded + failureThreshold: 3 + + ## @param livenessProbe.successThreshold Minimum consecutive successes for the liveness probe to be considered successful after having failed + successThreshold: 1 + +readinessProbe: + ## @param readinessProbe.enabled Enable readiness probe + enabled: true + + ## @param readinessProbe.initialDelaySeconds Delay before the readiness probe is initiated + initialDelaySeconds: 0 + + ## @param readinessProbe.periodSeconds How often to perform the readiness probe + periodSeconds: 10 + + ## @param readinessProbe.timeoutSeconds When the readiness probe times out + timeoutSeconds: 1 + + ## @param readinessProbe.failureThreshold Minimum consecutive failures for the readiness probe to be considered failed after having succeeded + failureThreshold: 3 + + ## @param readinessProbe.successThreshold Minimum consecutive successes for the readiness probe to be considered successful after having failed + successThreshold: 1 + +startupProbe: + ## @param startupProbe.enabled Enable startup probe + enabled: false + + ## @param startupProbe.initialDelaySeconds Delay before the startup probe is initiated + initialDelaySeconds: 0 + + ## @param startupProbe.periodSeconds How often to perform the startup probe + periodSeconds: 10 + + ## @param startupProbe.timeoutSeconds When the startup probe times out + timeoutSeconds: 1 + + ## @param startupProbe.failureThreshold Minimum consecutive failures for the startup probe to be considered failed after having succeeded + failureThreshold: 3 + + ## @param startupProbe.successThreshold Minimum consecutive successes for the startup probe to be considered successful after having failed + successThreshold: 1 + +service: + ## @param service.annotations Service annotations + annotations: {} + + ## @param service.type Service type + type: ClusterIP + + ## @param service.clusterIP Static cluster IP address or None for headless service when service type is ClusterIP + clusterIP: + # clusterIP: 10.43.0.100 + + ## @param service.loadBalancerIP Static load balancer IP address when service type is LoadBalancer + loadBalancerIP: + # loadBalancerIP: 10.0.0.100 + + ## @param service.loadBalancerSourceRanges Source IP address ranges when service type is LoadBalancer + loadBalancerSourceRanges: + # - 10.0.0.0/24 + + ## @param service.externalTrafficPolicy External traffic routing policy when service type is LoadBalancer or NodePort + externalTrafficPolicy: Cluster + + ports: + ## @param service.ports.http Service port for HTTP + http: 8081 + + nodePorts: + ## @param service.nodePorts.http Service node port for HTTP when service type is LoadBalancer or NodePort + http: + # http: 30000 + +ingress: + ## @param ingress.enabled Enable ingress controller resource + enabled: false + + ## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress + ingressClassName: "" + + ## @param ingress.pathType Ingress path type + pathType: ImplementationSpecific + + ## @param ingress.annotations Ingress annotations + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + ## @param ingress.hosts[0].host Hostname to your Mongo Express installation + ## @param ingress.hosts[0].paths Paths within the url structure + hosts: + - host: mongo-express.local + paths: + - / + + ## @param ingress.tls TLS configuration + tls: [] + # - secretName: mongo-express-tls + # hosts: + # - mongo-express.local + +## @param resources CPU/Memory resource requests/limits +resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +## @param nodeSelector Node labels for pod assignment +nodeSelector: {} + +## @param tolerations Tolerations for pod assignment +tolerations: [] + +## @param affinity Map of node/pod affinities +affinity: {} + +## @param extraArgs Additional container arguments +extraArgs: {} + # name: "" + +## @param extraEnvVars Additional container environment variables +extraEnvVars: [] + # - name: MY-NAME + # value: "MY-VALUE" + +## @param extraEnvVarsCM Name of existing ConfigMap containing additional container environment variables +extraEnvVarsCM: + +## @param extraEnvVarsSecret Name of existing Secret containing additional container environment variables +extraEnvVarsSecret: + +## @section Config parameters + +## @param mongodbServer MongoDB host name or IP address +mongodbServer: mongodb + +## @param mongodbPort MongoDB port +mongodbPort: 27017 + +## @param mongodbEnableAdmin Enable administrator access +mongodbEnableAdmin: false + +## @param mongodbAdminUsername Administrator username +mongodbAdminUsername: root + +## @param mongodbAdminPassword Administrator password +mongodbAdminPassword: "" + +## @param mongodbAuthUsername Database username (only needed if `mongodbEnableAdmin` is `false`) +mongodbAuthUsername: "" + +## @param mongodbAuthPassword Database password (only needed if `mongodbEnableAdmin` is `false`) +mongodbAuthPassword: "" + +## @param mongodbAuthDatabase Database name (only needed if `mongodbEnableAdmin` is `false`) +mongodbAuthDatabase: "" + +## @param siteBaseUrl Set the express baseUrl to ease mounting at a subdirectory +siteBaseUrl: / + +## @param siteCookieSecret String used by cookie-parser middleware to sign cookies (Random 32 character long alphanumeric string if not set) +siteCookieSecret: "" + +## @param siteSessionSecret String used to sign the session ID cookie by express-session middleware (Random 32 character long alphanumeric string if not set) +siteSessionSecret: "" + +## @param basicAuthUsername Mongo Express web login name +basicAuthUsername: "" + +## @param basicAuthPassword Mongo Express web login password +basicAuthPassword: "" + +## @param existingSecret Name of existing Secret to use +existingSecret: "" + +## @param existingSecretKeyMongodbAdminPassword Key in existing Secret that contains administrator password +existingSecretKeyMongodbAdminPassword: mongodb-admin-password + +## @param existingSecretKeyMongodbAuthPassword Key in existing Secret that contains database password +existingSecretKeyMongodbAuthPassword: mongodb-auth-password + +## @param existingSecretKeySiteCookieSecret Key in existing Secret that contains string used by cookie-parser middleware to sign cookies +existingSecretKeySiteCookieSecret: site-cookie-secret + +## @param existingSecretKeySiteSessionSecret Key in existing Secret that contains string used to sign the session ID cookie by express-session middleware +existingSecretKeySiteSessionSecret: site-session-secret + +## @param existingSecretKeyBasicAuthPassword Key in existing Secret that contains Mongo Express web login password +existingSecretKeyBasicAuthPassword: basic-auth-password + +## @section MongoDB parameters + +mongodb: + ## @param mongodb.enabled Whether to use the MongoDB chart (for testing purposes only) + enabled: false + +## @section Tests parameters + +tests: + image: + ## @param tests.image.registry Image registry + registry: ghcr.io + + ## @param tests.image.repository Image repository + repository: cowboysysop/pytest + + ## @param tests.image.tag Image tag + tag: 1.0.41 + + ## @param tests.image.digest Image digest + digest: "" + + ## @param tests.image.pullPolicy Image pull policy + pullPolicy: IfNotPresent diff --git a/utils/assets/charts/mongodb/.helmignore b/utils/assets/charts/mongodb/.helmignore new file mode 100644 index 0000000..207983f --- /dev/null +++ b/utils/assets/charts/mongodb/.helmignore @@ -0,0 +1,25 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/utils/assets/charts/mongodb/.relok8s-images.yaml b/utils/assets/charts/mongodb/.relok8s-images.yaml new file mode 100644 index 0000000..81233da --- /dev/null +++ b/utils/assets/charts/mongodb/.relok8s-images.yaml @@ -0,0 +1,19 @@ +# relok8s image hints file +# This file makes this Helm Chart relocatable by relok8s +# More info here https://github.com/vmware-tanzu/asset-relocation-tool-for-kubernetes +# +# mongodb chart + +# mongodb image +- "{{.image.registry}}/{{.image.repository}}:{{.image.tag}}" +# kubectl image +- "{{.externalAccess.autoDiscovery.image.registry}}/{{.externalAccess.autoDiscovery.image.repository}}:{{.externalAccess.autoDiscovery.image.tag}}" +# mongodb-exporter image +- "{{.metrics.image.registry}}/{{.metrics.image.repository}}:{{.metrics.image.tag}}" +# nginx image +- "{{.tls.image.registry}}/{{.tls.image.repository}}:{{.tls.image.tag}}" +# os-shell image +- "{{.externalAccess.dnsCheck.image.registry}}/{{.externalAccess.dnsCheck.image.repository}}:{{.externalAccess.dnsCheck.image.tag}}" +# os-shell image +- "{{.volumePermissions.image.registry}}/{{.volumePermissions.image.repository}}:{{.volumePermissions.image.tag}}" + diff --git a/utils/assets/charts/mongodb/Chart.yaml b/utils/assets/charts/mongodb/Chart.yaml new file mode 100644 index 0000000..d539b77 --- /dev/null +++ b/utils/assets/charts/mongodb/Chart.yaml @@ -0,0 +1,45 @@ +annotations: + fips: "true" + images: | + - name: kubectl + version: 1.34.1 + image: registry-1.docker.io/bitnami/kubectl:latest + - name: mongodb + version: 8.2.1 + image: registry-1.docker.io/bitnami/mongodb:latest + - name: mongodb-exporter + version: 0.47.1 + image: registry-1.docker.io/bitnami/mongodb-exporter:latest + - name: nginx + version: 1.29.3 + image: registry-1.docker.io/bitnami/nginx:latest + - name: os-shell + version: "5" + image: registry-1.docker.io/bitnami/os-shell:latest + licenses: Apache-2.0 + tanzuCategory: service +apiVersion: v2 +appVersion: 8.2.1 +dependencies: +- name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.33.2 +description: "MongoDB(R) is a relational open source NoSQL database. Easy to use, it stores data in JSON-like documents. Automated scalability and high-performance. Ideal for developing cloud native applications." +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/mongodb/img/mongodb-stack-220x234.png +keywords: +- mongodb +- database +- nosql +- cluster +- replicaset +- replication +maintainers: +- name: "Broadcom, Inc. All Rights Reserved." + url: https://github.com/bitnami/charts +name: mongodb +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/mongodb +version: 18.1.9 diff --git a/utils/assets/charts/mongodb/README.md b/utils/assets/charts/mongodb/README.md new file mode 100644 index 0000000..f925378 --- /dev/null +++ b/utils/assets/charts/mongodb/README.md @@ -0,0 +1,1362 @@ + + +# MongoDB® packaged by Bitnami + +MongoDB® is a relational open source NoSQL database. Easy to use, it stores data in JSON-like documents. Automated scalability and high-performance. Ideal for developing cloud native applications. + +[Overview of MongoDB®](http://www.mongodb.org) + +Disclaimer: The respective trademarks mentioned in the offering are owned by the respective companies. We do not provide a commercial license for any of these products. This listing has an open-source license. MongoDB® is run and maintained by MongoDB, which is a completely separate project from Bitnami. + +## TL;DR + +```console +helm install my-release oci://MY-OCI-REGISTRY/mongodb +``` + +> Tip: Did you know that this app is also available as a Kubernetes App on the Azure Marketplace? Kubernetes Apps are the easiest way to deploy Bitnami on AKS. Click [here](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/bitnami.mongodb-cnab) to see the listing on Azure Marketplace. + +## Why use Bitnami Secure Images? + +Those are hardened, minimal CVE images built and maintained by Bitnami. Bitnami Secure Images are based on the cloud-optimized, security-hardened enterprise [OS Photon Linux](https://vmware.github.io/photon/). Why choose BSI images? + +- Hardened secure images of popular open source software with Near-Zero Vulnerabilities +- Vulnerability Triage & Prioritization with VEX Statements, KEV and EPSS Scores +- Compliance focus with FIPS, STIG, and air-gap options, including secure bill of materials (SBOM) +- Software supply chain provenance attestation through in-toto +- First class support for the internet’s favorite Helm charts + +Each image comes with valuable security metadata. You can view the metadata in [our public catalog here](https://app-catalog.vmware.com/bitnami/apps). Note: Some data is only available with [commercial subscriptions to BSI](https://bitnami.com/). + +![Alt text](https://github.com/bitnami/containers/blob/main/BSI%20UI%201.png?raw=true "Application details") +![Alt text](https://github.com/bitnami/containers/blob/main/BSI%20UI%202.png?raw=true "Packaging report") + +If you are looking for our previous generation of images based on Debian Linux, please see the [Bitnami Legacy registry](https://hub.docker.com/u/bitnamilegacy). + +## Introduction + +This chart bootstraps a [MongoDB(®)](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Architecture + +This chart allows installing MongoDB(®) using two different architecture setups: `standalone` or `replicaset`. Use the `architecture` parameter to choose the one to use: + +```console +architecture="standalone" +architecture="replicaset" +``` + +### Standalone architecture + +The *standalone* architecture installs a deployment (or StatefulSet) with one MongoDB® server (it cannot be scaled): + +```text + ---------------- + | MongoDB® | + | svc | + ---------------- + | + v + ------------ + |MongoDB®| + | Server | + | Pod | + ----------- +``` + +### Replicaset architecture + +The chart also supports the *replicaset* architecture with and without a MongoDB(®) Arbiter: + +When the MongoDB(®) Arbiter is enabled, the chart installs two StatefulSets: A StatefulSet with N MongoDB(®) servers (organised with one primary and N-1 secondary nodes), and a StatefulSet with one MongoDB(®) arbiter node (it cannot be scaled). + +```text + ---------------- ---------------- ---------------- ------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | | Arbiter | + | external svc | | external svc | | external svc | | svc | + ---------------- ---------------- ---------------- ------------- + | | | | + v v v v + ---------------- ---------------- ---------------- -------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | | MongoDB® | + | Server | | Server | | Server | | Arbiter | + | Pod | | Pod | | Pod | | Pod | + ---------------- ---------------- ---------------- -------------- + primary secondary secondary +``` + +The PSA model is useful when the third Availability Zone cannot hold a full MongoDB(®) instance. The MongoDB(®) Arbiter as decision maker is lightweight and can run alongside other workloads. + +> NOTE: An update takes your MongoDB(®) replicaset offline if the Arbiter is enabled and the number of MongoDB(®) replicas is two. Helm applies updates to the StatefulSets for the MongoDB(®) instance and the Arbiter at the same time so you lose two out of three quorum votes. + +Without the Arbiter, the chart deploys a single statefulset with N MongoDB(®) servers (organised with one primary and N-1 secondary nodes). + +```text + ---------------- ---------------- ---------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | + | external svc | | external svc | | external svc | + ---------------- ---------------- ---------------- + | | | + v v v + ---------------- ---------------- ---------------- + | MongoDB® 0 | | MongoDB® 1 | | MongoDB® N | + | Server | | Server | | Server | + | Pod | | Pod | | Pod | + ---------------- ---------------- ---------------- + primary secondary secondary +``` + +There are no services load balancing requests between MongoDB(®) nodes; instead, each node has an associated service to access them individually. + +> NOTE: Although the first replica is initially assigned the primary role, any of the secondary nodes can become the primary if it is down, or during upgrades. Do not make any assumption about what replica has the primary role. Instead, configure your MongoDB(®) client with the list of MongoDB(®) hostnames so it can dynamically choose the node to send requests. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ +- PV provisioner support in the underlying infrastructure + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The command deploys MongoDB(®) on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Configuration and installation details + +### Resource requests and limits + +Bitnami charts allow setting resource requests and limits for all containers inside the chart deployment. These are inside the `resources` value (check parameter table). Setting requests is essential for production workloads and these should be adapted to your specific use case. + +To make this process easier, the chart contains the `resourcesPreset` values, which automatically sets the `resources` section according to different presets. Check these presets in [the bitnami/common chart](https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15). However, in production workloads using `resourcesPreset` is discouraged as it may not fully adapt to your specific needs. Find more information on container resource management in the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + +### Prometheus metrics + +This chart can be integrated with Prometheus by setting `metrics.enabled` to `true`. This will deploy a sidecar container with [mongodb_exporter](https://github.com/percona/mongodb_exporter) in all pods and a `metrics` service, which can be configured under the `metrics.service` section. This `metrics` service will have the necessary annotations to be automatically scraped by Prometheus. + +#### Prometheus requirements + +It is necessary to have a working installation of Prometheus or Prometheus Operator for the integration to work. Install the [Bitnami Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/prometheus) or the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) to easily have a working Prometheus in your cluster. + +#### Integration with Prometheus Operator + +The chart can deploy `ServiceMonitor` objects for integration with Prometheus Operator installations. To do so, set the value `metrics.serviceMonitor.enabled=true`. Ensure that the Prometheus Operator `CustomResourceDefinitions` are installed in the cluster or it will fail with the following error: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Install the [Bitnami Kube Prometheus helm chart](https://github.com/bitnami/charts/tree/main/bitnami/kube-prometheus) for having the necessary CRDs and the Prometheus Operator. + +### [Rolling vs Immutable tags](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html) + +It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. + +Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. + +### Customize a new MongoDB instance + +The [Bitnami MongoDB(®) image](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) supports the use of custom scripts to initialize a fresh instance. In order to execute the scripts, two options are available: + +- Specify them using the `initdbScripts` parameter as dict. +- Define an external Kubernetes ConfigMap with all the initialization scripts by setting the `initdbScriptsConfigMap` parameter. Note that this will override the previous option. + +The allowed script extensions are `.sh` and `.js`. + +### Replicaset: Access MongoDB(®) nodes from outside the cluster + +In order to access MongoDB(®) nodes from outside the cluster when using a replicaset architecture, a specific service per MongoDB(®) pod will be created. There are two ways of configuring external access: + +- Using LoadBalancer services +- Using NodePort services. + +#### Use LoadBalancer services + +Three alternatives are available to use *LoadBalancer* services: + +- Use random load balancer IP addresses using an *initContainer* that waits for the IP addresses to be ready and discovers them automatically. An example deployment configuration is shown below: + + ```yaml + architecture: replicaset + replicaCount: 2 + externalAccess: + enabled: true + service: + type: LoadBalancer + autoDiscovery: + enabled: true + serviceAccount: + create: true + automountServiceAccountToken: true + rbac: + create: true + ``` + + > NOTE: This option requires creating RBAC rules on clusters where RBAC policies are enabled. + +- Manually specify the load balancer IP addresses. An example deployment configuration is shown below, with the placeholder EXTERNAL-IP-ADDRESS-X used in place of the load balancer IP addresses: + + ```yaml + architecture: replicaset + replicaCount: 2 + externalAccess: + enabled: true + service: + type: LoadBalancer + loadBalancerIPs: + - 'EXTERNAL-IP-ADDRESS-1' + - 'EXTERNAL-IP-ADDRESS-2' + ``` + + > NOTE: This option requires knowing the load balancer IP addresses, so that each MongoDB® node's advertised hostname is configured with it. + +- Specify `externalAccess.service.publicNames`. These names must be resolvable by the MongoDB® containers. To ensure that, if this value is set, an initContainer is added to wait for the ip addresses associated to those names. We can combine this feature with `external-dns`, setting the required annotations to configure the load balancer names: + + ```yaml + architecture: replicaset + replicaCount: 2 + externalAccess: + enabled: true + service: + type: LoadBalancer + publicNames: + - 'mongodb-0.example.com' + - 'mongodb-1.example.com' + annotationsList: + - external-dns.alpha.kubernetes.io/hostname: mongodb-0.example.com + - external-dns.alpha.kubernetes.io/hostname: mongodb-1.example.com + ``` + + > NOTE: If register new DNS records for those names is not an option, the release can be upgraded setting `hostAliases` with the public IPs assigned to the external services. + +#### Use NodePort services + +Manually specify the node ports to use. An example deployment configuration is shown below, with the placeholder NODE-PORT-X used in place of the node ports: + +```text +architecture=replicaset +replicaCount=2 +externalAccess.enabled=true +externalAccess.service.type=NodePort +externalAccess.service.nodePorts[0]='NODE-PORT-1' +externalAccess.service.nodePorts[1]='NODE-PORT-2' +``` + +> NOTE: This option requires knowing the node ports that will be exposed, so each MongoDB® node's advertised hostname is configured with it. + +The pod will try to get the external IP address of the node using the command `curl -s https://ipinfo.io/IP-ADDRESS` unless the `externalAccess.service.domain` parameter is set. + +### Bootstrapping with an External Cluster + +This chart is equipped with the ability to bring online a set of Pods that connect to an existing MongoDB(®) deployment that lies outside of Kubernetes. This effectively creates a hybrid MongoDB(®) Deployment where both Pods in Kubernetes and Instances such as Virtual Machines can partake in a single MongoDB(®) Deployment. This is helpful in situations where one may be migrating MongoDB(®) from Virtual Machines into Kubernetes, for example. To take advantage of this, use the following as an example configuration: + +```yaml +externalAccess: + externalMaster: + enabled: true + host: external-mongodb-0.internal +``` + +:warning: To bootstrap MongoDB(®) with an external master that lies outside of Kubernetes, be sure to set up external access using any of the suggested methods in this chart to have connectivity between the MongoDB(®) members. :warning: + +### Add extra environment variables + +To add extra environment variables (useful for advanced operations like custom init scripts), use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: LOG_LEVEL + value: error +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` properties. + +### Use Sidecars and Init Containers + +If additional containers are needed in the same pod (such as additional metrics or logging exporters), they can be defined using the `sidecars` config parameter. + +```yaml +sidecars: +- name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +If these sidecars export extra ports, extra port definitions can be added using the `service.extraPorts` parameter (where available), as shown in the example below: + +```yaml +service: + extraPorts: + - name: extraPort + port: 11311 + targetPort: 11311 +``` + +> NOTE: This Helm chart already includes sidecar containers for the Prometheus exporters (where applicable). These can be activated by adding the `--enable-metrics=true` parameter at deployment time. The `sidecars` parameter should therefore only be used for any extra sidecar containers. + +If additional init containers are needed in the same pod, they can be defined using the `initContainers` parameter. Here is an example: + +```yaml +initContainers: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +Learn more about [sidecar containers](https://kubernetes.io/docs/concepts/workloads/pods/) and [init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +### Update credentials + +Bitnami charts, with its default settings, configure credentials at first boot. Any further change in the secrets or credentials can be done using one of the following methods: + +#### Manual update of the passwords and secrets + +- Update the user password following [the upstream documentation](https://www.mongodb.com/docs/manual/reference/method/db.changeUserPassword/) +- Update the password secret with the new values (replace the SECRET_NAME, PASSWORDS and ROOT_PASSWORD placeholders) + +```shell +kubectl create secret generic SECRET_NAME --from-literal=mongodb-passwords=PASSWORD --from-literal=mongodb-root-password=ROOT_PASSWORD --dry-run -o yaml | kubectl apply -f - +``` + +#### Automated update using a password update job + +The Bitnami MongoDB provides a password update job that will automatically change the MongoDB passwords when running helm upgrade. To enable the job set `passwordUpdateJob.enabled=true`. This job requires: + +- The new passwords: this is configured using either `auth.rootPassword`, `auth.passwords` and `metrics.passwords` (if applicable) or setting `auth.existingSecret`. +- The previous root password: This value is taken automatically from already deployed secret object. If you are using `auth.existingSecret` or `helm template` instead of `helm upgrade`, then set either `passwordUpdateJob.previousPasswords.rootPassword` or setting `passwordUpdateJob.previousPasswords.existingSecret`. + +In the following example we update only the root password via values.yaml in a MongoDB installation: + +```yaml +auth: + rootPassword: "newRootPassword123" +passwordUpdateJob: + enabled: true +``` + +In the following example we update the password via values.yaml in a MongoDB installation with replication and several usernames and databases (including metrics). + +```yaml +architecture: "replicaset" + +auth: + usernames: + - "user1" + - "user2" + rootPassword: "newRootPassword123" + passwords: + - "newUserPassword123" + - "newUserPassword144" + databases: + - "userdatabase" + - "userdatabase2" + +metrics: + username: "metricsuser" + password: "newMetricsPassword" + +passwordUpdateJob: + enabled: true +``` + +In this example we use two existing secrets (`new-password-secret` and `previous-password-secret`) to update several users and passwords (including metrics): + +```yaml +auth: + usernames: + - "user1" + - "user2" + databases: + - "userdatabase" + - "userdatabase2" + existingSecret: new-password-secret + +metrics: + username: "metricsuser" + +passwordUpdateJob: + enabled: true + previousPasswords: + existingSecret: previous-password-secret +``` + +You can add extra update commands using the `passwordUpdateJob.extraCommands` value. + +### Backup and restore + +Two different approaches are available to back up and restore Bitnami MongoDB® Helm chart deployments on Kubernetes: + +- Back up the data from the source deployment and restore it in a new deployment using MongoDB® built-in backup/restore tools. +- Back up the persistent volumes from the source deployment and attach them to a new deployment using Velero, a Kubernetes backup/restore tool. + +#### Method 1: Backup and restore data using MongoDB® built-in tools + +This method involves the following steps: + +- Use the *mongodump* tool to create a snapshot of the data in the source cluster. +- Create a new MongoDB® Cluster deployment and forward the MongoDB® Cluster service port for the new deployment. +- Restore the data using the *mongorestore* tool to import the backup to the new cluster. + +> NOTE: Under this approach, it is important to create the new deployment on the destination cluster using the same credentials as the original deployment on the source cluster. + +#### Method 2: Back up and restore persistent data volumes + +This method involves copying the persistent data volumes for the MongoDB® nodes and reusing them in a new deployment with [Velero](https://velero.io/), an open source Kubernetes backup/restore tool. This method is only suitable when: + +- The Kubernetes provider is [supported by Velero](https://velero.io/docs/latest/supported-providers/). +- Both clusters are on the same Kubernetes provider, as this is a requirement of [Velero's native support for migrating persistent volumes](https://velero.io/docs/latest/migration-case/). +- The restored deployment on the destination cluster will have the same name, namespace, topology and credentials as the original deployment on the source cluster. + +This method involves the following steps: + +- Install Velero on the source and destination clusters. +- Use Velero to back up the PersistentVolumes (PVs) used by the deployment on the source cluster. +- Use Velero to restore the backed-up PVs on the destination cluster. +- Create a new deployment on the destination cluster with the same chart, deployment name, credentials and other parameters as the original. This new deployment will use the restored PVs and hence the original data. + +Refer to our detailed [tutorial on backing up and restoring MongoDB® chart deployments on Kubernetes](https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-backup-restore-data-mongodb-kubernetes-index.html), which covers both these approaches, for more information. + +### Use custom Prometheus rules + +Custom Prometheus rules can be defined for the Prometheus Operator by using the `prometheusRule` parameter. A basic configuration example is shown below: + +```text + metrics: + enabled: true + prometheusRule: + enabled: true + rules: + - name: rule1 + rules: + - alert: HighRequestLatency + expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 + for: 10m + labels: + severity: page + annotations: + summary: High request latency +``` + +### Securing traffic using TLS + +This chart supports enabling SSL/TLS between nodes in the cluster, as well as between MongoDB(®) clients and nodes, by setting the `MONGODB_EXTRA_FLAGS` and `MONGODB_CLIENT_EXTRA_FLAGS` container environment variables, together with the correct `MONGODB_ADVERTISED_HOSTNAME`. To enable full TLS encryption, set the `tls.enabled` parameter to `true`. + +#### Generate the self-signed certificates via pre-install Helm hooks + +The `secrets-ca.yaml` file utilizes the Helm "pre-install" hook to ensure that the certificates will only be generated on chart install. + +The `genCA()` function will create a new self-signed x509 certificate authority. The `genSignedCert()` function creates an object with the certificate and key, which are base64-encoded and used in a YAML-like object. The `genSignedCert()` function is passed the CN, an empty IP list (the nil part), the validity and the CA created previously. + +A Kubernetes Secret is used to hold the signed certificate created above, and the `initContainer` sets up the rest. Using Helm's hook annotations ensures that the certificates will only be generated on chart install. This will prevent overriding the certificates if the chart is upgraded. + +#### Use your own CA + +To use your own CA, set `tls.caCert` and `tls.caKey` with appropriate base64 encoded data. The `secrets-ca.yaml` file will utilize this data to create the Secret. + +> NOTE: Currently, only RSA private keys are supported. + +#### Use your own certificates + +To use your own certificates, set `tls.standalone.existingSecret`, `tls.replicaset.existingSecrets`, `tls.hidden.existingSecrets` and/or `tls.arbiter.existingSecret` secrets according to your needs. All of them must be references to `kubernetes.io/tls` secrets and the certificates must be created using the same CA. The CA can be added directly to each secret using the `ca.crt` key: + +```shell +kubectl create secret tls "mongodb-0-cert" --cert="mongodb-0.crt" --key="mongodb-0.key" +kubectl patch secret "mongodb-0-cert" -p="{\"data\":{\"ca.crt\": \"$(cat ca.crt | base64 -w0 )\"}}" +``` + +Or adding it to the "endpoint certificate" and setting the value `tls.pemChainIncluded`. If we reuse the example above, the `mongodb-0.crt` file should include CA cert and we shouldn't need to patch the secret to add the `ca.crt` set key. + +> NOTE: Certificates should be signed for the fully qualified domain names. If `externalAccess.service.publicNames`is set, those names should be used in the certificates set in `tls.replicaset.existingSecrets`. + +#### Access the cluster + +To access the cluster, enable the init container which generates the MongoDB(®) server/client PEM key needed to access the cluster. Please be sure to include the `$my_hostname` section with your actual hostname, and the alternative hostnames section should contain the hostnames that should be allowed access to the MongoDB(®) replicaset. Additionally, if external access is enabled, the load balancer IP addresses are added to the alternative names list. + +> NOTE: You will be generating self-signed certificates for the MongoDB(®) deployment. The init container generates a new MongoDB(®) private key which will be used to create a Certificate Authority (CA) and the public certificate for the CA. The Certificate Signing Request will be created as well and signed using the private key of the CA previously created. Finally, the PEM bundle will be created using the private key and public certificate. This process will be repeated for each node in the cluster. + +#### Start the cluster + +After the certificates have been generated and made available to the containers at the correct mount points, the MongoDB(®) server will be started with TLS enabled. The options for the TLS mode will be one of `disabled`, `allowTLS`, `preferTLS`, or `requireTLS`. This value can be changed via the `MONGODB_EXTRA_FLAGS` field using the `tlsMode` parameter. The client should now be able to connect to the TLS-enabled cluster with the provided certificates. + +### Set Pod affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod affinity in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +### FIPS parameters + +The FIPS parameters only have effect if you are using images from the [Bitnami Secure Images catalog](https://go-vmware.broadcom.com/contact-us). + +For more information on this new support, please refer to the [FIPS Compliance section](https://techdocs.broadcom.com/us/en/vmware-tanzu/bitnami-secure-images/bitnami-secure-images/services/bsi-doc/security-frameworks-FIPS-compliance.html). + +## Persistence + +The [Bitnami MongoDB(®)](https://github.com/bitnami/containers/tree/main/bitnami/mongodb) image stores the MongoDB(®) data and configurations at the `/bitnami/mongodb` path of the container. + +The chart mounts a [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) at this location. The volume is created using dynamic volume provisioning. + +If you encounter errors when working with persistent volumes, refer to our [troubleshooting guide for persistent volumes](https://docs.bitnami.com/kubernetes/faq/troubleshooting/troubleshooting-persistence-volumes/). + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.defaultStorageClass` | Global default StorageClass for Persistent Volume(s) | `""` | +| `global.storageClass` | DEPRECATED: use global.defaultStorageClass instead | `""` | +| `global.namespaceOverride` | Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride | `""` | +| `global.defaultFips` | Default value for the FIPS configuration (allowed values: '', restricted, relaxed, off). Can be overriden by the 'fips' object | `restricted` | +| `global.security.allowInsecureImages` | Allows skipping image verification | `false` | +| `global.compatibility.openshift.adaptSecurityContext` | Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) | `auto` | + +### Common parameters + +| Name | Description | Value | +| ------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- | +| `nameOverride` | String to partially override mongodb.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override mongodb.fullname template | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release | `[]` | +| `commonLabels` | Add labels to all the deployed resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `commonAnnotations` | Common annotations to add to all Mongo resources (sub-charts are not considered). Evaluated as a template | `{}` | +| `topologyKey` | Override common lib default topology key. If empty - "kubernetes.io/hostname" is used | `""` | +| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` | +| `enableServiceLinks` | Whether information about services should be injected into pod's environment variable | `true` | +| `usePasswordFiles` | Mount credentials as files instead of using environment variables | `true` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `["infinity"]` | + +### MongoDB(®) parameters + +| Name | Description | Value | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| `image.registry` | MongoDB(®) image registry | `REGISTRY_NAME` | +| `image.repository` | MongoDB(®) image registry | `REPOSITORY_NAME/mongodb` | +| `image.digest` | MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `image.pullPolicy` | MongoDB(®) image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Set to true if you would like to see extra information on logs | `false` | +| `schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `architecture` | MongoDB(®) architecture (`standalone` or `replicaset`) | `standalone` | +| `useStatefulSet` | Set to true to use a StatefulSet instead of a Deployment (only when `architecture=standalone`) | `false` | +| `auth.enabled` | Enable authentication | `true` | +| `auth.rootUser` | MongoDB(®) root user | `root` | +| `auth.rootPassword` | MongoDB(®) root password | `""` | +| `auth.usernames` | List of custom users to be created during the initialization | `[]` | +| `auth.passwords` | List of passwords for the custom users set at `auth.usernames` | `[]` | +| `auth.databases` | List of custom databases to be created during the initialization | `[]` | +| `auth.username` | DEPRECATED: use `auth.usernames` instead | `""` | +| `auth.password` | DEPRECATED: use `auth.passwords` instead | `""` | +| `auth.database` | DEPRECATED: use `auth.databases` instead | `""` | +| `auth.replicaSetKey` | Key used for authentication in the replicaset (only when `architecture=replicaset`) | `""` | +| `auth.existingSecret` | Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) | `""` | +| `tls.enabled` | Enable MongoDB(®) TLS support between nodes in the cluster as well as between mongo clients and nodes | `false` | +| `tls.mTLS.enabled` | IF TLS support is enabled, require clients to provide certificates | `true` | +| `tls.autoGenerated` | Generate a custom CA and self-signed certificates | `true` | +| `tls.existingSecret` | Existing secret with TLS certificates (keys: `mongodb-ca-cert`, `mongodb-ca-key`) | `""` | +| `tls.caCert` | Custom CA certificated (base64 encoded) | `""` | +| `tls.caKey` | CA certificate private key (base64 encoded) | `""` | +| `tls.pemChainIncluded` | Flag to denote that the Certificate Authority (CA) certificates are bundled with the endpoint cert. | `false` | +| `tls.standalone.existingSecret` | Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `""` | +| `tls.replicaset.existingSecrets` | Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `[]` | +| `tls.hidden.existingSecrets` | Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `[]` | +| `tls.arbiter.existingSecret` | Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. | `""` | +| `tls.image.registry` | Init container TLS certs setup image registry | `REGISTRY_NAME` | +| `tls.image.repository` | Init container TLS certs setup image repository | `REPOSITORY_NAME/nginx` | +| `tls.image.digest` | Init container TLS certs setup image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `tls.image.pullPolicy` | Init container TLS certs setup image pull policy | `IfNotPresent` | +| `tls.image.pullSecrets` | Init container TLS certs specify docker-registry secret names as an array | `[]` | +| `tls.extraDnsNames` | Add extra dns names to the CA, can solve x509 auth issue for pod clients | `[]` | +| `tls.mode` | Allows to set the tls mode which should be used when tls is enabled (options: `allowTLS`, `preferTLS`, `requireTLS`) | `requireTLS` | +| `tls.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). | `nano` | +| `tls.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `tls.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `tls.securityContext` | Init container generate-tls-cert Security context | `{}` | +| `automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `hostAliases` | Add deployment host aliases | `[]` | +| `replicaSetName` | Name of the replica set (only when `architecture=replicaset`) | `rs0` | +| `replicaSetHostnames` | Enable DNS hostnames in the replicaset config (only when `architecture=replicaset`) | `true` | +| `enableIPv6` | Switch to enable/disable IPv6 on MongoDB(®) | `false` | +| `directoryPerDB` | Switch to enable/disable DirectoryPerDB on MongoDB(®) | `false` | +| `systemLogVerbosity` | MongoDB(®) system log verbosity level | `0` | +| `disableSystemLog` | Switch to enable/disable MongoDB(®) system log | `false` | +| `disableJavascript` | Switch to enable/disable MongoDB(®) server-side JavaScript execution | `false` | +| `enableJournal` | Switch to enable/disable MongoDB(®) Journaling | `true` | +| `configuration` | MongoDB(®) configuration file to be used for Primary and Secondary nodes | `""` | + +### replicaSetConfigurationSettings settings applied during runtime (not via configuration file) + +| Name | Description | Value | +| ----------------------------------------------- | --------------------------------------------------------------------------------------------------- | ------- | +| `replicaSetConfigurationSettings.enabled` | Enable MongoDB(®) Switch to enable/disable configuring MongoDB(®) run time rs.conf settings | `false` | +| `replicaSetConfigurationSettings.configuration` | run-time rs.conf settings | `{}` | +| `existingConfigmap` | Name of existing ConfigMap with MongoDB(®) configuration for Primary and Secondary nodes | `""` | +| `initdbScripts` | Dictionary of initdb scripts | `{}` | +| `initdbScriptsConfigMap` | Existing ConfigMap with custom initdb scripts | `""` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `args` | Override default container args (useful when using custom images) | `[]` | +| `extraFlags` | MongoDB(®) additional command line flags | `[]` | +| `extraEnvVars` | Extra environment variables to add to MongoDB(®) pods | `[]` | +| `extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | + +### MongoDB(®) statefulset parameters + +| Name | Description | Value | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `annotations` | Additional labels to be added to the MongoDB(®) statefulset. Evaluated as a template | `{}` | +| `labels` | Annotations to be added to the MongoDB(®) statefulset. Evaluated as a template | `{}` | +| `replicaCount` | Number of MongoDB(®) nodes | `2` | +| `updateStrategy.type` | Strategy to use to replace existing MongoDB(®) pods. When architecture=standalone and useStatefulSet=false, | `RollingUpdate` | +| `podManagementPolicy` | Pod management policy for MongoDB(®) | `OrderedReady` | +| `podAffinityPreset` | MongoDB(®) Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | MongoDB(®) Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | MongoDB(®) Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | MongoDB(®) Node label key to match Ignored if `affinity` is set. | `""` | +| `nodeAffinityPreset.values` | MongoDB(®) Node label values to match. Ignored if `affinity` is set. | `[]` | +| `affinity` | MongoDB(®) Affinity for pod assignment | `{}` | +| `nodeSelector` | MongoDB(®) Node labels for pod assignment | `{}` | +| `tolerations` | MongoDB(®) Tolerations for pod assignment | `[]` | +| `topologySpreadConstraints` | MongoDB(®) Spread Constraints for Pods | `[]` | +| `lifecycleHooks` | LifecycleHook for the MongoDB(®) container(s) to automate configuration before or after startup | `{}` | +| `terminationGracePeriodSeconds` | MongoDB(®) Termination Grace Period | `""` | +| `podLabels` | MongoDB(®) pod labels | `{}` | +| `podAnnotations` | MongoDB(®) Pod annotations | `{}` | +| `priorityClassName` | Name of the existing priority class to be used by MongoDB(®) pod(s) | `""` | +| `runtimeClassName` | Name of the runtime class to be used by MongoDB(®) pod(s) | `""` | +| `podSecurityContext.enabled` | Enable MongoDB(®) pod(s)' Security Context | `true` | +| `podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `podSecurityContext.fsGroup` | Group ID for the volumes of the MongoDB(®) pod(s) | `1001` | +| `podSecurityContext.sysctls` | sysctl settings of the MongoDB(®) pod(s)' | `[]` | +| `containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` | +| `resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `containerPorts.mongodb` | MongoDB(®) container port | `27017` | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `20` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `10` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `customLivenessProbe` | Override default liveness probe for MongoDB(®) containers | `{}` | +| `customReadinessProbe` | Override default readiness probe for MongoDB(®) containers | `{}` | +| `customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `initContainers` | Add additional init containers for the hidden node pod(s) | `[]` | +| `sidecars` | Add additional sidecar containers for the MongoDB(®) pod(s) | `[]` | +| `extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the MongoDB(®) container(s) | `[]` | +| `extraVolumes` | Optionally specify extra list of additional volumes to the MongoDB(®) statefulset | `[]` | +| `pdb.create` | Enable/disable a Pod Disruption Budget creation for MongoDB(®) pod(s) | `true` | +| `pdb.minAvailable` | Minimum number/percentage of MongoDB(®) pods that must still be available after the eviction | `""` | +| `pdb.maxUnavailable` | Maximum number/percentage of MongoDB(®) pods that may be made unavailable after the eviction. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. | `""` | + +### Traffic exposure parameters + +| Name | Description | Value | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | +| `service.nameOverride` | MongoDB(®) service name | `""` | +| `service.type` | Kubernetes Service type (only for standalone architecture) | `ClusterIP` | +| `service.portName` | MongoDB(®) service port name (only for standalone architecture) | `mongodb` | +| `service.ports.mongodb` | MongoDB(®) service port. | `27017` | +| `service.nodePorts.mongodb` | Port to bind to for NodePort and LoadBalancer service types (only for standalone architecture) | `""` | +| `service.clusterIP` | MongoDB(®) service cluster IP (only for standalone architecture) | `""` | +| `service.externalIPs` | Specify the externalIP value ClusterIP service type (only for standalone architecture) | `[]` | +| `service.loadBalancerIP` | loadBalancerIP for MongoDB(®) Service (only for standalone architecture) | `""` | +| `service.loadBalancerClass` | loadBalancerClass for MongoDB(®) Service (only for standalone architecture) | `""` | +| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer (only for standalone architecture) | `[]` | +| `service.allocateLoadBalancerNodePorts` | Wheter to allocate node ports when service type is LoadBalancer | `true` | +| `service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `service.annotations` | Provide any additional annotations that may be required | `{}` | +| `service.externalTrafficPolicy` | service external traffic policy (only for standalone architecture) | `Local` | +| `service.sessionAffinity` | Control where client requests go, to the same pod or round-robin. Allowed values: `ClientIP` or `None` | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity. Ignored if `service.sessionAffinity` is `None` | `{}` | +| `service.headless.annotations` | Annotations for the headless service. | `{}` | +| `service.publishNotReadyAddresses` | Indicates that any agent which deals with endpoints for this Service should disregard any indications of ready/not-ready | `false` | +| `externalAccess.enabled` | Enable Kubernetes external cluster access to MongoDB(®) nodes (only for replicaset architecture) | `false` | +| `externalAccess.autoDiscovery.enabled` | Enable using an init container to auto-detect external IPs by querying the K8s API | `false` | +| `externalAccess.autoDiscovery.image.registry` | Init container auto-discovery image registry | `REGISTRY_NAME` | +| `externalAccess.autoDiscovery.image.repository` | Init container auto-discovery image repository | `REPOSITORY_NAME/kubectl` | +| `externalAccess.autoDiscovery.image.digest` | Init container auto-discovery image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `externalAccess.autoDiscovery.image.pullPolicy` | Init container auto-discovery image pull policy | `IfNotPresent` | +| `externalAccess.autoDiscovery.image.pullSecrets` | Init container auto-discovery image pull secrets | `[]` | +| `externalAccess.autoDiscovery.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). | `nano` | +| `externalAccess.autoDiscovery.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `externalAccess.autoDiscovery.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `externalAccess.dnsCheck.image.registry` | Init container dns-check image registry | `REGISTRY_NAME` | +| `externalAccess.dnsCheck.image.repository` | Init container dns-check image repository | `REPOSITORY_NAME/kubectl` | +| `externalAccess.dnsCheck.image.digest` | Init container dns-check image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `externalAccess.dnsCheck.image.pullPolicy` | Init container dns-check image pull policy | `IfNotPresent` | +| `externalAccess.dnsCheck.image.pullSecrets` | Init container dns-check image pull secrets | `[]` | +| `externalAccess.dnsCheck.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). | `nano` | +| `externalAccess.dnsCheck.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `externalAccess.dnsCheck.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `externalAccess.externalMaster.enabled` | Use external master for bootstrapping | `false` | +| `externalAccess.externalMaster.host` | External master host to bootstrap from | `""` | +| `externalAccess.externalMaster.port` | Port for MongoDB(®) service external master host | `27017` | +| `externalAccess.service.type` | Kubernetes Service type for external access. Allowed values: NodePort, LoadBalancer or ClusterIP | `LoadBalancer` | +| `externalAccess.service.portName` | MongoDB(®) port name used for external access when service type is LoadBalancer | `mongodb` | +| `externalAccess.service.ports.mongodb` | MongoDB(®) port used for external access when service type is LoadBalancer | `27017` | +| `externalAccess.service.loadBalancerIPs` | Array of load balancer IPs for MongoDB(®) nodes | `[]` | +| `externalAccess.service.publicNames` | Array of public names. The size should be equal to the number of replicas. | `[]` | +| `externalAccess.service.loadBalancerClass` | loadBalancerClass when service type is LoadBalancer | `""` | +| `externalAccess.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | +| `externalAccess.service.allocateLoadBalancerNodePorts` | Whether to allocate node ports when service type is LoadBalancer | `true` | +| `externalAccess.service.externalTrafficPolicy` | MongoDB(®) service external traffic policy | `Local` | +| `externalAccess.service.nodePorts` | Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort | `[]` | +| `externalAccess.service.domain` | Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort | `""` | +| `externalAccess.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `externalAccess.service.annotations` | Service annotations for external access. These annotations are common for all services created. | `{}` | +| `externalAccess.service.annotationsList` | Service annotations for eache external service. This value contains a list allowing different annotations per each external service. | `[]` | +| `externalAccess.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin. Allowed values: `ClientIP` or `None` | `None` | +| `externalAccess.service.sessionAffinityConfig` | Additional settings for the sessionAffinity. Ignored if `externalAccess.service.sessionAffinity` is `None` | `{}` | +| `externalAccess.hidden.enabled` | Enable Kubernetes external cluster access to MongoDB(®) hidden nodes | `false` | +| `externalAccess.hidden.service.type` | Kubernetes Service type for external access. Allowed values: NodePort or LoadBalancer | `LoadBalancer` | +| `externalAccess.hidden.service.portName` | MongoDB(®) port name used for external access when service type is LoadBalancer | `mongodb` | +| `externalAccess.hidden.service.ports.mongodb` | MongoDB(®) port used for external access when service type is LoadBalancer | `27017` | +| `externalAccess.hidden.service.loadBalancerIPs` | Array of load balancer IPs for MongoDB(®) nodes | `[]` | +| `externalAccess.hidden.service.loadBalancerClass` | loadBalancerClass when service type is LoadBalancer | `""` | +| `externalAccess.hidden.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | +| `externalAccess.hidden.service.allocateLoadBalancerNodePorts` | Wheter to allocate node ports when service type is LoadBalancer | `true` | +| `externalAccess.hidden.service.externalTrafficPolicy` | MongoDB(®) service external traffic policy | `Local` | +| `externalAccess.hidden.service.nodePorts` | Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort. Length must be the same as replicaCount | `[]` | +| `externalAccess.hidden.service.domain` | Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort | `""` | +| `externalAccess.hidden.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `externalAccess.hidden.service.annotations` | Service annotations for external access | `{}` | +| `externalAccess.hidden.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin. Allowed values: `ClientIP` or `None` | `None` | +| `externalAccess.hidden.service.sessionAffinityConfig` | Additional settings for the sessionAffinity. Ignored if `externalAccess.hidden.service.sessionAffinity` is `None` | `{}` | + +### Password update job + +| Name | Description | Value | +| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `passwordUpdateJob.enabled` | Enable password update job | `false` | +| `passwordUpdateJob.backoffLimit` | set backoff limit of the job | `10` | +| `passwordUpdateJob.command` | Override default container command on mysql Primary container(s) (useful when using custom images) | `[]` | +| `passwordUpdateJob.args` | Override default container args on mysql Primary container(s) (useful when using custom images) | `[]` | +| `passwordUpdateJob.extraCommands` | Extra commands to pass to the generation job | `""` | +| `passwordUpdateJob.previousPasswords.rootPassword` | Previous root password (set if the password secret was already changed) | `""` | +| `passwordUpdateJob.previousPasswords.existingSecret` | Name of a secret containing the previous passwords (set if the password secret was already changed) | `""` | +| `passwordUpdateJob.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `passwordUpdateJob.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `passwordUpdateJob.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `passwordUpdateJob.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `passwordUpdateJob.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `passwordUpdateJob.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `passwordUpdateJob.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `passwordUpdateJob.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `passwordUpdateJob.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `passwordUpdateJob.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `passwordUpdateJob.podSecurityContext.enabled` | Enabled credential init job pods' Security Context | `true` | +| `passwordUpdateJob.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `passwordUpdateJob.podSecurityContext.sysctls` | Set kernel settings using the sysctl interface | `[]` | +| `passwordUpdateJob.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `passwordUpdateJob.podSecurityContext.fsGroup` | Set credential init job pod's Security Context fsGroup | `1001` | +| `passwordUpdateJob.extraEnvVars` | Array containing extra env vars to configure the credential init job | `[]` | +| `passwordUpdateJob.extraEnvVarsCM` | ConfigMap containing extra env vars to configure the credential init job | `""` | +| `passwordUpdateJob.extraEnvVarsSecret` | Secret containing extra env vars to configure the credential init job (in case of sensitive data) | `""` | +| `passwordUpdateJob.extraVolumes` | Optionally specify extra list of additional volumes for the credential init job | `[]` | +| `passwordUpdateJob.extraVolumeMounts` | Array of extra volume mounts to be added to the jwt Container (evaluated as template). Normally used with `extraVolumes`. | `[]` | +| `passwordUpdateJob.initContainers` | Add additional init containers for the mysql Primary pod(s) | `[]` | +| `passwordUpdateJob.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if passwordUpdateJob.resources is set (passwordUpdateJob.resources is recommended for production). | `micro` | +| `passwordUpdateJob.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `passwordUpdateJob.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `passwordUpdateJob.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `passwordUpdateJob.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `passwordUpdateJob.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `passwordUpdateJob.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `passwordUpdateJob.hostAliases` | Add deployment host aliases | `[]` | +| `passwordUpdateJob.annotations` | Add annotations to the job | `{}` | +| `passwordUpdateJob.podLabels` | Additional pod labels | `{}` | +| `passwordUpdateJob.podAnnotations` | Additional pod annotations | `{}` | + +### Network policy parameters + +| Name | Description | Value | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `networkPolicy.enabled` | Specifies whether a NetworkPolicy should be created | `true` | +| `networkPolicy.allowExternal` | Don't require server label for connections | `true` | +| `networkPolicy.allowExternalEgress` | Allow the pod to access any range of port and all destinations. | `true` | +| `networkPolicy.addExternalClientAccess` | Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. | `true` | +| `networkPolicy.extraIngress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.extraEgress` | Add extra ingress rules to the NetworkPolicy | `[]` | +| `networkPolicy.ingressPodMatchLabels` | Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `networkPolicy.ingressNSMatchLabels` | Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `networkPolicy.ingressNSPodMatchLabels` | Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. | `{}` | +| `persistence.enabled` | Enable MongoDB(®) data persistence using PVC | `true` | +| `persistence.name` | Name of the PVC and mounted volume | `datadir` | +| `persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `persistence.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `persistence.storageClass` | PVC Storage Class for MongoDB(®) data volume | `""` | +| `persistence.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `persistence.size` | PVC Storage Request for MongoDB(®) data volume | `8Gi` | +| `persistence.annotations` | PVC annotations | `{}` | +| `persistence.labels` | PVC labels | `{}` | +| `persistence.mountPath` | Path to mount the volume at | `/bitnami/mongodb` | +| `persistence.subPath` | Subdirectory of the volume to mount at | `""` | +| `persistence.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | +| `persistence.volumeClaimTemplates.requests` | Custom PVC requests attributes | `{}` | +| `persistence.volumeClaimTemplates.dataSource` | Add dataSource to the VolumeClaimTemplate | `{}` | +| `persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for MongoDB(®) Statefulset | `false` | +| `persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` | +| `persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` | + +### Backup parameters + +| Name | Description | Value | +| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `backup.enabled` | Enable the logical dump of the database "regularly" | `false` | +| `backup.cronjob.schedule` | Set the cronjob parameter schedule | `@daily` | +| `backup.cronjob.timeZone` | Set the cronjob parameter timeZone | `""` | +| `backup.cronjob.concurrencyPolicy` | Set the cronjob parameter concurrencyPolicy | `Allow` | +| `backup.cronjob.failedJobsHistoryLimit` | Set the cronjob parameter failedJobsHistoryLimit | `1` | +| `backup.cronjob.successfulJobsHistoryLimit` | Set the cronjob parameter successfulJobsHistoryLimit | `3` | +| `backup.cronjob.startingDeadlineSeconds` | Set the cronjob parameter startingDeadlineSeconds | `""` | +| `backup.cronjob.ttlSecondsAfterFinished` | Set the cronjob parameter ttlSecondsAfterFinished | `""` | +| `backup.cronjob.restartPolicy` | Set the cronjob parameter restartPolicy | `OnFailure` | +| `backup.cronjob.backoffLimit` | Set the cronjob parameter backoffLimit | `6` | +| `backup.cronjob.serviceAccount.name` | Set the cronjob parameter serviceAccountName. If you change from the default values make sure that the SA already exists. | `default` | +| `backup.cronjob.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `backup.cronjob.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `backup.cronjob.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `backup.cronjob.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `backup.cronjob.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `backup.cronjob.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `backup.cronjob.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `backup.cronjob.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `backup.cronjob.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `backup.cronjob.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `backup.cronjob.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `none` | +| `backup.cronjob.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `backup.cronjob.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `backup.cronjob.command` | Set backup container's command to run | `[]` | +| `backup.cronjob.labels` | Set the cronjob labels | `{}` | +| `backup.cronjob.annotations` | Set the cronjob annotations | `{}` | +| `backup.cronjob.storage.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` | +| `backup.cronjob.storage.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` | +| `backup.cronjob.storage.storageClass` | PVC Storage Class for the backup data volume | `""` | +| `backup.cronjob.storage.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `backup.cronjob.storage.size` | PVC Storage Request for the backup data volume | `8Gi` | +| `backup.cronjob.storage.annotations` | PVC annotations | `{}` | +| `backup.cronjob.storage.mountPath` | Path to mount the volume at | `/backup/mongodb` | +| `backup.cronjob.storage.subPath` | Subdirectory of the volume to mount at | `""` | +| `backup.cronjob.storage.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | + +### RBAC parameters + +| Name | Description | Value | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable creation of ServiceAccount for MongoDB(®) pods | `true` | +| `serviceAccount.name` | Name of the created serviceAccount | `""` | +| `serviceAccount.annotations` | Additional Service Account annotations | `{}` | +| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `false` | +| `rbac.create` | Whether to create & use RBAC resources or not | `false` | +| `rbac.rules` | Custom rules to create following the role specification | `[]` | +| `podSecurityPolicy.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | +| `podSecurityPolicy.allowPrivilegeEscalation` | Enable privilege escalation | `false` | +| `podSecurityPolicy.privileged` | Allow privileged | `false` | +| `podSecurityPolicy.spec` | Specify the full spec to use for Pod Security Policy | `{}` | + +### Volume Permissions parameters + +| Name | Description | Value | +| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` | +| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `volumePermissions.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). | `nano` | +| `volumePermissions.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `volumePermissions.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `volumePermissions.securityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `volumePermissions.securityContext.runAsUser` | User ID for the volumePermissions container | `0` | + +### Arbiter parameters + +| Name | Description | Value | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| `arbiter.enabled` | Enable deploying the arbiter | `true` | +| `arbiter.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `arbiter.hostAliases` | Add deployment host aliases | `[]` | +| `arbiter.configuration` | Arbiter configuration file to be used | `""` | +| `arbiter.existingConfigmap` | Name of existing ConfigMap with Arbiter configuration | `""` | +| `arbiter.command` | Override default container command (useful when using custom images) | `[]` | +| `arbiter.args` | Override default container args (useful when using custom images) | `[]` | +| `arbiter.extraFlags` | Arbiter additional command line flags | `[]` | +| `arbiter.extraEnvVars` | Extra environment variables to add to Arbiter pods | `[]` | +| `arbiter.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `arbiter.extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | +| `arbiter.annotations` | Additional labels to be added to the Arbiter statefulset | `{}` | +| `arbiter.labels` | Annotations to be added to the Arbiter statefulset | `{}` | +| `arbiter.topologySpreadConstraints` | MongoDB(®) Spread Constraints for arbiter Pods | `[]` | +| `arbiter.lifecycleHooks` | LifecycleHook for the Arbiter container to automate configuration before or after startup | `{}` | +| `arbiter.terminationGracePeriodSeconds` | Arbiter Termination Grace Period | `""` | +| `arbiter.updateStrategy.type` | Strategy that will be employed to update Pods in the StatefulSet | `RollingUpdate` | +| `arbiter.podManagementPolicy` | Pod management policy for MongoDB(®) | `OrderedReady` | +| `arbiter.schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `arbiter.podAffinityPreset` | Arbiter Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `arbiter.podAntiAffinityPreset` | Arbiter Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `arbiter.nodeAffinityPreset.type` | Arbiter Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `arbiter.nodeAffinityPreset.key` | Arbiter Node label key to match Ignored if `affinity` is set. | `""` | +| `arbiter.nodeAffinityPreset.values` | Arbiter Node label values to match. Ignored if `affinity` is set. | `[]` | +| `arbiter.affinity` | Arbiter Affinity for pod assignment | `{}` | +| `arbiter.nodeSelector` | Arbiter Node labels for pod assignment | `{}` | +| `arbiter.tolerations` | Arbiter Tolerations for pod assignment | `[]` | +| `arbiter.podLabels` | Arbiter pod labels | `{}` | +| `arbiter.podAnnotations` | Arbiter Pod annotations | `{}` | +| `arbiter.priorityClassName` | Name of the existing priority class to be used by Arbiter pod(s) | `""` | +| `arbiter.runtimeClassName` | Name of the runtime class to be used by Arbiter pod(s) | `""` | +| `arbiter.podSecurityContext.enabled` | Enable Arbiter pod(s)' Security Context | `true` | +| `arbiter.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `arbiter.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `arbiter.podSecurityContext.fsGroup` | Group ID for the volumes of the Arbiter pod(s) | `1001` | +| `arbiter.podSecurityContext.sysctls` | sysctl settings of the Arbiter pod(s)' | `[]` | +| `arbiter.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `arbiter.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `arbiter.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `arbiter.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `arbiter.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `arbiter.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `arbiter.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `arbiter.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `arbiter.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `arbiter.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `arbiter.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if arbiter.resources is set (arbiter.resources is recommended for production). | `small` | +| `arbiter.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `arbiter.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `arbiter.containerPorts.mongodb` | MongoDB(®) arbiter container port | `27017` | +| `arbiter.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `arbiter.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `arbiter.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `arbiter.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `arbiter.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `arbiter.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `arbiter.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `arbiter.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `arbiter.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `20` | +| `arbiter.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `arbiter.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `arbiter.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `arbiter.startupProbe.enabled` | Enable startupProbe | `false` | +| `arbiter.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `arbiter.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `arbiter.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `arbiter.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `arbiter.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `arbiter.customLivenessProbe` | Override default liveness probe for Arbiter containers | `{}` | +| `arbiter.customReadinessProbe` | Override default readiness probe for Arbiter containers | `{}` | +| `arbiter.customStartupProbe` | Override default startup probe for Arbiter containers | `{}` | +| `arbiter.initContainers` | Add additional init containers for the Arbiter pod(s) | `[]` | +| `arbiter.sidecars` | Add additional sidecar containers for the Arbiter pod(s) | `[]` | +| `arbiter.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the Arbiter container(s) | `[]` | +| `arbiter.extraVolumes` | Optionally specify extra list of additional volumes to the Arbiter statefulset | `[]` | +| `arbiter.pdb.create` | Enable/disable a Pod Disruption Budget creation for Arbiter pod(s) | `true` | +| `arbiter.pdb.minAvailable` | Minimum number/percentage of Arbiter pods that should remain scheduled | `""` | +| `arbiter.pdb.maxUnavailable` | Maximum number/percentage of Arbiter pods that may be made unavailable. Defaults to `1` if both `arbiter.pdb.minAvailable` and `arbiter.pdb.maxUnavailable` are empty. | `""` | +| `arbiter.service.nameOverride` | The arbiter service name | `""` | +| `arbiter.service.ports.mongodb` | MongoDB(®) service port | `27017` | +| `arbiter.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `arbiter.service.annotations` | Provide any additional annotations that may be required | `{}` | +| `arbiter.service.headless.annotations` | Annotations for the headless service. | `{}` | + +### Hidden Node parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `hidden.enabled` | Enable deploying the hidden nodes | `false` | +| `hidden.automountServiceAccountToken` | Mount Service Account token in pod | `false` | +| `hidden.hostAliases` | Add deployment host aliases | `[]` | +| `hidden.configuration` | Hidden node configuration file to be used | `""` | +| `hidden.existingConfigmap` | Name of existing ConfigMap with Hidden node configuration | `""` | +| `hidden.command` | Override default container command (useful when using custom images) | `[]` | +| `hidden.args` | Override default container args (useful when using custom images) | `[]` | +| `hidden.extraFlags` | Hidden node additional command line flags | `[]` | +| `hidden.extraEnvVars` | Extra environment variables to add to Hidden node pods | `[]` | +| `hidden.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `""` | +| `hidden.extraEnvVarsSecret` | Name of existing Secret containing extra env vars (in case of sensitive data) | `""` | +| `hidden.annotations` | Additional labels to be added to thehidden node statefulset | `{}` | +| `hidden.labels` | Annotations to be added to the hidden node statefulset | `{}` | +| `hidden.topologySpreadConstraints` | MongoDB(®) Spread Constraints for hidden Pods | `[]` | +| `hidden.lifecycleHooks` | LifecycleHook for the Hidden container to automate configuration before or after startup | `{}` | +| `hidden.replicaCount` | Number of hidden nodes (only when `architecture=replicaset`) | `1` | +| `hidden.terminationGracePeriodSeconds` | Hidden Termination Grace Period | `""` | +| `hidden.updateStrategy.type` | Strategy that will be employed to update Pods in the StatefulSet | `RollingUpdate` | +| `hidden.podManagementPolicy` | Pod management policy for hidden node | `OrderedReady` | +| `hidden.schedulerName` | Name of the scheduler (other than default) to dispatch pods | `""` | +| `hidden.podAffinityPreset` | Hidden node Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `hidden.podAntiAffinityPreset` | Hidden node Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `hidden.nodeAffinityPreset.type` | Hidden Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `hidden.nodeAffinityPreset.key` | Hidden Node label key to match Ignored if `affinity` is set. | `""` | +| `hidden.nodeAffinityPreset.values` | Hidden Node label values to match. Ignored if `affinity` is set. | `[]` | +| `hidden.affinity` | Hidden node Affinity for pod assignment | `{}` | +| `hidden.nodeSelector` | Hidden node Node labels for pod assignment | `{}` | +| `hidden.tolerations` | Hidden node Tolerations for pod assignment | `[]` | +| `hidden.podLabels` | Hidden node pod labels | `{}` | +| `hidden.podAnnotations` | Hidden node Pod annotations | `{}` | +| `hidden.priorityClassName` | Name of the existing priority class to be used by hidden node pod(s) | `""` | +| `hidden.runtimeClassName` | Name of the runtime class to be used by hidden node pod(s) | `""` | +| `hidden.podSecurityContext.enabled` | Enable Hidden pod(s)' Security Context | `true` | +| `hidden.podSecurityContext.fsGroupChangePolicy` | Set filesystem group change policy | `Always` | +| `hidden.podSecurityContext.supplementalGroups` | Set filesystem extra groups | `[]` | +| `hidden.podSecurityContext.fsGroup` | Group ID for the volumes of the Hidden pod(s) | `1001` | +| `hidden.podSecurityContext.sysctls` | sysctl settings of the Hidden pod(s)' | `[]` | +| `hidden.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` | +| `hidden.containerSecurityContext.seLinuxOptions` | Set SELinux options in container | `{}` | +| `hidden.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` | +| `hidden.containerSecurityContext.runAsGroup` | Set containers' Security Context runAsGroup | `1001` | +| `hidden.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` | +| `hidden.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` | +| `hidden.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `true` | +| `hidden.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` | +| `hidden.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` | +| `hidden.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` | +| `hidden.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if hidden.resources is set (hidden.resources is recommended for production). | `micro` | +| `hidden.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `hidden.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `hidden.containerPorts.mongodb` | MongoDB(®) hidden container port | `27017` | +| `hidden.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `hidden.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `hidden.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `20` | +| `hidden.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `hidden.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `hidden.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `hidden.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `hidden.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `hidden.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `20` | +| `hidden.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `hidden.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `hidden.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `hidden.startupProbe.enabled` | Enable startupProbe | `false` | +| `hidden.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `hidden.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `hidden.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `hidden.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `hidden.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `hidden.customLivenessProbe` | Override default liveness probe for hidden node containers | `{}` | +| `hidden.customReadinessProbe` | Override default readiness probe for hidden node containers | `{}` | +| `hidden.customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `hidden.initContainers` | Add init containers to the MongoDB(®) Hidden pods. | `[]` | +| `hidden.sidecars` | Add additional sidecar containers for the hidden node pod(s) | `[]` | +| `hidden.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the hidden node container(s) | `[]` | +| `hidden.extraVolumes` | Optionally specify extra list of additional volumes to the hidden node statefulset | `[]` | +| `hidden.pdb.create` | Enable/disable a Pod Disruption Budget creation for hidden node pod(s) | `true` | +| `hidden.pdb.minAvailable` | Minimum number/percentage of hidden node pods that should remain scheduled | `""` | +| `hidden.pdb.maxUnavailable` | Maximum number/percentage of hidden node pods that may be made unavailable. Defaults to `1` if both `hidden.pdb.minAvailable` and `hidden.pdb.maxUnavailable` are empty. | `""` | +| `hidden.persistence.enabled` | Enable hidden node data persistence using PVC | `true` | +| `hidden.persistence.medium` | Provide a medium for `emptyDir` volumes. | `""` | +| `hidden.persistence.storageClass` | PVC Storage Class for hidden node data volume | `""` | +| `hidden.persistence.accessModes` | PV Access Mode | `["ReadWriteOnce"]` | +| `hidden.persistence.size` | PVC Storage Request for hidden node data volume | `8Gi` | +| `hidden.persistence.annotations` | PVC annotations | `{}` | +| `hidden.persistence.mountPath` | The path the volume will be mounted at, useful when using different MongoDB(®) images. | `/bitnami/mongodb` | +| `hidden.persistence.subPath` | The subdirectory of the volume to mount to, useful in dev environments | `""` | +| `hidden.persistence.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` | +| `hidden.persistence.volumeClaimTemplates.requests` | Custom PVC requests attributes | `{}` | +| `hidden.persistence.volumeClaimTemplates.dataSource` | Set volumeClaimTemplate dataSource | `{}` | +| `hidden.service.nameOverride` | The hidden service name | `""` | +| `hidden.service.portName` | MongoDB(®) service port name | `mongodb` | +| `hidden.service.ports.mongodb` | MongoDB(®) service port | `27017` | +| `hidden.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `hidden.service.annotations` | Provide any additional annotations that may be required | `{}` | +| `hidden.service.headless.annotations` | Annotations for the headless service. | `{}` | + +### Metrics parameters + +| Name | Description | Value | +| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| `metrics.enabled` | Enable using a sidecar Prometheus exporter | `false` | +| `metrics.image.registry` | MongoDB(®) Prometheus exporter image registry | `REGISTRY_NAME` | +| `metrics.image.repository` | MongoDB(®) Prometheus exporter image repository | `REPOSITORY_NAME/mongodb-exporter` | +| `metrics.image.digest` | MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` | +| `metrics.image.pullPolicy` | MongoDB(®) Prometheus exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `metrics.username` | String with username for the metrics exporter | `""` | +| `metrics.password` | String with password for the metrics exporter | `""` | +| `metrics.compatibleMode` | Enables old style mongodb-exporter metrics | `true` | +| `metrics.collector.all` | Enable all collectors. Same as enabling all individual metrics | `false` | +| `metrics.collector.diagnosticdata` | Boolean Enable collecting metrics from getDiagnosticData | `true` | +| `metrics.collector.replicasetstatus` | Boolean Enable collecting metrics from replSetGetStatus | `true` | +| `metrics.collector.dbstats` | Boolean Enable collecting metrics from dbStats | `false` | +| `metrics.collector.topmetrics` | Boolean Enable collecting metrics from top admin command | `false` | +| `metrics.collector.indexstats` | Boolean Enable collecting metrics from $indexStats | `false` | +| `metrics.collector.collstats` | Boolean Enable collecting metrics from $collStats | `false` | +| `metrics.collector.collstatsColls` | List of \.\ to get $collStats | `[]` | +| `metrics.collector.indexstatsColls` | List - List of \.\ to get $indexStats | `[]` | +| `metrics.collector.collstatsLimit` | Number - Disable collstats, dbstats, topmetrics and indexstats collector if there are more than \ collections. 0=No limit | `0` | +| `metrics.extraFlags` | String with extra flags to the metrics exporter | `""` | +| `metrics.command` | Override default container command (useful when using custom images) | `[]` | +| `metrics.args` | Override default container args (useful when using custom images) | `[]` | +| `metrics.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). | `nano` | +| `metrics.resources` | Set container requests and limits for different resources like CPU or memory (essential for production workloads) | `{}` | +| `metrics.fips.openssl` | Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `""` | +| `metrics.fips.golang` | Configure Golang FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used | `relaxed` | +| `metrics.containerPort` | Port of the Prometheus metrics container | `9216` | +| `metrics.service.annotations` | Annotations for Prometheus Exporter pods. Evaluated as a template. | `{}` | +| `metrics.service.type` | Type of the Prometheus metrics service | `ClusterIP` | +| `metrics.service.ports.metrics` | Port of the Prometheus metrics service | `9216` | +| `metrics.service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `15` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `10` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `5` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `10` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.startupProbe.enabled` | Enable startupProbe | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `5` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `5` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `30` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.customLivenessProbe` | Override default liveness probe for MongoDB(®) containers | `{}` | +| `metrics.customReadinessProbe` | Override default readiness probe for MongoDB(®) containers | `{}` | +| `metrics.customStartupProbe` | Override default startup probe for MongoDB(®) containers | `{}` | +| `metrics.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the metrics container(s) | `[]` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using Prometheus Operator | `false` | +| `metrics.serviceMonitor.namespace` | Namespace which Prometheus is running in | `""` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | Specify the timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricsRelabelConfigs to apply to samples before ingestion. | `[]` | +| `metrics.serviceMonitor.labels` | Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with | `{}` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.prometheusRule.enabled` | Set this to true to create prometheusRules for Prometheus operator | `false` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so prometheusRules will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.namespace` | Namespace where prometheusRules resource should be created | `""` | +| `metrics.prometheusRule.rules` | Rules to be created, check values for an example | `[]` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set auth.rootPassword=secretpassword,auth.username=my-user,auth.password=my-password,auth.database=my-database \ + oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. + +The above command sets the MongoDB(®) `root` account password to `secretpassword`. Additionally, it creates a standard database user named `my-user`, with the password `my-password`, who has access to a database named `my-database`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +helm install my-release -f values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/mongodb/values.yaml) + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +### To 16.4.0 + +This version introduces image verification for security purposes. To disable it, set `global.security.allowInsecureImages` to `true`. More details at [GitHub issue](https://github.com/bitnami/charts/issues/30850). + +If authentication is enabled, it's necessary to set the `auth.rootPassword` (also `auth.replicaSetKey` when using a replicaset architecture) when upgrading for readiness/liveness probes to work properly. When you install this chart for the first time, some notes will be displayed providing the credentials you must use under the 'Credentials' section. Please note down the password, and run the command below to upgrade your chart: + +```console +helm upgrade my-release oci://REGISTRY_NAME/REPOSITORY_NAME/mongodb --set auth.rootPassword=[PASSWORD] (--set auth.replicaSetKey=[REPLICASETKEY]) +``` + +> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`. +> Note: you need to substitute the placeholders [PASSWORD] and [REPLICASETKEY] with the values obtained in the installation notes. + +### To 16.0.0 + +To upgrade to MongoDB `8.0` from a `7.0` deployment, the `7.0` deployment must have `featureCompatibilityVersion` set to `7.0`. Please refer to the [official documentation](https://www.mongodb.com/docs/manual/release-notes/8.0/#upgrade-procedures). + +### To 15.0.0 + +This major bump changes the following security defaults: + +- `runAsGroup` is changed from `0` to `1001` +- `readOnlyRootFilesystem` is set to `true` +- `resourcesPreset` is changed from `none` to the minimum size working in our test suites (NOTE: `resourcesPreset` is not meant for production usage, but `resources` adapted to your use case). +- `global.compatibility.openshift.adaptSecurityContext` is changed from `disabled` to `auto`. + +This could potentially break any customization or init scripts used in your deployment. If this is the case, change the default values to the previous ones. + +### To 12.0.0 + +This major release renames several values in this chart and adds missing features, in order to be inline with the rest of assets in the Bitnami charts repository. + +Affected values: + +- `strategyType` is replaced by `updateStrategy` +- `service.port` is renamed to `service.ports.mongodb` +- `service.nodePort` is renamed to `service.nodePorts.mongodb` +- `externalAccess.service.port` is renamed to `externalAccess.hidden.service.ports.mongodb` +- `rbac.role.rules` is renamed to `rbac.rules` +- `externalAccess.hidden.service.port` is renamed ot `externalAccess.hidden.service.ports.mongodb` +- `hidden.strategyType` is replaced by `hidden.updateStrategy` +- `metrics.serviceMonitor.relabellings` is renamed to `metrics.serviceMonitor.relabelings`(typo fixed) +- `metrics.serviceMonitor.additionalLabels` is renamed to `metrics.serviceMonitor.labels` + +Additionally also updates the MongoDB image dependency to it newest major, 5.0 + +### To 11.0.0 + +In this version, the mongodb-exporter bundled as part of this Helm chart was updated to a new version which, even it is not a major change, can contain breaking changes (from `0.11.X` to `0.30.X`). +Please visit the release notes from the upstream project at + +### To 10.0.0 + +[On November 13, 2020, Helm v2 support formally ended](https://github.com/helm/charts#status-of-the-project). This major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +### To 9.0.0 + +MongoDB(®) container images were updated to `4.4.x` and it can affect compatibility with older versions of MongoDB(®). Refer to the following guides to upgrade your applications: + +- [Standalone](https://docs.mongodb.com/manual/release-notes/4.4-upgrade-standalone/) +- [Replica Set](https://docs.mongodb.com/manual/release-notes/4.4-upgrade-replica-set/) + +### To 8.0.0 + +- Architecture used to configure MongoDB(®) as a replicaset was completely refactored. Now, both primary and secondary nodes are part of the same statefulset. +- Chart labels were adapted to follow the Helm charts best practices. +- This version introduces `bitnami/common`, a [library chart](https://helm.sh/docs/topics/library_charts/#helm) as a dependency. More documentation about this new utility could be found [here](https://github.com/bitnami/charts/tree/main/bitnami/common#bitnami-common-library-chart). Please, make sure that you have updated the chart dependencies before executing any upgrade. +- Several parameters were renamed or disappeared in favor of new ones on this major version. These are the most important ones: + - `replicas` is renamed to `replicaCount`. + - Authentication parameters are reorganized under the `auth.*` parameter: + - `usePassword` is renamed to `auth.enabled`. + - `mongodbRootPassword`, `mongodbUsername`, `mongodbPassword`, `mongodbDatabase`, and `replicaSet.key` are now `auth.rootPassword`, `auth.username`, `auth.password`, `auth.database`, and `auth.replicaSetKey` respectively. + - `securityContext.*` is deprecated in favor of `podSecurityContext` and `containerSecurityContext`. + - Parameters prefixed with `mongodb` are renamed removing the prefix. E.g. `mongodbEnableIPv6` is renamed to `enableIPv6`. + - Parameters affecting Arbiter nodes are reorganized under the `arbiter.*` parameter. + +Consequences: + +- Backwards compatibility is not guaranteed. To upgrade to `8.0.0`, install a new release of the MongoDB(®) chart, and migrate your data by creating a backup of the database, and restoring it on the new release. + +### To 7.0.0 + +From this version, the way of setting the ingress rules has changed. Instead of using `ingress.paths` and `ingress.hosts` as separate objects, you should now define the rules as objects inside the `ingress.hosts` value, for example: + +```yaml +ingress: + hosts: + - name: mongodb.local + path: / +``` + +### To 6.0.0 + +From this version, `mongodbEnableIPv6` is set to `false` by default in order to work properly in most k8s clusters, if you want to use IPv6 support, you need to set this variable to `true` by adding `--set mongodbEnableIPv6=true` to your `helm` command. +You can find more information in the [`bitnami/mongodb` image README](https://github.com/bitnami/containers/tree/main/bitnami/mongodb#readme). + +### To 5.0.0 + +When enabling replicaset configuration, backwards compatibility is not guaranteed unless you modify the labels used on the chart's statefulsets. +Use the workaround below to upgrade from versions previous to 5.0.0. The following example assumes that the release name is `my-release`: + +```console +kubectl delete statefulset my-release-mongodb-arbiter my-release-mongodb-primary my-release-mongodb-secondary --cascade=false +``` + +### Add extra deployment options + +To add extra deployments (useful for advanced features like sidecars), use the `extraDeploy` property. + +In the example below, you can find how to use a example here for a [MongoDB replica set pod labeler sidecar](https://github.com/combor/k8s-mongo-labeler-sidecar) to identify the primary pod and dynamically label it as the primary node: + +```yaml +extraDeploy: + - apiVersion: v1 + kind: Service + metadata: + name: mongodb-primary + namespace: default + labels: + app.kubernetes.io/component: mongodb + app.kubernetes.io/instance: mongodb + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: mongodb + spec: + type: NodePort + externalTrafficPolicy: Cluster + ports: + - name: mongodb-primary + port: 30001 + nodePort: 30001 + protocol: TCP + targetPort: mongodb + selector: + app.kubernetes.io/component: mongodb + app.kubernetes.io/instance: mongodb + app.kubernetes.io/name: mongodb + primary: "true" +``` + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/utils/assets/charts/mongodb/charts/common/.helmignore b/utils/assets/charts/mongodb/charts/common/.helmignore new file mode 100644 index 0000000..d0e1084 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/.helmignore @@ -0,0 +1,26 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# img folder +img/ +# Changelog +CHANGELOG.md diff --git a/utils/assets/charts/mongodb/charts/common/Chart.yaml b/utils/assets/charts/mongodb/charts/common/Chart.yaml new file mode 100644 index 0000000..fb0a86e --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/Chart.yaml @@ -0,0 +1,25 @@ +annotations: + fips: "true" + images: | + [] + licenses: Apache-2.0 +apiVersion: v2 +appVersion: 2.33.2 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://bitnami.com +icon: https://dyltqmyl993wv.cloudfront.net/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts/tree/main/bitnami/common +type: library +version: 2.33.2 diff --git a/utils/assets/charts/mongodb/charts/common/README.md b/utils/assets/charts/mongodb/charts/common/README.md new file mode 100644 index 0000000..90d377a --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/README.md @@ -0,0 +1,410 @@ + + +# Common library for Bitnami packages + +A Library Helm Chart for grouping common logic between bitnami charts. This chart is not deployable by itself. + +[Overview of Common](https://github.com/bitnami/charts/tree/main/bitnami/common) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 2.x.x + repository: oci://MY-OCI-REGISTRY +``` + +```console +helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +## Why use Bitnami Secure Images? + +Those are hardened, minimal CVE images built and maintained by Bitnami. Bitnami Secure Images are based on the cloud-optimized, security-hardened enterprise [OS Photon Linux](https://vmware.github.io/photon/). Why choose BSI images? + +- Hardened secure images of popular open source software with Near-Zero Vulnerabilities +- Vulnerability Triage & Prioritization with VEX Statements, KEV and EPSS Scores +- Compliance focus with FIPS, STIG, and air-gap options, including secure bill of materials (SBOM) +- Software supply chain provenance attestation through in-toto +- First class support for the internet’s favorite Helm charts + +Each image comes with valuable security metadata. You can view the metadata in [our public catalog here](https://app-catalog.vmware.com/bitnami/apps). Note: Some data is only available with [commercial subscriptions to BSI](https://bitnami.com/). + +![Alt text](https://github.com/bitnami/containers/blob/main/BSI%20UI%201.png?raw=true "Application details") +![Alt text](https://github.com/bitnami/containers/blob/main/BSI%20UI%202.png?raw=true "Packaging report") + +If you are looking for our previous generation of images based on Debian Linux, please see the [Bitnami Legacy registry](https://hub.docker.com/u/bitnamilegacy). + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3.8.0+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------ | +| `common.affinities.nodes.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes` | Return a nodeAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.topologyKey` | Return a topologyKey definition | `dict "topologyKey" "FOO"` | +| `common.affinities.pods.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods` | Return a podAffinity/podAntiAffinity definition | `dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------- | +| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | +| `common.capabilities.apiVersions.has` | Return true if the apiVersion is supported | `dict "version" "batch/v1" "context" $` | +| `common.capabilities.job.apiVersion` | Return the appropriate apiVersion for job. | `.` Chart context | +| `common.capabilities.cronjob.apiVersion` | Return the appropriate apiVersion for cronjob. | `.` Chart context | +| `common.capabilities.daemonset.apiVersion` | Return the appropriate apiVersion for daemonset. | `.` Chart context | +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | +| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | +| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | +| `common.capabilities.policy.apiVersion` | Return the appropriate apiVersion for podsecuritypolicy. | `.` Chart context | +| `common.capabilities.networkPolicy.apiVersion` | Return the appropriate apiVersion for networkpolicy. | `.` Chart context | +| `common.capabilities.apiService.apiVersion` | Return the appropriate apiVersion for APIService. | `.` Chart context | +| `common.capabilities.hpa.apiVersion` | Return the appropriate apiVersion for Horizontal Pod Autoscaler | `.` Chart context | +| `common.capabilities.vpa.apiVersion` | Return the appropriate apiVersion for Vertical Pod Autoscaler. | `.` Chart context | +| `common.capabilities.psp.supported` | Returns true if PodSecurityPolicy is supported | `.` Chart context | +| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | +| `common.capabilities.admissionConfiguration.supported` | Returns true if AdmissionConfiguration is supported | `.` Chart context | +| `common.capabilities.admissionConfiguration.apiVersion` | Return the appropriate apiVersion for AdmissionConfiguration. | `.` Chart context | +| `common.capabilities.podSecurityConfiguration.apiVersion` | Return the appropriate apiVersion for PodSecurityConfiguration. | `.` Chart context | + +### Certificates + +| Helper identifier | Description | Expected Input | +| ------------------ | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `common.certs.sans`| Returns a space-separated list of Subject Alternative Names (SANs) to create a TLS certificate | `dict "namespace" "default" "clusterDomain" "cluster.local" "serviceName" "my-service" "headlessServiceName" "my-service-headless"` | + +### Compatibility + +| Helper identifier | Description | Expected Input | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| `common.compatibility.isOpenshift` | Return true if the detected platform is Openshift | `.` Chart context | +| `common.compatibility.renderSecurityContext` | Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC | `dict "secContext" .Values.containerSecurityContext "context" $` | + +### Errors + +| Helper identifier | Description | Expected Input | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | +| `common.errors.insecureImages` | Throw error when original container images are replaced. The error can be bypassed by setting the `global.security.allowInsecureImages` to true. | `dict "images" (list .Values.path.to.the.imageRoot) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | +| `common.images.renderPullSecrets` | Return the proper Docker Image Registry Secret Names (evaluates values as templates) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $` | +| `common.images.version` | Return the proper image version | `dict "imageRoot" .Values.path.to.the.image "chart" .Chart` , see [ImageRoot](#imageroot) for the structure. | + +### Ingress + +| Helper identifier | Description | Expected Input | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | +| `common.ingress.certManagerRequest` | Prints "true" if required cert-manager annotations for TLS signed certificates are set in the Ingress annotations | `dict "annotations" .Values.path.to.the.ingress.annotations` | + +### Labels + +| Helper identifier | Description | Expected Input | +| --------------------------- | --------------------------------------------------------------------------- | ----------------- | +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Labels to use on `deploy.spec.selector.matchLabels` and `svc.spec.selector` | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.namespace` | Allow the release namespace to be overridden | `.` Chart context | +| `common.names.fullname.namespace` | Create a fully qualified app name adding the installation's namespace | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | +| `common.names.dependency.fullname` | Create a default fully qualified dependency name. | `dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $` | + +### Resources + +| Helper identifier | Description | Expected Input | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `common.resources.preset` | Return a resource request/limit object based on a given preset. These presets are for basic testing and not meant to be used in production. | `dict "type" "nano"` | + +### Secrets + +| Helper identifier | Description | Expected Input | +| --------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $`, length, strong, honorProvidedValues and chartName fields are optional. | +| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | +| `common.secrets.lookup` | Reuses the value from an existing secret, otherwise sets its value to a default value. | `dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $` | + +### Storage + +| Helper identifier | Description | Expected Input | +| ---------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `common.storage.class` | Return the proper Storage Class | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +| ---------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | +| `common.tplvalues.merge` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | +| `common.tplvalues.merge-overwrite` | Merge a list of values that contains template after rendering them. | `dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $` | + +### Utils + +| Helper identifier | Description | Expected Input | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | +| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | +| `common.utils.checksumTemplate` | Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376) | `dict "path" "/configmap.yaml" "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +| -------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- | +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.modifiedImages` | Warning about replaced images from the original. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | +| `common.warnings.resources` | Warning about not setting the resource object in all deployments. | `dict "sections" (list "path1" "path2") context $` | + +### FIPS + +| Helper identifier | Description | Expected Input | +| -------------------- | ------------------- | ------------------------------------------------------------------------------- | +| `common.fips.enabled` | Enable FIPS mode | `.` Chart context | +| `common.fips.config` | Configure FIPS mode | `dict "tech" "openssl|java|golang" "fips" .Values.fips "global" .Values.global` | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy.' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +#### What changes were introduced in this major version? + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +#### Considerations when upgrading to this version + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +#### Useful links + +- +- +- + +## License + +Copyright © 2025 Broadcom. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/utils/assets/charts/mongodb/charts/common/templates/_affinities.tpl b/utils/assets/charts/mongodb/charts/common/templates/_affinities.tpl new file mode 100644 index 0000000..c6ccc62 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_affinities.tpl @@ -0,0 +1,169 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a topologyKey definition +{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}} +*/}} +{{- define "common.affinities.topologyKey" -}} +{{ .topologyKey | default "kubernetes.io/hostname" -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: 1 + {{- range $extraPodAffinityTerms }} + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 8 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + weight: {{ .weight | default 1 -}} + {{- end -}} +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "extraNamespaces" (list "namespace1" "namespace2") "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $customLabels := default (dict) .customLabels -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}} +{{- $extraNamespaces := default (list) .extraNamespaces -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if $extraNamespaces }} + namespaces: + - {{ .context.Release.Namespace }} + {{- with $extraNamespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- range $extraPodAffinityTerms }} + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := .extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .namespaces }} + namespaces: + - {{ $.context.Release.Namespace }} + {{- with .namespaces }} + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 6 }} + {{- end }} + {{- end }} + topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }} + {{- end -}} +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_capabilities.tpl b/utils/assets/charts/mongodb/charts/common/templates/_capabilities.tpl new file mode 100644 index 0000000..58f58c1 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_capabilities.tpl @@ -0,0 +1,178 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- default (default .Capabilities.KubeVersion.Version .Values.kubeVersion) ((.Values.global).kubeVersion) -}} +{{- end -}} + +{{/* +Return true if the apiVersion is supported +Usage: +{{ include "common.capabilities.apiVersions.has" (dict "version" "batch/v1" "context" $) }} +*/}} +{{- define "common.capabilities.apiVersions.has" -}} +{{- $providedAPIVersions := default .context.Values.apiVersions ((.context.Values.global).apiVersions) -}} +{{- if and (empty $providedAPIVersions) (.context.Capabilities.APIVersions.Has .version) -}} + {{- true -}} +{{- else if has .version $providedAPIVersions -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- print "policy/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for job. +*/}} +{{- define "common.capabilities.job.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- print "batch/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "common.capabilities.daemonset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" .context -}} +{{- print "autoscaling/v2" -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Vertical Pod Autoscaler. +*/}} +{{- define "common.capabilities.vpa.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "autoscaling/v1beta2" -}} +{{- else -}} +{{- print "autoscaling/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if PodSecurityPolicy is supported +*/}} +{{- define "common.capabilities.psp.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if or (empty $kubeVersion) (semverCompare "<1.25-0" $kubeVersion) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if AdmissionConfiguration is supported +*/}} +{{- define "common.capabilities.admissionConfiguration.supported" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} + {{- true -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for AdmissionConfiguration. +*/}} +{{- define "common.capabilities.admissionConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "apiserver.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiserver.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for PodSecurityConfiguration. +*/}} +{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}} +{{- $kubeVersion := include "common.capabilities.kubeVersion" . -}} +{{- if and (not (empty $kubeVersion)) (semverCompare "<1.25-0" $kubeVersion) -}} +{{- print "pod-security.admission.config.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "pod-security.admission.config.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_certs.tpl b/utils/assets/charts/mongodb/charts/common/templates/_certs.tpl new file mode 100644 index 0000000..55efc51 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_certs.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Returns a space-separated list of Subject Alternative Names (SANs) to create a TLS certificate +Usage: +{{ include "common.certs.sans" (dict "namespace" "default" "clusterDomain" "cluster.local" "serviceName" "my-service" "headlessServiceName" "my-service-headless" "loopback" true "extraSANs" (list "custom.domain.com")) }} + +Params: + - namespace - String - Required - Namespace where the app which we are generating the certificate for is deployed. + - clusterDomain - String - Optional - Cluster domain. Default is "cluster.local". + - serviceName - String - Optional - App service name. If provided, the following SANs will be generated: + - serviceName.namespace.svc.clusterDomain + - serviceName.namespace.svc + - serviceName.namespace + - serviceName + - headlessServiceName - String - Optional - App headless service name. If provided, the following wildcard SANs will be generated: + - *.headlessServiceName.namespace.svc.clusterDomain + - *.headlessServiceName.namespace.svc + - *.headlessServiceName.namespace + - *.headlessServiceName + - extraSANs - List - Optional - Additional custom SANs to be added. + - loopback - Boolean - Optional - If true, "localhost" will be added to the SANs. +*/}} +{{- define "common.certs.sans" -}} +{{- $sans := list }} +{{- if .serviceName -}} + {{- $sans = append $sans (printf "%s.%s.svc.%s" .serviceName .namespace (default "cluster.local" .clusterDomain)) -}} + {{- $sans = append $sans (printf "%s.%s.svc" .serviceName .namespace) -}} + {{- $sans = append $sans (printf "%s.%s" .serviceName .namespace) -}} + {{- $sans = append $sans .serviceName -}} +{{- end -}} +{{- if .headlessServiceName -}} + {{- /* Include wildcard SANs for headless service */ -}} + {{- $sans = append $sans (printf "*.%s.%s.svc.%s" .headlessServiceName .namespace (default "cluster.local" .clusterDomain)) -}} + {{- $sans = append $sans (printf "*.%s.%s.svc" .headlessServiceName .namespace) -}} + {{- $sans = append $sans (printf "*.%s.%s" .headlessServiceName .namespace) -}} + {{- $sans = append $sans (printf "*.%s" .headlessServiceName) -}} +{{- end -}} +{{- range .extraSANs }} + {{- $sans = append $sans . -}} +{{- end -}} +{{- if (default false .loopback) -}} + {{- $sans = append $sans "localhost" }} +{{- end -}} +{{- join " " $sans | trim -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_compatibility.tpl b/utils/assets/charts/mongodb/charts/common/templates/_compatibility.tpl new file mode 100644 index 0000000..19c26db --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_compatibility.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return true if the detected platform is Openshift +Usage: +{{- include "common.compatibility.isOpenshift" . -}} +*/}} +{{- define "common.compatibility.isOpenshift" -}} +{{- if .Capabilities.APIVersions.Has "security.openshift.io/v1" -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Render a compatible securityContext depending on the platform. By default it is maintained as it is. In other platforms like Openshift we remove default user/group values that do not work out of the box with the restricted-v1 SCC +Usage: +{{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) -}} +*/}} +{{- define "common.compatibility.renderSecurityContext" -}} +{{- $adaptedContext := .secContext -}} + +{{- if (((.context.Values.global).compatibility).openshift) -}} + {{- if or (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "force") (and (eq .context.Values.global.compatibility.openshift.adaptSecurityContext "auto") (include "common.compatibility.isOpenshift" .context)) -}} + {{/* Remove incompatible user/group values that do not work in Openshift out of the box */}} + {{- $adaptedContext = omit $adaptedContext "fsGroup" "runAsUser" "runAsGroup" -}} + {{- if not .secContext.seLinuxOptions -}} + {{/* If it is an empty object, we remove it from the resulting context because it causes validation issues */}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* Remove empty seLinuxOptions object if global.compatibility.omitEmptySeLinuxOptions is set to true */}} +{{- if and (((.context.Values.global).compatibility).omitEmptySeLinuxOptions) (not .secContext.seLinuxOptions) -}} + {{- $adaptedContext = omit $adaptedContext "seLinuxOptions" -}} +{{- end -}} +{{/* Remove fields that are disregarded when running the container in privileged mode */}} +{{- if $adaptedContext.privileged -}} + {{- $adaptedContext = omit $adaptedContext "capabilities" -}} +{{- end -}} +{{- omit $adaptedContext "enabled" | toYaml -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_errors.tpl b/utils/assets/charts/mongodb/charts/common/templates/_errors.tpl new file mode 100644 index 0000000..fb704c9 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_errors.tpl @@ -0,0 +1,92 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Throw error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Throw error when original container images are replaced. +The error can be bypassed by setting the "global.security.allowInsecureImages" to true. In this case, +a warning message will be shown instead. + +Usage: +{{ include "common.errors.insecureImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.errors.insecureImages" -}} +{{- $relocatedImages := list -}} +{{- $replacedImages := list -}} +{{- $bitnamiLegacyImages := list -}} +{{- $retaggedImages := list -}} +{{- $globalRegistry := ((.context.Values.global).imageRegistry) -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $registryName := default .registry $globalRegistry -}} + {{- $fullImageNameNoTag := printf "%s/%s" $registryName .repository -}} + {{- $fullImageName := printf "%s:%s" $fullImageNameNoTag .tag -}} + {{- if not (contains $fullImageNameNoTag $originalImages) -}} + {{- if not (contains $registryName $originalImages) -}} + {{- $relocatedImages = append $relocatedImages $fullImageName -}} + {{- else if not (contains .repository $originalImages) -}} + {{- $replacedImages = append $replacedImages $fullImageName -}} + {{- if contains "docker.io/bitnamilegacy/" $fullImageNameNoTag -}} + {{- $bitnamiLegacyImages = append $bitnamiLegacyImages $fullImageName -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if not (contains (printf "%s:%s" .repository .tag) $originalImages) -}} + {{- $retaggedImages = append $retaggedImages $fullImageName -}} + {{- end -}} +{{- end -}} + +{{- if and (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) (((.context.Values.global).security).allowInsecureImages) -}} + {{- print "\n\n⚠ SECURITY WARNING: Verifying original container images was skipped. Please note this Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.\n" -}} +{{- else if (or (gt (len $relocatedImages) 0) (gt (len $replacedImages) 0)) -}} + {{- $errorString := "Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables." -}} + {{- $errorString = print $errorString "\n\nUnrecognized images:" -}} + {{- range (concat $relocatedImages $replacedImages) -}} + {{- $errorString = print $errorString "\n - " . -}} + {{- end -}} + {{- if and (eq (len $relocatedImages) 0) (eq (len $replacedImages) (len $bitnamiLegacyImages)) -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- else if or (contains "docker.io/bitnami/" $originalImages) (contains "docker.io/bitnamiprem/" $originalImages) (contains "docker.io/bitnamisecure/" $originalImages) -}} + {{- $errorString = print "\n\n⚠ ERROR: " $errorString -}} + {{- $errorString = print $errorString "\n\nIf you are sure you want to proceed with non-standard containers, you can skip container image verification by setting the global parameter 'global.security.allowInsecureImages' to true." -}} + {{- $errorString = print $errorString "\nFurther information can be obtained at https://github.com/bitnami/charts/issues/30850" -}} + {{- print $errorString | fail -}} + {{- else if gt (len $replacedImages) 0 -}} + {{- $errorString = print "\n\n⚠ WARNING: " $errorString -}} + {{- print $errorString -}} + {{- end -}} +{{- else if gt (len $retaggedImages) 0 -}} + {{- $warnString := "\n\n⚠ WARNING: Original containers have been retagged. Please note this Helm chart was tested, and validated on multiple platforms using a specific set of Bitnami and Bitnami Secure Images containers. Substituting original image tags could cause unexpected behavior." -}} + {{- $warnString = print $warnString "\n\nRetagged images:" -}} + {{- range $retaggedImages -}} + {{- $warnString = print $warnString "\n - " . -}} + {{- end -}} + {{- print $warnString -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_fips.tpl b/utils/assets/charts/mongodb/charts/common/templates/_fips.tpl new file mode 100644 index 0000000..fd0d06a --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_fips.tpl @@ -0,0 +1,73 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Enable FIPS features +{{ include "common.fips.enabled" . }} +*/}} +{{- define "common.fips.enabled" -}} + {{- $fips := .Chart.Annotations.fips -}} + {{- if eq "true" $fips -}} + {{- true -}} + {{- end -}} +{{- end -}} + +{{/* +Get FIPS environment variable value for the given tech +{{ include "common.fips.config" (dict "tech" "openssl|java|golang" "fips" .Values.fips "global" .Values.global) }} +*/}} +{{- define "common.fips.config" -}} + {{- $availableTechs := list "openssl" "java" "golang" -}} + {{- if not (has .tech $availableTechs) -}} + {{- printf "The common.fips.config method can only provide configuration for: %s" $availableTechs | fail -}} + {{- end -}} + {{- $tech := get (.fips) .tech -}} + {{- $value := $tech | default (.global).defaultFips -}} + {{- if empty $value -}} + {{- printf "Please configure a value for 'fips.%s' or 'global.defaultFips'" .tech | fail -}} + {{- else -}} + {{- $method := printf "common.fips.%s" .tech -}} + {{- include $method (dict "value" $value) | trim | print -}} + {{- end -}} +{{- end -}} + +{{/* +Map OpenSSL values for FIPS configuration +{{ include "common.fips.openssl" (dict "value" "restricted") }} +*/}} +{{- define "common.fips.openssl" -}} + {{- ternary "yes" "no" (eq .value "restricted") | print -}} +{{- end -}} + +{{/* +Map JAVA values for FIPS configuration +{{ include "common.fips.java" (dict "value" "restricted") }} +*/}} +{{- define "common.fips.java" -}} + {{- $suffix := ternary "original" .value (eq .value "off") -}} + {{- $javaSecurityFile := printf "java.security.%s" $suffix -}} + {{/* The two equals signs mean the property file will completely override the master properties file */}} + {{- $javaSecurityOpt := printf "-Djava.security.properties==/opt/bitnami/java/conf/security/%s" $javaSecurityFile -}} + {{- $bcModulesFlag := "--module-path=/opt/bitnami/bc-fips/" -}} + {{- $restrictedFlags := printf "%s %s" $bcModulesFlag $javaSecurityOpt -}} + + {{- ternary $restrictedFlags $javaSecurityOpt (eq .value "restricted") | print -}} +{{- end -}} + +{{/* +Map Golang values for FIPS configuration +{{ include "common.fips.golang" (dict "value" "restricted") }} +*/}} +{{- define "common.fips.golang" -}} + {{- if eq .value "restricted" -}} + {{- print "fips140=only" -}} + {{- else if eq .value "relaxed" -}} + {{- print "fips140=on" -}} + {{- else -}} + {{- print "fips140=off" -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_images.tpl b/utils/assets/charts/mongodb/charts/common/templates/_images.tpl new file mode 100644 index 0000000..76bb7ce --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_images.tpl @@ -0,0 +1,115 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name. +If image tag and digest are not defined, termination fallbacks to chart appVersion. +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $separator := ":" -}} +{{- $termination := .imageRoot.tag | toString -}} + +{{- if not .imageRoot.tag }} + {{- if .chart }} + {{- $termination = .chart.AppVersion | toString -}} + {{- end -}} +{{- end -}} +{{- if .imageRoot.digest }} + {{- $separator = "@" -}} + {{- $termination = .imageRoot.digest | toString -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}} +{{- else -}} + {{- printf "%s%s%s" $repositoryName $separator $termination -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- range ((.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end }} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets .name -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- range (($context.Values.global).imagePullSecrets) -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- if kindIs "map" . -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}} + {{- else -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) -}} +imagePullSecrets: + {{- range $pullSecrets | uniq }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion) +{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }} +*/}} +{{- define "common.images.version" -}} +{{- $imageTag := .imageRoot.tag | toString -}} +{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}} +{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}} + {{- $version := semver $imageTag -}} + {{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}} +{{- else -}} + {{- print .chart.AppVersion -}} +{{- end -}} +{{- end -}} + diff --git a/utils/assets/charts/mongodb/charts/common/templates/_ingress.tpl b/utils/assets/charts/mongodb/charts/common/templates/_ingress.tpl new file mode 100644 index 0000000..2d0dbf1 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_ingress.tpl @@ -0,0 +1,41 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_labels.tpl b/utils/assets/charts/mongodb/charts/common/templates/_labels.tpl new file mode 100644 index 0000000..4c98597 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_labels.tpl @@ -0,0 +1,46 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}} +{{- with .context.Chart.AppVersion -}} +{{- $_ := set $default "app.kubernetes.io/version" . -}} +{{- end -}} +{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | replace "+" "_" | quote }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}} + +We don't want to loop over custom labels appending them to the selector +since it's very likely that it will break deployments, services, etc. +However, it's important to overwrite the standard labels if the user +overwrote them on metadata.labels fields. +*/}} +{{- define "common.labels.matchLabels" -}} +{{- if and (hasKey . "customLabels") (hasKey . "context") -}} +{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }} +{{- else -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_names.tpl b/utils/assets/charts/mongodb/charts/common/templates/_names.tpl new file mode 100644 index 0000000..d5d0ae4 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_names.tpl @@ -0,0 +1,72 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $releaseName := regexReplaceAll "(-?[^a-z\\d\\-])+-?" (lower .Release.Name) "-" -}} +{{- if contains $name $releaseName -}} +{{- $releaseName | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" $releaseName $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_resources.tpl b/utils/assets/charts/mongodb/charts/common/templates/_resources.tpl new file mode 100644 index 0000000..4c73492 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_resources.tpl @@ -0,0 +1,50 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a resource request/limit object based on a given preset. +These presets are for basic testing and not meant to be used in production +{{ include "common.resources.preset" (dict "type" "nano") -}} +*/}} +{{- define "common.resources.preset" -}} +{{/* The limits are the requests increased by 50% (except ephemeral-storage and xlarge/2xlarge sizes)*/}} +{{- $presets := dict + "nano" (dict + "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "150m" "memory" "192Mi" "ephemeral-storage" "2Gi") + ) + "micro" (dict + "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "380m" "memory" "384Mi" "ephemeral-storage" "2Gi") + ) + "small" (dict + "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "768Mi" "ephemeral-storage" "2Gi") + ) + "medium" (dict + "requests" (dict "cpu" "500m" "memory" "1024Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "750m" "memory" "1536Mi" "ephemeral-storage" "2Gi") + ) + "large" (dict + "requests" (dict "cpu" "1.0" "memory" "2048Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "1.5" "memory" "3072Mi" "ephemeral-storage" "2Gi") + ) + "xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "3.0" "memory" "6144Mi" "ephemeral-storage" "2Gi") + ) + "2xlarge" (dict + "requests" (dict "cpu" "1.0" "memory" "3072Mi" "ephemeral-storage" "50Mi") + "limits" (dict "cpu" "6.0" "memory" "12288Mi" "ephemeral-storage" "2Gi") + ) + }} +{{- if hasKey $presets .type -}} +{{- index $presets .type | toYaml -}} +{{- else -}} +{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" .type (join "," (keys $presets)) | fail -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_secrets.tpl b/utils/assets/charts/mongodb/charts/common/templates/_secrets.tpl new file mode 100644 index 0000000..7868c00 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_secrets.tpl @@ -0,0 +1,192 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "honorProvidedValues" false "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + - failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets. + - skipB64enc - Boolean - Optional - Default to false. If set to true, no the secret will not be base64 encrypted. + - skipQuote - Boolean - Optional - Default to false. If set to true, no quotes will be added around the secret. + - honorProvidedValues - Boolean - Optional - Default to false. If set to true, the values in providedValues have higher priority than an existing secret +The order in which this function returns a secret password: + 1. Password provided via the values.yaml if honorProvidedValues = true + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 2. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 3. Password provided via the values.yaml if honorProvidedValues = false + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 4. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key | b64dec }} + {{- else if not (eq .failOnNew false) }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- end }} + +{{- if and $providedPasswordValue .honorProvidedValues }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} +{{- end }} + +{{- if not $password }} + {{- if $providedPasswordValue }} + {{- $password = tpl ($providedPasswordValue | toString) .context }} + {{- else }} + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- if not (eq .failOnNew false) }} + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + {{- end }} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle }} + {{- else }} + {{- $password = randAlphaNum $passwordLength }} + {{- end }} + {{- end -}} +{{- end -}} +{{- if not .skipB64enc }} +{{- $password = $password | b64enc }} +{{- end -}} +{{- if .skipQuote -}} +{{- printf "%s" $password -}} +{{- else -}} +{{- printf "%s" $password | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Reuses the value from an existing secret, otherwise sets its value to a default value. + +Usage: +{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - context - Context - Required - Parent context. + +*/}} +{{- define "common.secrets.lookup" -}} +{{- $value := "" -}} +{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}} +{{- if and $secretData (hasKey $secretData .key) -}} + {{- $value = index $secretData .key -}} +{{- else if .defaultValue -}} + {{- $value = .defaultValue | toString | b64enc -}} +{{- end -}} +{{- if $value -}} +{{- printf "%s" $value -}} +{{- end -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_storage.tpl b/utils/assets/charts/mongodb/charts/common/templates/_storage.tpl new file mode 100644 index 0000000..aa75856 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_storage.tpl @@ -0,0 +1,21 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} +{{- $storageClass := (.global).storageClass | default .persistence.storageClass | default (.global).defaultStorageClass | default "" -}} +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else -}} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_tplvalues.tpl b/utils/assets/charts/mongodb/charts/common/templates/_tplvalues.tpl new file mode 100644 index 0000000..a04f4c1 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,52 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template perhaps with scope if the scope is present. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }} +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }} +{{- if contains "{{" (toJson .value) }} + {{- if .scope }} + {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }} + {{- else }} + {{- tpl $value .context }} + {{- end }} +{{- else }} + {{- $value }} +{{- end }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge +Usage: +{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} + +{{/* +Merge a list of values that contains template after rendering them. +Merge precedence is consistent with https://masterminds.github.io/sprig/dicts.html#mergeoverwrite-mustmergeoverwrite +Usage: +{{ include "common.tplvalues.merge-overwrite" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }} +*/}} +{{- define "common.tplvalues.merge-overwrite" -}} +{{- $dst := dict -}} +{{- range .values -}} +{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | mergeOverwrite $dst -}} +{{- end -}} +{{ $dst | toYaml }} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_utils.tpl b/utils/assets/charts/mongodb/charts/common/templates/_utils.tpl new file mode 100644 index 0000000..d53c74a --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_utils.tpl @@ -0,0 +1,77 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376). +Usage: +{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }} +*/}} +{{- define "common.utils.checksumTemplate" -}} +{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}} +{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/_warnings.tpl b/utils/assets/charts/mongodb/charts/common/templates/_warnings.tpl new file mode 100644 index 0000000..62c44df --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/_warnings.tpl @@ -0,0 +1,109 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html +{{- end }} +{{- end -}} + +{{/* +Warning about replaced images from the original. +Usage: +{{ include "common.warnings.modifiedImages" (dict "images" (list .Values.path.to.the.imageRoot) "context" $) }} +*/}} +{{- define "common.warnings.modifiedImages" -}} +{{- $affectedImages := list -}} +{{- $printMessage := false -}} +{{- $originalImages := .context.Chart.Annotations.images -}} +{{- range .images -}} + {{- $fullImageName := printf (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- if not (contains $fullImageName $originalImages) }} + {{- $affectedImages = append $affectedImages (printf "%s/%s:%s" .registry .repository .tag) -}} + {{- $printMessage = true -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables. + +Substituted images detected: +{{- range $affectedImages }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Warning about not setting the resource object in all deployments. +Usage: +{{ include "common.warnings.resources" (dict "sections" (list "path1" "path2") context $) }} +Example: +{{- include "common.warnings.resources" (dict "sections" (list "csiProvider.provider" "server" "volumePermissions" "") "context" $) }} +The list in the example assumes that the following values exist: + - csiProvider.provider.resources + - server.resources + - volumePermissions.resources + - resources +*/}} +{{- define "common.warnings.resources" -}} +{{- $values := .context.Values -}} +{{- $printMessage := false -}} +{{ $affectedSections := list -}} +{{- range .sections -}} + {{- if eq . "" -}} + {{/* Case where the resources section is at the root (one main deployment in the chart) */}} + {{- if not (index $values "resources") -}} + {{- $affectedSections = append $affectedSections "resources" -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Case where the are multiple resources sections (more than one main deployment in the chart) */}} + {{- $keys := split "." . -}} + {{/* We iterate through the different levels until arriving to the resource section. Example: a.b.c.resources */}} + {{- $section := $values -}} + {{- range $keys -}} + {{- $section = index $section . -}} + {{- end -}} + {{- if not (index $section "resources") -}} + {{/* If the section has enabled=false or replicaCount=0, do not include it */}} + {{- if and (hasKey $section "enabled") -}} + {{- if index $section "enabled" -}} + {{/* enabled=true */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else if and (hasKey $section "replicaCount") -}} + {{/* We need a casting to int because number 0 is not treated as an int by default */}} + {{- if (gt (index $section "replicaCount" | int) 0) -}} + {{/* replicaCount > 0 */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- else -}} + {{/* Default case, add it to the affected sections */}} + {{- $affectedSections = append $affectedSections (printf "%s.resources" .) -}} + {{- $printMessage = true -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- if $printMessage }} + +WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs: +{{- range $affectedSections }} + - {{ . }} +{{- end }} ++info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/validations/_cassandra.tpl b/utils/assets/charts/mongodb/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 0000000..f8fd213 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/validations/_mariadb.tpl b/utils/assets/charts/mongodb/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 0000000..6ea8c0f --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,108 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/validations/_mongodb.tpl b/utils/assets/charts/mongodb/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 0000000..e678a6d --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/validations/_mysql.tpl b/utils/assets/charts/mongodb/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 0000000..fbb65c3 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,67 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/validations/_postgresql.tpl b/utils/assets/charts/mongodb/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 0000000..51d4716 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,105 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/validations/_redis.tpl b/utils/assets/charts/mongodb/charts/common/templates/validations/_redis.tpl new file mode 100644 index 0000000..9fedfef --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,48 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + + +{{/* vim: set filetype=mustache: */}} +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/templates/validations/_validations.tpl b/utils/assets/charts/mongodb/charts/common/templates/validations/_validations.tpl new file mode 100644 index 0000000..7cdee61 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,51 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/charts/common/values.yaml b/utils/assets/charts/mongodb/charts/common/values.yaml new file mode 100644 index 0000000..de2cac5 --- /dev/null +++ b/utils/assets/charts/mongodb/charts/common/values.yaml @@ -0,0 +1,8 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/utils/assets/charts/mongodb/templates/NOTES.txt b/utils/assets/charts/mongodb/templates/NOTES.txt new file mode 100644 index 0000000..a3931c8 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/NOTES.txt @@ -0,0 +1,176 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free. + Subscribe to Bitnami Secure Images to receive continued support and security updates. + More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267 + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ .Release.Namespace }} -ti -- bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + +{{- else }} + +{{- $replicaCount := int .Values.replicaCount }} +{{- $portNumber := int .Values.service.ports.mongodb }} +{{- $fullname := include "mongodb.fullname" . }} +{{- $releaseNamespace := include "mongodb.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- $mongoList := list }} +{{- range $e, $i := until $replicaCount }} +{{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $portNumber) }} +{{- end }} + +{{- if and (or (and (eq .Values.architecture "standalone") (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort"))) (and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled)) (not .Values.auth.enabled) }} +------------------------------------------------------------------------------- + WARNING + + By not enabling "mongodb.auth.enabled" you have most likely exposed the + MongoDB® service externally without any authentication mechanism. + + For security reasons, we strongly suggest that you enable authentication + setting the "mongodb.auth.enabled" parameter to "true". + +------------------------------------------------------------------------------- +{{- end }} + +** Please be patient while the chart is being deployed ** + +MongoDB® can be accessed on the following DNS name(s) and ports from within your cluster: + +{{- if eq .Values.architecture "replicaset" }} +{{ join "\n" $mongoList | nindent 4 }} +{{- else }} + + {{ $fullname }}.{{ $releaseNamespace }}.svc.{{ .Values.clusterDomain }} + +{{- end }} + +{{- if .Values.auth.enabled }} + +To get the root password run: + + export MONGODB_ROOT_PASSWORD=$(kubectl get secret --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.secretName" . }} -o jsonpath="{.data.mongodb-root-password}" | base64 -d) + +{{- end }} +{{- $customUsers := include "mongodb.customUsers" . -}} +{{- $customDatabases := include "mongodb.customDatabases" . -}} +{{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} +{{- $customUsersList := splitList "," $customUsers }} +{{- range $index, $user := $customUsersList }} + +To get the password for "{{ $user }}" run: + + export MONGODB_PASSWORD=$(kubectl get secret --namespace {{ include "mongodb.namespace" $ }} {{ include "mongodb.secretName" $ }} -o jsonpath="{.data.mongodb-passwords}" | base64 -d | awk -F',' '{print ${{ add 1 $index }}}') + +{{- end }} +{{- end }} + +To connect to your database, create a MongoDB® client container: + + kubectl run --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.fullname" . }}-client --rm --tty -i --restart='Never' --env="MONGODB_ROOT_PASSWORD=$MONGODB_ROOT_PASSWORD" --image {{ template "mongodb.image" . }} --command -- bash + +Then, run the following command: + + {{- if eq .Values.architecture "replicaset" }} + mongosh admin --host "{{ join "," $mongoList }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }} + {{- else }} + mongosh admin --host "{{ template "mongodb.service.nameOverride" . }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }} + {{- end }} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled }} + +To connect to your database nodes from outside, you need to add both primary and secondary nodes hostnames/IPs to your Mongo client. To obtain them, follow the instructions below: + +{{- if eq "NodePort" .Values.externalAccess.service.type }} +{{- if .Values.externalAccess.service.domain }} + + MongoDB® nodes domain: Use your provided hostname to reach MongoDB® nodes, {{ .Values.externalAccess.service.domain }} + +{{- else }} + + MongoDB® nodes domain: you can reach MongoDB® nodes on any of the K8s nodes external IPs. + + kubectl get nodes -o wide + +{{- end }} + + MongoDB® nodes port: You will have a different node port for each MongoDB® node. You can get the list of configured node ports using the command below: + + echo "$(kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -o jsonpath='{.items[*].spec.ports[0].nodePort}' | tr ' ' '\n')" + +{{- else if contains "LoadBalancer" .Values.externalAccess.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IPs to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -w' + + MongoDB® nodes domain: You will have a different external IP for each MongoDB® node. You can get the list of external IPs using the command below: + + echo "$(kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "mongodb.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=mongodb,pod" -o jsonpath='{.items[*].status.loadBalancer.ingress[0].ip}' | tr ' ' '\n')" + + MongoDB® nodes port: {{ .Values.externalAccess.service.ports.mongodb }} + +{{- end }} + +{{- else if eq .Values.architecture "standalone" }} + +To connect to your database from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ template "mongodb.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ template "mongodb.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "mongodb.service.nameOverride" . }}) + mongo --host $NODE_IP --port $NODE_PORT {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- else if contains "LoadBalancer" .Values.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ template "mongodb.namespace" . }} -w {{ template "mongodb.service.nameOverride" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ template "mongodb.namespace" . }} {{ template "mongodb.service.nameOverride" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + mongosh --host $SERVICE_IP --port {{ $portNumber }} {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- else if contains "ClusterIP" .Values.service.type }} + + kubectl port-forward --namespace {{ template "mongodb.namespace" . }} svc/{{ template "mongodb.service.nameOverride" . }} {{ $portNumber }}:{{ $portNumber }} & + mongosh --host 127.0.0.1 {{- if .Values.auth.enabled }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }} + +{{- end }} +{{- end }} + +{{- if .Values.metrics.enabled }} + +To access the MongoDB® Prometheus metrics, get the MongoDB® Prometheus URL by running: + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ printf "%s-metrics" (include "mongodb.fullname" .) }} {{ .Values.metrics.service.ports.metrics }}:{{ .Values.metrics.service.ports.metrics }} & + echo "Prometheus Metrics URL: http://127.0.0.1:{{ .Values.metrics.service.ports.metrics }}/metrics" + +Then, open the obtained URL in a browser. + +{{- end }} +{{- end }} +{{- include "common.warnings.rollingTag" .Values.image }} +{{- include "common.warnings.rollingTag" .Values.metrics.image }} +{{- include "common.warnings.rollingTag" .Values.externalAccess.autoDiscovery.image }} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} +{{- include "common.warnings.rollingTag" .Values.tls.image }} +{{- include "mongodb.validateValues" . }} +{{- include "common.warnings.resources" (dict "sections" (list "arbiter" "externalAccess.autoDiscovery" "hidden" "metrics" "" "tls" "volumePermissions") "context" $) }} +{{- include "common.warnings.modifiedImages" (dict "images" (list .Values.image .Values.tls.image .Values.externalAccess.autoDiscovery.image .Values.externalAccess.dnsCheck.image .Values.volumePermissions.image .Values.metrics.image) "context" $) }} +{{- include "common.errors.insecureImages" (dict "images" (list .Values.image .Values.tls.image .Values.externalAccess.autoDiscovery.image .Values.externalAccess.dnsCheck.image .Values.volumePermissions.image .Values.metrics.image) "context" $) }} diff --git a/utils/assets/charts/mongodb/templates/_helpers.tpl b/utils/assets/charts/mongodb/templates/_helpers.tpl new file mode 100644 index 0000000..dcecfdf --- /dev/null +++ b/utils/assets/charts/mongodb/templates/_helpers.tpl @@ -0,0 +1,733 @@ +{{/* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "mongodb.name" -}} +{{- include "common.names.name" . -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongodb.fullname" -}} +{{- include "common.names.fullname" . -}} +{{- end -}} + +{{/* +Create a default mongo service name which can be overridden. +*/}} +{{- define "mongodb.service.nameOverride" -}} + {{- if and .Values.service .Values.service.nameOverride -}} + {{- print .Values.service.nameOverride -}} + {{- else -}} + {{- if eq .Values.architecture "replicaset" -}} + {{- printf "%s-headless" (include "mongodb.fullname" .) -}} + {{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Create a default mongo arbiter service name which can be overridden. +*/}} +{{- define "mongodb.arbiter.service.nameOverride" -}} + {{- if and .Values.arbiter.service .Values.arbiter.service.nameOverride -}} + {{- print .Values.arbiter.service.nameOverride -}} + {{- else -}} + {{- printf "%s-arbiter-headless" (include "mongodb.fullname" .) -}} + {{- end }} +{{- end }} + +{{/* +Create a default mongo hidden service name which can be overridden. +*/}} +{{- define "mongodb.hidden.service.nameOverride" -}} + {{- if and .Values.hidden.service .Values.hidden.service.nameOverride -}} + {{- print .Values.hidden.service.nameOverride -}} + {{- else -}} + {{- printf "%s-hidden-headless" (include "mongodb.fullname" .) -}} + {{- end }} +{{- end }} + +{{/* +Return the proper MongoDB® image name +*/}} +{{- define "mongodb.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "mongodb.metrics.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "mongodb.volumePermissions.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container auto-discovery image) +*/}} +{{- define "mongodb.externalAccess.autoDiscovery.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.externalAccess.autoDiscovery.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the init container dns-check image) +*/}} +{{- define "mongodb.externalAccess.dnsCheck.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.externalAccess.dnsCheck.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper image name (for the TLS Certs image) +*/}} +{{- define "mongodb.tls.image" -}} +{{- include "common.images.image" (dict "imageRoot" .Values.tls.image "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "mongodb.imagePullSecrets" -}} +{{- include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image .Values.tls.image .Values.externalAccess.dnsCheck.image .Values.externalAccess.autoDiscovery.image) "context" $) -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "mongodb.namespace" -}} + {{- if and .Values.global .Values.global.namespaceOverride -}} + {{- print .Values.global.namespaceOverride -}} + {{- else -}} + {{- print .Release.Namespace -}} + {{- end }} +{{- end -}} +{{- define "mongodb.serviceMonitor.namespace" -}} + {{- if .Values.metrics.serviceMonitor.namespace -}} + {{- print .Values.metrics.serviceMonitor.namespace -}} + {{- else -}} + {{- include "mongodb.namespace" . -}} + {{- end }} +{{- end -}} +{{- define "mongodb.prometheusRule.namespace" -}} + {{- if .Values.metrics.prometheusRule.namespace -}} + {{- print .Values.metrics.prometheusRule.namespace -}} + {{- else -}} + {{- include "mongodb.namespace" . -}} + {{- end }} +{{- end -}} + +{{/* +Returns the proper service account name depending if an explicit service account name is set +in the values file. If the name is not set it will default to either mongodb.fullname if serviceAccount.create +is true or default otherwise. +*/}} +{{- define "mongodb.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{- default (include "mongodb.fullname" .) (print .Values.serviceAccount.name) -}} + {{- else -}} + {{- default "default" (print .Values.serviceAccount.name) -}} + {{- end -}} +{{- end -}} + +{{/* +Return the list of custom users to create during the initialization (string format) +*/}} +{{- define "mongodb.customUsers" -}} + {{- $customUsers := list -}} + {{- if .Values.auth.username -}} + {{- $customUsers = append $customUsers .Values.auth.username }} + {{- end }} + {{- range .Values.auth.usernames }} + {{- $customUsers = append $customUsers . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customUsers)) -}} +{{- end -}} + +{{/* +Return the list of passwords for the custom users (string format) +*/}} +{{- define "mongodb.customPasswords" -}} + {{- $customPasswords := list -}} + {{- if .Values.auth.password -}} + {{- $customPasswords = append $customPasswords .Values.auth.password }} + {{- end }} + {{- range .Values.auth.passwords }} + {{- $customPasswords = append $customPasswords . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customPasswords)) -}} +{{- end -}} + +{{/* +Return the list of custom databases to create during the initialization (string format) +*/}} +{{- define "mongodb.customDatabases" -}} + {{- $customDatabases := list -}} + {{- if .Values.auth.database -}} + {{- $customDatabases = append $customDatabases .Values.auth.database }} + {{- end }} + {{- range .Values.auth.databases }} + {{- $customDatabases = append $customDatabases . }} + {{- end }} + {{- printf "%s" (default "" (join "," $customDatabases)) -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration +*/}} +{{- define "mongodb.configmapName" -}} +{{- if .Values.existingConfigmap -}} + {{- printf "%s" (tpl .Values.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® +*/}} +{{- define "mongodb.createConfigmap" -}} +{{- if and .Values.configuration (not .Values.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret with MongoDB® credentials +*/}} +{{- define "mongodb.secretName" -}} + {{- if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} + {{- else -}} + {{- printf "%s" (include "mongodb.fullname" .) -}} + {{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for MongoDB® +*/}} +{{- define "mongodb.createSecret" -}} +{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created for MongoDB +*/}} +{{- define "mongodb.createPreviousSecret" -}} +{{- if and .Values.passwordUpdateJob.previousPasswords.rootPassword (not .Values.passwordUpdateJob.previousPasswords.existingSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret with previous MongoDB credentials +*/}} +{{- define "mongodb.update-job.previousSecretName" -}} + {{- if .Values.passwordUpdateJob.previousPasswords.existingSecret -}} + {{- /* The secret with the new password is managed externally */ -}} + {{- tpl .Values.passwordUpdateJob.previousPasswords.existingSecret $ -}} + {{- else if .Values.passwordUpdateJob.previousPasswords.rootPassword -}} + {{- /* The secret with the new password is managed externally */ -}} + {{- printf "%s-previous-secret" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- /* The secret with the new password is managed by the helm chart. We use the current secret name as it has the old password */ -}} + {{- include "common.names.fullname" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return the secret with new MongoDB credentials +*/}} +{{- define "mongodb.update-job.newSecretName" -}} + {{- if and (not .Values.passwordUpdateJob.previousPasswords.existingSecret) (not .Values.passwordUpdateJob.previousPasswords.rootPassword) -}} + {{- /* The secret with the new password is managed by the helm chart. We create a new secret as the current one has the old password */ -}} + {{- printf "%s-new-secret" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- /* The secret with the new password is managed externally */ -}} + {{- include "mongodb.secretName" . -}} + {{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "mongodb.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} +{{- printf "%s" (tpl .Values.initdbScriptsConfigMap $) -}} +{{- else -}} +{{- printf "%s-init-scripts" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get initial primary host to configure MongoDB cluster. +*/}} +{{- define "mongodb.initialPrimaryHost" -}} +{{ ternary ( printf "%s-0.%s.$(MY_POD_NAMESPACE).svc.%s" (include "mongodb.fullname" .) (include "mongodb.service.nameOverride" .) .Values.clusterDomain ) ( first .Values.externalAccess.service.publicNames ) ( empty .Values.externalAccess.service.publicNames ) }} +{{- end -}} + +{{/* +Init container definition to change/establish volume permissions. +*/}} +{{- define "mongodb.initContainer.volumePermissions" }} +- name: volume-permissions + image: {{ include "mongodb.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + mkdir -p {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} + find {{ printf "%s/%s" .Values.persistence.mountPath (default "" .Values.persistence.subPath) }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | xargs -r chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.volumePermissions.resources "context" $) | nindent 12 }} + {{- else if ne .Values.volumePermissions.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.volumePermissions.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if include "common.fips.enabled" . }} + env: + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.volumePermissions.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} +{{- end -}} + +{{/* +Init container definition to recover log dir. +*/}} +{{- define "mongodb.initContainer.prepareLogDir" }} +- name: log-dir + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + ln -sf /dev/stdout "/opt/bitnami/mongodb/logs/mongodb.log" + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.resources "context" $) | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if include "common.fips.enabled" . }} + env: + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir +{{- end -}} + +{{/* +Init container definition to get external IP addresses. +*/}} +{{- define "mongodb.initContainers.autoDiscovery" -}} +- name: auto-discovery + image: {{ include "mongodb.externalAccess.autoDiscovery.image" . }} + imagePullPolicy: {{ .Values.externalAccess.autoDiscovery.image.pullPolicy | quote }} + # We need the service account token for contacting the k8s API + command: + - /scripts/auto-discovery.sh + env: + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SHARED_FILE + value: "/shared/info.txt" + {{- if .Values.externalAccess.autoDiscovery.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.externalAccess.autoDiscovery.resources "context" $) | nindent 12 }} + {{- else if ne .Values.externalAccess.autoDiscovery.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.externalAccess.autoDiscovery.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if include "common.fips.enabled" . }} + env: + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.externalAccess.autoDiscovery.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: shared + mountPath: /shared + - name: scripts + mountPath: /scripts/auto-discovery.sh + subPath: auto-discovery.sh + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir +{{- end -}} + +{{/* +Init container definition to wait external DNS names. +*/}} +{{- define "mongodb.initContainers.dnsCheck" -}} +- name: dns-check + image: {{ include "mongodb.externalAccess.dnsCheck.image" . }} + imagePullPolicy: {{ .Values.externalAccess.dnsCheck.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + # MONGODB_INITIAL_PRIMARY_HOST should be resolvable + while ! (getent ahosts "{{ include "mongodb.initialPrimaryHost" . }}" | grep STREAM); do + sleep 10 + done + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.externalAccess.dnsCheck.resources }} + resources: {{- toYaml .Values.externalAccess.dnsCheck.resources | nindent 12 }} + {{- else if ne .Values.externalAccess.dnsCheck.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.externalAccess.dnsCheck.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if include "common.fips.enabled" . }} + env: + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.externalAccess.dnsCheck.fips "global" .Values.global) | quote }} + {{- end }} +{{- end -}} + +{{/* +Return true if the Arbiter should be deployed +*/}} +{{- define "mongodb.arbiter.enabled" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.arbiter.enabled }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration for the Arbiter +*/}} +{{- define "mongodb.arbiter.configmapName" -}} +{{- if .Values.arbiter.existingConfigmap -}} + {{- printf "%s" (tpl .Values.arbiter.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-arbiter" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® Arbiter +*/}} +{{- define "mongodb.arbiter.createConfigmap" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.arbiter.enabled .Values.arbiter.configuration (not .Values.arbiter.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if the Hidden should be deployed +*/}} +{{- define "mongodb.hidden.enabled" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.hidden.enabled }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the configmap with the MongoDB® configuration for the Hidden +*/}} +{{- define "mongodb.hidden.configmapName" -}} +{{- if .Values.hidden.existingConfigmap -}} + {{- printf "%s" (tpl .Values.hidden.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-hidden" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for MongoDB® Hidden +*/}} +{{- define "mongodb.hidden.createConfigmap" -}} +{{- if and (include "mongodb.hidden.enabled" .) .Values.hidden.enabled .Values.hidden.configuration (not .Values.hidden.existingConfigmap) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "mongodb.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "mongodb.validateValues.pspAndRBAC" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.architecture" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.customUsersDBs" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.customUsersDBsLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessServiceType" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.loadBalancerIPsListLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.nodePortListLength" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessAutoDiscoveryRBAC" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.externalAccessAutoDiscoverySA" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.replicaset.existingSecrets" .) -}} +{{- $messages := append $messages (include "mongodb.validateValues.hidden.existingSecrets" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* Validate RBAC is created when using PSP */}} +{{- define "mongodb.validateValues.pspAndRBAC" -}} +{{- if and (.Values.podSecurityPolicy.create) (not .Values.rbac.create) -}} +mongodb: podSecurityPolicy.create, rbac.create + Both podSecurityPolicy.create and rbac.create must be true, if you want + to create podSecurityPolicy +{{- end -}} +{{- end -}} + +{{/* Validate values of MongoDB® - must provide a valid architecture */}} +{{- define "mongodb.validateValues.architecture" -}} +{{- if and (ne .Values.architecture "standalone") (ne .Values.architecture "replicaset") -}} +mongodb: architecture + Invalid architecture selected. Valid values are "standalone" and + "replicaset". Please set a valid architecture (--set mongodb.architecture="xxxx") +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - both auth.usernames and auth.databases are necessary +to create a custom user and database during 1st initialization +*/}} +{{- define "mongodb.validateValues.customUsersDBs" -}} +{{- $customUsers := include "mongodb.customUsers" . -}} +{{- $customDatabases := include "mongodb.customDatabases" . -}} +{{- if or (and (empty $customUsers) (not (empty $customDatabases))) (and (not (empty $customUsers)) (empty $customDatabases)) }} +mongodb: auth.usernames, auth.databases + Both auth.usernames and auth.databases must be provided to create + custom users and databases during 1st initialization. + Please set both of them (--set auth.usernames[0]="xxxx",auth.databases[0]="yyyy") +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - both auth.usernames and auth.databases arrays should have the same length +to create a custom user and database during 1st initialization +*/}} +{{- define "mongodb.validateValues.customUsersDBsLength" -}} +{{- if ne (len .Values.auth.usernames) (len .Values.auth.databases) }} +mongodb: auth.usernames, auth.databases + Both auth.usernames and auth.databases arrays should have the same length +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - service type for external access +*/}} +{{- define "mongodb.validateValues.externalAccessServiceType" -}} +{{- if and (eq .Values.architecture "replicaset") (not (eq .Values.externalAccess.service.type "NodePort")) (not (eq .Values.externalAccess.service.type "LoadBalancer")) (not (eq .Values.externalAccess.service.type "ClusterIP")) -}} +mongodb: externalAccess.service.type + Available service type for external access are NodePort, LoadBalancer or ClusterIP. +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - number of replicas must be the same than LoadBalancer IPs list +*/}} +{{- define "mongodb.validateValues.loadBalancerIPsListLength" -}} +{{- $replicaCount := int .Values.replicaCount }} +{{- $loadBalancerListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- $publicNamesListLength := len .Values.externalAccess.service.publicNames }} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "LoadBalancer") -}} +{{- if and (not .Values.externalAccess.autoDiscovery.enabled) (eq $loadBalancerListLength 0) (eq $publicNamesListLength 0) -}} +mongodb: .Values.externalAccess.service.loadBalancerIPs, .Values.externalAccess.service.publicNames + externalAccess.service.loadBalancerIPs, externalAccess.service.publicNames or externalAccess.autoDiscovery.enabled are required when externalAccess is enabled. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerListLength )) (not (eq $loadBalancerListLength 0)) -}} +mongodb: .Values.externalAccess.service.loadBalancerIPs + Number of replicas ({{ $replicaCount }}) and loadBalancerIPs array length ({{ $loadBalancerListLength }}) must be the same. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $publicNamesListLength )) (not (eq $publicNamesListLength 0)) -}} +mongodb: .Values.externalAccess.service.publicNames + Number of replicas ({{ $replicaCount }}) and publicNames array length ({{ $publicNamesListLength }}) must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - number of replicas must be the same than NodePort list +*/}} +{{- define "mongodb.validateValues.nodePortListLength" -}} +{{- $replicaCount := int .Values.replicaCount }} +{{- $nodePortListLength := len .Values.externalAccess.service.nodePorts }} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "NodePort") -}} +{{- if and (not .Values.externalAccess.autoDiscovery.enabled) (eq $nodePortListLength 0) -}} +mongodb: .Values.externalAccess.service.nodePorts + externalAccess.service.nodePorts or externalAccess.autoDiscovery.enabled are required when externalAccess is enabled. +{{- else if and (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $nodePortListLength )) -}} +mongodb: .Values.externalAccess.service.nodePorts + Number of replicas ({{ $replicaCount }}) and nodePorts ({{ $nodePortListLength }}) array length must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - RBAC should be enabled when autoDiscovery is enabled +*/}} +{{- define "mongodb.validateValues.externalAccessAutoDiscoveryRBAC" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (not .Values.rbac.create ) }} +mongodb: rbac.create + By specifying "externalAccess.enabled=true" and "externalAccess.autoDiscovery.enabled=true" + an initContainer will be used to autodetect the external IPs/ports by querying the + K8s API. Please note this initContainer requires specific RBAC resources. You can create them + by specifying "--set rbac.create=true". +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - automountServiceAccountToken should be enabled when autoDiscovery is enabled +*/}} +{{- define "mongodb.validateValues.externalAccessAutoDiscoverySA" -}} +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (not .Values.automountServiceAccountToken ) }} +mongodb: automountServiceAccountToken + By specifying "externalAccess.enabled=true" and "externalAccess.autoDiscovery.enabled=true" + an initContainer will be used to autodetect the external IPs/ports by querying the + K8s API. Please note this initContainer requires a service account to access K8S API. + You can attach it to the pod by specifying "--set automountServiceAccountToken=true". +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - Number of replicaset secrets must be the same than number of replicaset nodes. +*/}} +{{- define "mongodb.validateValues.replicaset.existingSecrets" -}} +{{- if and .Values.tls.enabled (eq .Values.architecture "replicaset") (not (empty .Values.tls.replicaset.existingSecrets)) }} +{{- $nbSecrets := len .Values.tls.replicaset.existingSecrets -}} +{{- if not (eq $nbSecrets (int .Values.replicaCount)) }} +mongodb: tls.replicaset.existingSecrets + tls.replicaset.existingSecrets Number of secrets and number of replicaset nodes must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® - Number of hidden secrets must be the same than number of hidden nodes. +*/}} +{{- define "mongodb.validateValues.hidden.existingSecrets" -}} +{{- if and .Values.tls.enabled (include "mongodb.hidden.enabled" .) (not (empty .Values.tls.hidden.existingSecrets)) }} +{{- $nbSecrets := len .Values.tls.hidden.existingSecrets -}} +{{- if not (eq $nbSecrets (int .Values.hidden.replicaCount)) }} +mongodb: tls.hidden.existingSecrets + tls.hidden.existingSecrets Number of secrets and number of hidden nodes must be the same. +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of MongoDB® exporter URI string - auth.enabled and/or tls.enabled must be enabled or it defaults +*/}} +{{- define "mongodb.mongodb_exporter.uri" -}} + {{- $tlsEnabled := .Values.tls.enabled -}} + {{- $mTlsEnabled := and $tlsEnabled .Values.tls.mTLS.enabled -}} + {{- $tlsArgs := "" -}} + {{- if $tlsEnabled -}} + {{- $tlsCertKeyFile := ternary "&tlsCertificateKeyFile=/certs/mongodb.pem" "" $mTlsEnabled -}} + {{- $tlsArgs = printf "tls=true%s&tlsCAFile=/certs/mongodb-ca-cert" $tlsCertKeyFile -}} + {{- end -}} + {{- if .Values.metrics.username -}} + {{- $uriAuth := ternary "$(echo $MONGODB_METRICS_USERNAME | sed -r \"s/@/%40/g;s/:/%3A/g\"):$(echo $MONGODB_METRICS_PASSWORD | sed -r \"s/@/%40/g;s/:/%3A/g\")@" "" .Values.auth.enabled -}} + {{- printf "mongodb://%s$(hostname -s):%d/admin?%s" $uriAuth (int .Values.containerPorts.mongodb) $tlsArgs -}} + {{- else -}} + {{- $uriAuth := ternary "$MONGODB_ROOT_USER:$(echo $MONGODB_ROOT_PASSWORD | sed -r \"s/@/%40/g;s/:/%3A/g\")@" "" .Values.auth.enabled -}} + {{- printf "mongodb://%s$(hostname -s):%d/admin?%s" $uriAuth (int .Values.containerPorts.mongodb) $tlsArgs -}} + {{- end -}} +{{- end -}} + +{{/* +Return true if a TLS secret object should be created +*/}} +{{- define "mongodb.createTlsSecret" -}} +{{- if and .Values.tls.enabled (not .Values.tls.existingSecret) (include "mongodb.autoGenerateCerts" .) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the secret containing MongoDB® TLS certificates +*/}} +{{- define "mongodb.tlsSecretName" -}} +{{- $secretName := .Values.tls.existingSecret -}} +{{- if $secretName -}} + {{- printf "%s" (tpl $secretName $) -}} +{{- else -}} + {{- printf "%s-ca" (include "mongodb.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if certificates must be auto generated +*/}} +{{- define "mongodb.autoGenerateCerts" -}} +{{- $standalone := (eq .Values.architecture "standalone") | ternary (not .Values.tls.standalone.existingSecret) true -}} +{{- $replicaset := (eq .Values.architecture "replicaset") | ternary (empty .Values.tls.replicaset.existingSecrets) true -}} +{{- $arbiter := (eq (include "mongodb.arbiter.enabled" .) "true") | ternary (not .Values.tls.arbiter.existingSecret) true -}} +{{- $hidden := (eq (include "mongodb.hidden.enabled" .) "true") | ternary (empty .Values.tls.hidden.existingSecrets) true -}} +{{- if and $standalone $replicaset $arbiter $hidden -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Generate argument list for mongodb-exporter +reference: https://github.com/percona/mongodb_exporter/blob/main/REFERENCE.md +*/}} +{{- define "mongodb.exporterArgs" -}} +{{- with .Values.metrics.collector -}} +{{- ternary " --collect-all" "" .all -}} +{{- ternary " --collector.diagnosticdata" "" .diagnosticdata -}} +{{- ternary " --collector.replicasetstatus" "" .replicasetstatus -}} +{{- ternary " --collector.dbstats" "" .dbstats -}} +{{- ternary " --collector.topmetrics" "" .topmetrics -}} +{{- ternary " --collector.indexstats" "" .indexstats -}} +{{- ternary " --collector.collstats" "" .collstats -}} +{{- if .collstatsColls -}} +{{- " --mongodb.collstats-colls=" -}} +{{- join "," .collstatsColls -}} +{{- end -}} +{{- if .indexstatsColls -}} +{{- " --mongodb.indexstats-colls=" -}} +{{- join "," .indexstatsColls -}} +{{- end -}} +{{- $limitArg := print " --collector.collstats-limit=" .collstatsLimit -}} +{{- ne (print .collstatsLimit) "0" | ternary $limitArg "" -}} +{{- end -}} +{{- ternary " --compatible-mode" "" .Values.metrics.compatibleMode -}} +{{- end -}} diff --git a/utils/assets/charts/mongodb/templates/arbiter/configmap.yaml b/utils/assets/charts/mongodb/templates/arbiter/configmap.yaml new file mode 100644 index 0000000..a3b3f4c --- /dev/null +++ b/utils/assets/charts/mongodb/templates/arbiter/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/arbiter/headless-svc.yaml b/utils/assets/charts/mongodb/templates/arbiter/headless-svc.yaml new file mode 100644 index 0000000..088eaf4 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/arbiter/headless-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.enabled" .) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.arbiter.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if or .Values.arbiter.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-mongodb + port: {{ .Values.arbiter.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.arbiter.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/arbiter/pdb.yaml b/utils/assets/charts/mongodb/templates/arbiter/pdb.yaml new file mode 100644 index 0000000..0799eea --- /dev/null +++ b/utils/assets/charts/mongodb/templates/arbiter/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.arbiter.enabled" .) .Values.arbiter.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.arbiter.pdb.minAvailable }} + minAvailable: {{ .Values.arbiter.pdb.minAvailable }} + {{- end }} + {{- if or .Values.arbiter.pdb.maxUnavailable (not .Values.arbiter.pdb.minAvailable) }} + maxUnavailable: {{ .Values.arbiter.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: arbiter +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/arbiter/statefulset.yaml b/utils/assets/charts/mongodb/templates/arbiter/statefulset.yaml new file mode 100644 index 0000000..456cbc8 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/arbiter/statefulset.yaml @@ -0,0 +1,348 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.arbiter.enabled" .) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-arbiter" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: arbiter + {{- if or .Values.arbiter.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.arbiter.service.nameOverride" . }} + podManagementPolicy: {{ .Values.arbiter.podManagementPolicy }} + replicas: 1 + {{- if .Values.arbiter.updateStrategy }} + updateStrategy: {{- toYaml .Values.arbiter.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.arbiter.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: arbiter + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: arbiter + {{- if or (include "mongodb.arbiter.createConfigmap" .) .Values.arbiter.podAnnotations .Values.passwordUpdateJob.enabled }} + annotations: + {{- if (include "mongodb.arbiter.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/arbiter/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.passwordUpdateJob.enabled }} + charts.bitnami.com/password-last-update: {{ now | date "20060102150405" | quote }} + {{- end }} + {{- if .Values.arbiter.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.arbiter.schedulerName }} + schedulerName: {{ .Values.arbiter.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + {{- if .Values.arbiter.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.arbiter.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.arbiter.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.arbiter.nodeAffinityPreset.type "key" .Values.arbiter.nodeAffinityPreset.key "values" .Values.arbiter.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.arbiter.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.nodeSelector "context" $) | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.arbiter.automountServiceAccountToken }} + {{- if .Values.arbiter.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.arbiter.priorityClassName }} + priorityClassName: {{ .Values.arbiter.priorityClassName }} + {{- end }} + {{- if .Values.arbiter.runtimeClassName }} + runtimeClassName: {{ .Values.arbiter.runtimeClassName }} + {{- end }} + {{- if .Values.arbiter.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.arbiter.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.arbiter.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.arbiter.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.arbiter.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.service.publicNames }} + {{- include "mongodb.initContainers.dnsCheck" . | nindent 8 }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.tls.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.arbiter.service.nameOverride" . }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: mongodb-arbiter + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.arbiter.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.arbiter.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.arbiter.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.arbiter.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.arbiter.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MONGODB_REPLICA_SET_MODE + value: "arbiter" + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ include "mongodb.initialPrimaryHost" . | quote }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.arbiter.fips "global" .Values.global) | quote }} + {{- end }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).{{ include "mongodb.arbiter.service.nameOverride" . }}.$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + - name: MONGODB_PORT_NUMBER + value: {{ .Values.arbiter.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + {{- if .Values.auth.enabled }} + - name: MONGODB_INITIAL_PRIMARY_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + - name: MONGODB_REPLICA_SET_KEY_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-replica-set-key" + {{- else }} + - name: MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + {{- $extraFlags := .Values.arbiter.extraFlags | join " " -}} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.arbiter.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.arbiter.extraEnvVarsCM .Values.arbiter.extraEnvVarsSecret }} + envFrom: + {{- if .Values.arbiter.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.arbiter.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.arbiter.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.arbiter.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.arbiter.containerPorts.mongodb }} + name: mongodb + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.arbiter.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - pgrep + - mongod + {{- end }} + {{- if .Values.arbiter.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.readinessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: mongodb + {{- end }} + {{- if .Values.arbiter.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.arbiter.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.arbiter.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.arbiter.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.resources "context" $) | nindent 12 }} + {{- else if ne .Values.arbiter.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.arbiter.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /bitnami/mongodb + subPath: app-volume-dir + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.arbiter.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.arbiter.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + secret: + secretName: {{ include "mongodb.secretName" . }} + {{- end }} + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap .Values.arbiter.extraVolumes .Values.tls.enabled }} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0555 + {{- if or .Values.arbiter.configuration .Values.arbiter.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.arbiter.configmapName" . }} + {{- end }} + {{- if and .Values.tls.enabled .Values.arbiter.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.arbiter.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if .Values.arbiter.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.arbiter.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/backup/cronjob.yaml b/utils/assets/charts/mongodb/templates/backup/cronjob.yaml new file mode 100644 index 0000000..8672a70 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/backup/cronjob.yaml @@ -0,0 +1,245 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.backup.enabled }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "mongodb.fullname" . }}-mongodump + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + schedule: {{ quote .Values.backup.cronjob.schedule }} + {{- if .Values.backup.cronjob.timeZone }} + timeZone: {{ .Values.backup.cronjob.timeZone | quote }} + {{- end }} + concurrencyPolicy: {{ .Values.backup.cronjob.concurrencyPolicy }} + failedJobsHistoryLimit: {{ .Values.backup.cronjob.failedJobsHistoryLimit }} + successfulJobsHistoryLimit: {{ .Values.backup.cronjob.successfulJobsHistoryLimit }} + {{- if .Values.backup.cronjob.startingDeadlineSeconds }} + startingDeadlineSeconds: {{ .Values.backup.cronjob.startingDeadlineSeconds }} + {{- end }} + jobTemplate: + spec: + {{- if .Values.backup.cronjob.backoffLimit }} + backoffLimit: {{ .Values.backup.cronjob.backoffLimit }} + {{- end }} + {{- if .Values.backup.cronjob.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.backup.cronjob.ttlSecondsAfterFinished }} + {{- end }} + template: + metadata: + labels: {{- include "common.labels.standard" . | nindent 12 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 12 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 12 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 10 }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 12 }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + serviceAccountName: {{ .Values.backup.cronjob.serviceAccount.name | quote }} + {{- if .Values.tls.enabled }} + initContainers: + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.tls.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 16 }} + {{- end }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 16 }} + {{- end }} + {{- end }} + containers: + - name: {{ include "mongodb.fullname" . }}-mongodump + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + env: + {{- if .Values.auth.enabled }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + {{- else }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + {{- end }} + - name: MONGODB_SERVICE_NAME + value: {{ include "mongodb.service.nameOverride" . }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODUMP_DIR + value: {{ .Values.backup.cronjob.storage.mountPath }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.backup.cronjob.fips "global" .Values.global) | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --ssl --sslPEMKeyFile=/certs/mongodb.pem --sslCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.backup.cronjob.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.command "context" $) | nindent 14 }} + {{- else }} + command: + - /bin/bash + - -c + - | + {{- if and .Values.auth.enabled .Values.usePasswordFiles }} + export MONGODB_ROOT_PASSWORD="$(< $MONGODB_ROOT_PASSWORD_FILE)" + {{- end }} + mongodump {{- if .Values.auth.enabled }} --username=${MONGODB_ROOT_USER} --password=${MONGODB_ROOT_PASSWORD} --authenticationDatabase=admin {{- end }} --host=${MONGODB_SERVICE_NAME} --port=${MONGODB_PORT_NUMBER} ${MONGODB_CLIENT_EXTRA_FLAGS} {{- if (eq $.Values.architecture "replicaset") }}--oplog{{- end }} --gzip --archive=${MONGODUMP_DIR}/mongodump-$(date '+%Y-%m-%d-%H-%M').gz + {{- end }} + {{- if .Values.backup.cronjob.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.resources "context" $) | nindent 14 }} + {{- else if ne .Values.backup.cronjob.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.backup.cronjob.resourcesPreset) | nindent 14 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + {{- end }} + - name: datadir + mountPath: {{ .Values.backup.cronjob.storage.mountPath }} + subPath: {{ .Values.backup.cronjob.storage.subPath }} + {{- if .Values.backup.cronjob.containerSecurityContext.enabled }} + securityContext: + {{- include "common.tplvalues.render" ( dict "value" ( omit .Values.backup.cronjob.containerSecurityContext "enabled" ) "context" $) | nindent 14 }} + {{- end }} + restartPolicy: {{ .Values.backup.cronjob.restartPolicy }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + secret: + secretName: {{ include "mongodb.secretName" . }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.standalone.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if .Values.backup.cronjob.storage.existingClaim }} + - name: datadir + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.backup.cronjob.storage.existingClaim .) }} + {{- else }} + - name: datadir + persistentVolumeClaim: + claimName: {{ include "mongodb.fullname" . }}-mongodump + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/backup/pvc.yaml b/utils/assets/charts/mongodb/templates/backup/pvc.yaml new file mode 100644 index 0000000..583ea41 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/backup/pvc.yaml @@ -0,0 +1,41 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.backup.enabled (not .Values.backup.cronjob.storage.existingClaim) -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "mongodb.fullname" . }}-mongodump + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: mongodump + {{- if .Values.backup.cronjob.labels }} + {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.labels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations .Values.backup.cronjob.storage.resourcePolicy}} + annotations: + {{- if .Values.backup.cronjob.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.backup.cronjob.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.backup.cronjob.storage.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.backup.cronjob.storage.resourcePolicy | quote }} + {{- end }} + {{- end }} +spec: + accessModes: + {{- range .Values.backup.cronjob.storage.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backup.cronjob.storage.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.backup.cronjob.storage "global" .Values.global) | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/common-scripts-cm.yaml b/utils/assets/charts/mongodb/templates/common-scripts-cm.yaml new file mode 100644 index 0000000..6f65de4 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/common-scripts-cm.yaml @@ -0,0 +1,143 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- $fullname := include "mongodb.fullname" . }} + startup-probe.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval 'if (!(db.hello().isWritablePrimary || db.hello().secondary)) { throw new Error("Not ready") }' + readiness-probe.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + # Run the proper check depending on the version + [[ $(mongod -version | grep "db version") =~ ([0-9]+\.[0-9]+\.[0-9]+) ]] && VERSION=${BASH_REMATCH[1]} + . /opt/bitnami/scripts/libversion.sh + VERSION_MAJOR="$(get_sematic_version "$VERSION" 1)" + VERSION_MINOR="$(get_sematic_version "$VERSION" 2)" + VERSION_PATCH="$(get_sematic_version "$VERSION" 3)" + readiness_test='db.isMaster().ismaster || db.isMaster().secondary' + if [[ ( "$VERSION_MAJOR" -ge 5 ) || ( "$VERSION_MAJOR" -ge 4 && "$VERSION_MINOR" -ge 4 && "$VERSION_PATCH" -ge 2 ) ]]; then + readiness_test='db.hello().isWritablePrimary || db.hello().secondary' + fi + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval "if (!(${readiness_test})) { throw new Error(\"Not ready\") }" + ping-mongodb.sh: | + #!/bin/bash + {{- if .Values.tls.enabled }} + # Probes are using localhost/127.0.0.1 to tests if the service is up, ready or healthy. If TLS is enabled, we shouldn't validate the certificate hostname. + TLS_OPTIONS='--tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert --tlsAllowInvalidHostnames' + {{- end }} + exec mongosh $TLS_OPTIONS --port $MONGODB_PORT_NUMBER --eval "db.adminCommand('ping')" + {{- if .Values.tls.enabled }} + generate-certs.sh: | + #!/bin/bash + {{- if (include "mongodb.autoGenerateCerts" .) }} + additional_ips=() + additional_names=() + while getopts "i:n:s:" flag + do + case "${flag}" in + i) read -a additional_ips <<< ${OPTARG//,/ } ;; + n) read -a additional_names <<< ${OPTARG//,/ } ;; + s) svc=${OPTARG// /} ;; + \?) exit 1 ;; + esac + done + + my_hostname=$(hostname) + cp /certs/CAs/* /certs/ + cat >/certs/openssl.cnf <>/certs/openssl.cnf <>/certs/openssl.cnf < /certs/mongodb.pem + cd /certs/ + shopt -s extglob + rm -rf !(mongodb-ca-cert|mongodb.pem|CAs|openssl.cnf) + chmod 0600 mongodb-ca-cert mongodb.pem + {{- else }} + {{- if eq .Values.architecture "standalone" }} + ID="0" + {{- else }} + if [[ "$MY_POD_NAME" =~ "arbiter-0"$ ]]; then + ID="0" + elif [[ "$MY_POD_NAME" =~ "hidden-"[0-9]{1,}$ ]]; then + ID="${MY_POD_NAME#"{{ printf "%s-hidden-" $fullname }}"}" + else + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + fi + {{- end }} + + {{- if .Values.tls.pemChainIncluded }} + #Split the pem chain by the END CERTIFICATE string and store in files /certs/xx00, /certs/xx01 etc. + cat /certs-${ID}/tls.crt | csplit - -s -z '/\-*END CERTIFICATE\-*/+1' '{*}' -f /certs/xx + + #Use first certificate as leaf node and combine with key to store in pem file + cat "/certs/xx00" "/certs-${ID}/tls.key" > "/certs/mongodb.pem" + + #Use remaining intermediate certificates for ca.crt + echo $(find /certs/ -not -name 'xx00' -name 'xx*') | sort | xargs cat > "/certs/mongodb-ca-cert" + + rm -rf /certs/xx* + {{- else }} + cat "/certs-${ID}/tls.crt" "/certs-${ID}/tls.key" > "/certs/mongodb.pem" + cp "/certs-${ID}/ca.crt" "/certs/mongodb-ca-cert" + {{- end }} + + chmod 0600 /certs/mongodb-ca-cert /certs/mongodb.pem + {{- end }} + {{- end }} diff --git a/utils/assets/charts/mongodb/templates/configmap.yaml b/utils/assets/charts/mongodb/templates/configmap.yaml new file mode 100644 index 0000000..0110445 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/extra-list.yaml b/utils/assets/charts/mongodb/templates/extra-list.yaml new file mode 100644 index 0000000..329f5c6 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/extra-list.yaml @@ -0,0 +1,9 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/hidden/configmap.yaml b/utils/assets/charts/mongodb/templates/hidden/configmap.yaml new file mode 100644 index 0000000..fb26bdd --- /dev/null +++ b/utils/assets/charts/mongodb/templates/hidden/configmap.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + mongodb.conf: |- + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.configuration "context" $) | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/hidden/external-access-svc.yaml b/utils/assets/charts/mongodb/templates/hidden/external-access-svc.yaml new file mode 100644 index 0000000..4cfa531 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/hidden/external-access-svc.yaml @@ -0,0 +1,69 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.hidden.enabled" .) .Values.externalAccess.hidden.enabled }} +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.hidden.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-hidden-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-hidden-%d-external" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + pod: {{ $targetPod }} + {{- if or $root.Values.externalAccess.hidden.service.annotations $root.Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.externalAccess.hidden.service.annotations $root.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ $root.Values.externalAccess.hidden.service.type }} + {{- if eq $root.Values.externalAccess.hidden.service.type "LoadBalancer" }} + {{- if not (empty $root.Values.externalAccess.hidden.service.loadBalancerIPs) }} + loadBalancerIP: {{ index $root.Values.externalAccess.hidden.service.loadBalancerIPs $i }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.loadBalancerClass }} + loadBalancerClass: {{ $root.Values.externalAccess.hidden.service.loadBalancerClass }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.hidden.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + allocateLoadBalancerNodePorts: {{ $root.Values.externalAccess.hidden.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if (or (eq $root.Values.externalAccess.hidden.service.type "LoadBalancer") (eq $root.Values.externalAccess.hidden.service.type "NodePort")) }} + externalTrafficPolicy: {{ $root.Values.externalAccess.hidden.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.sessionAffinity }} + sessionAffinity: {{ $root.Values.externalAccess.hidden.service.sessionAffinity }} + {{- end }} + {{- if $root.Values.externalAccess.hidden.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.hidden.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + publishNotReadyAddresses: true + ports: + - name: {{ $root.Values.externalAccess.hidden.service.portName | quote }} + port: {{ $root.Values.externalAccess.hidden.service.ports.mongodb }} + {{- if not (empty $root.Values.externalAccess.hidden.service.nodePorts) }} + {{- $nodePort := index $root.Values.externalAccess.hidden.service.nodePorts $i }} + nodePort: {{ $nodePort }} + {{- else }} + nodePort: null + {{- end }} + targetPort: mongodb + {{- if $root.Values.externalAccess.hidden.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.hidden.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.hidden.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/hidden/headless-svc.yaml b/utils/assets/charts/mongodb/templates/hidden/headless-svc.yaml new file mode 100644 index 0000000..a2af519 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/hidden/headless-svc.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.enabled" .) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.hidden.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if or .Values.hidden.service.headless.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: {{ .Values.hidden.service.portName | quote }} + port: {{ .Values.hidden.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.hidden.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/hidden/pdb.yaml b/utils/assets/charts/mongodb/templates/hidden/pdb.yaml new file mode 100644 index 0000000..9125067 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/hidden/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "mongodb.hidden.enabled" .) .Values.hidden.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" . )}} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.hidden.pdb.minAvailable }} + minAvailable: {{ .Values.hidden.pdb.minAvailable }} + {{- end }} + {{- if or .Values.hidden.pdb.maxUnavailable (not .Values.hidden.pdb.minAvailable) }} + maxUnavailable: {{ .Values.hidden.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: hidden +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/hidden/statefulset.yaml b/utils/assets/charts/mongodb/templates/hidden/statefulset.yaml new file mode 100644 index 0000000..bc7cae8 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/hidden/statefulset.yaml @@ -0,0 +1,618 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.hidden.enabled" .) }} +{{- $replicaCount := int .Values.hidden.replicaCount }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.hidden.service.loadBalancerIPs }} +{{- if not (and .Values.externalAccess.hidden.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.hidden.service.type "LoadBalancer")) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ printf "%s-hidden" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: hidden + {{- if or .Values.hidden.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.hidden.service.nameOverride" . }} + podManagementPolicy: {{ .Values.hidden.podManagementPolicy }} + replicas: {{ .Values.hidden.replicaCount }} + {{- if .Values.hidden.updateStrategy }} + updateStrategy: {{- toYaml .Values.hidden.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.hidden.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: hidden + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: hidden + {{- if or (include "mongodb.hidden.createConfigmap" .) .Values.hidden.podAnnotations .Values.passwordUpdateJob.enabled }} + annotations: + {{- if (include "mongodb.hidden.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/hidden/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.passwordUpdateJob.enabled }} + charts.bitnami.com/password-last-update: {{ now | date "20060102150405" | quote }} + {{- end }} + {{- if .Values.hidden.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.hidden.schedulerName }} + schedulerName: {{ .Values.hidden.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.hidden.automountServiceAccountToken }} + {{- if .Values.hidden.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.hidden.podAffinityPreset "component" "hidden" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.hidden.podAntiAffinityPreset "component" "hidden" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.hidden.nodeAffinityPreset.type "key" .Values.hidden.nodeAffinityPreset.key "values" .Values.hidden.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.hidden.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.hidden.priorityClassName }} + priorityClassName: {{ .Values.hidden.priorityClassName }} + {{- end }} + {{- if .Values.hidden.runtimeClassName }} + runtimeClassName: {{ .Values.hidden.runtimeClassName }} + {{- end }} + {{- if .Values.hidden.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.hidden.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.hidden.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.hidden.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.hidden.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.hidden.persistence.enabled }} + {{- include "mongodb.initContainer.volumePermissions" . | indent 8 }} + {{- end }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + {{- include "mongodb.initContainers.autoDiscovery" . | indent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.service.publicNames }} + {{- include "mongodb.initContainers.dnsCheck" . | indent 8 }} + {{- end }} + {{- include "mongodb.initContainer.prepareLogDir" . | nindent 8 }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.tls.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + {{- range $index, $_ := .Values.tls.hidden.existingSecrets }} + - name: mongodb-certs-{{ $index }} + mountPath: /certs-{{ $index }} + {{- end }} + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.hidden.service.nameOverride" . }} + {{- if .Values.externalAccess.hidden.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.hidden.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.hidden.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.hidden.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.hidden.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.command "context" $) | nindent 12 }} + {{- else }} + command: + - /scripts/setup-hidden.sh + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.hidden.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.hidden.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: SHARED_FILE + value: "/shared/info.txt" + {{- end }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MONGODB_REPLICA_SET_MODE + value: "hidden" + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ include "mongodb.initialPrimaryHost" . | quote }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.hidden.fips "global" .Values.global) | quote }} + {{- end }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + {{- if and .Values.replicaSetHostnames (not .Values.externalAccess.hidden.enabled) }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).{{ include "mongodb.hidden.service.nameOverride" . }}.$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + {{- end }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_EXTRA_PASSWORDS_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-passwords" + {{- else }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + - name: MONGODB_REPLICA_SET_KEY_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-replica-set-key" + {{- else }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_METRICS_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-metrics-password" + {{- else }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.hidden.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.hidden.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.hidden.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.hidden.extraEnvVarsCM .Values.hidden.extraEnvVarsSecret }} + envFrom: + {{- if .Values.hidden.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.hidden.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.hidden.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.hidden.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.hidden.containerPorts.mongodb }} + name: mongodb + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.hidden.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- if .Values.hidden.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- if .Values.hidden.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.hidden.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.hidden.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.hidden.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.resources "context" $) | nindent 12 }} + {{- else if ne .Values.hidden.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.hidden.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: datadir + mountPath: {{ .Values.hidden.persistence.mountPath }} + subPath: {{ .Values.hidden.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.hidden.configuration .Values.hidden.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + - name: scripts + mountPath: /scripts/setup-hidden.sh + subPath: setup-hidden.sh + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: shared + mountPath: /shared + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /.mongodb + subPath: mongosh-home + {{- if .Values.hidden.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + {{- if .Values.metrics.username }} + export MONGODB_METRICS_PASSWORD="$(< $MONGODB_METRICS_PASSWORD_FILE)" + {{- else }} + export MONGODB_ROOT_PASSWORD="$(< $MONGODB_ROOT_PASSWORD_FILE)" + {{- end }} + {{- end }} + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + {{- else }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_METRICS_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-metrics-password" + {{- else }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + {{- end }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.metrics.fips "global" .Values.global) | quote }} + - name: GODEBUG + value: {{ include "common.fips.config" (dict "tech" "golang" "fips" .Values.metrics.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + - name: empty-dir + mountPath: /opt/bitnami/redis-cluster/tmp + subPath: app-tmp-dir + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: 9216 + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.resources "context" $) | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.hidden.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0555 + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + secret: + secretName: {{ include "mongodb.secretName" . }} + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.hidden.configuration .Values.hidden.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.hidden.configmapName" . }} + {{- end }} + {{- if and .Values.externalAccess.hidden.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.hidden.service.type "LoadBalancer") }} + - name: shared + emptyDir: {} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0755 + {{- if .Values.hidden.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + {{- range $index, $secret := .Values.tls.hidden.existingSecrets }} + - name: mongodb-certs-{{ $index }} + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" $secret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- if not .Values.hidden.persistence.enabled }} + - name: datadir + {{- if .Values.hidden.persistence.medium }} + emptyDir: + medium: {{ .Values.hidden.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + volumeClaimTemplates: + - metadata: + name: datadir + {{- if .Values.hidden.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.hidden.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.hidden.persistence.size | quote }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.requests }} + {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.requests "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.hidden.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.hidden.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.hidden.persistence "global" .Values.global) }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/initialization-configmap.yaml b/utils/assets/charts/mongodb/templates/initialization-configmap.yaml new file mode 100644 index 0000000..2c1273c --- /dev/null +++ b/utils/assets/charts/mongodb/templates/initialization-configmap.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.initdbScripts (not .Values.initdbScriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{- include "common.tplvalues.render" (dict "value" .Values.initdbScripts "context" .) | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/metrics-svc.yaml b/utils/assets/charts/mongodb/templates/metrics-svc.yaml new file mode 100644 index 0000000..b6bd266 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/metrics-svc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.metrics.service.type }} + ports: + - port: {{ .Values.metrics.service.ports.metrics }} + targetPort: metrics + protocol: TCP + name: http-metrics + {{- if .Values.metrics.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/mongo_seed_data.yml b/utils/assets/charts/mongodb/templates/mongo_seed_data.yml new file mode 100644 index 0000000..9348722 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/mongo_seed_data.yml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mongo-seed-data +data: +{{- range $path, $_ := .Files.Glob (printf "start_files/%s/*.json" .Values.clusterName) }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/mongodb/templates/mongo_seed_job.yaml b/utils/assets/charts/mongodb/templates/mongo_seed_job.yaml new file mode 100644 index 0000000..490259f --- /dev/null +++ b/utils/assets/charts/mongodb/templates/mongo_seed_job.yaml @@ -0,0 +1,52 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: mongo-seed +spec: + backoffLimit: 1 + template: + spec: + containers: + - name: mongo-seed + image: mongo:6 + command: + - sh + - -c + - | + echo "Waiting for Mongo to be ready..." + until mongo --host mongo --eval "print(\"ok\")" >/dev/null 2>&1; do + echo "Mongo not ready yet..." + sleep 2 + done + + echo "Checking for JSON files in /opt/opencloud/seed-data..." + files=(/opt/opencloud/seed-data/*.json) + + if [ "${files[0]}" = "/opt/opencloud/seed-data/*.json" ]; then + echo "No JSON files found. Skipping import." + else + echo "Importing JSON files..." + for file in /opt/opencloud/seed-data/*.json; do + if [ -f "$file" ]; then + collection=$(basename "$file" .json) + echo "Importing $file into collection $collection" + mongoimport \ + --uri="mongodb://mongo:27017/opencloud" \ + --collection "$collection" \ + --drop \ + --file "$file" \ + --jsonArray || echo "Failed to import $file, continuing..." + fi + done + fi + + echo "Mongo seed job finished." + exit 0 + volumeMounts: + - name: seed-volume + mountPath: /opt/opencloud/seed-data + volumes: + - name: seed-volume + configMap: + name: mongo-seed-data + restartPolicy: Never \ No newline at end of file diff --git a/utils/assets/charts/mongodb/templates/networkpolicy.yaml b/utils/assets/charts/mongodb/templates/networkpolicy.yaml new file mode 100644 index 0000000..1cb492f --- /dev/null +++ b/utils/assets/charts/mongodb/templates/networkpolicy.yaml @@ -0,0 +1,98 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotation }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + policyTypes: + - Ingress + - Egress + {{- if .Values.networkPolicy.allowExternalEgress }} + egress: + - {} + {{- else }} + egress: + # Allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # Allow connection to other cluster pods + - ports: + - port: {{ .Values.containerPorts.mongodb }} + to: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + {{- if (and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled) }} + {{- $kubernetesEndpoints := lookup "v1" "Endpoints" (include "common.names.namespace" .) "kubernetes" }} + {{- range $kubernetesEndpoints.subsets }} + # Allow connection to API server, required by auto-discovery containers + - ports: + {{- range .ports }} + - port: {{ .port }} + {{- end }} + to: + {{- range .addresses }} + - ipBlock: + cidr: {{ printf "%s/32" .ip }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.extraEgress }} + {{- include "common.tplvalues.render" ( dict "value" .Values.networkPolicy.extraEgress "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} + ingress: + - ports: + - port: {{ .Values.containerPorts.mongodb }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.metrics.containerPort }} + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 14 }} + app.kubernetes.io/component: mongodb + {{- if .Values.networkPolicy.addExternalClientAccess }} + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- end }} + {{- if .Values.networkPolicy.ingressPodMatchLabels }} + - podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- $ingressNSMatchLabels := coalesce .Values.networkPolicy.ingressNSMatchLabels .Values.networkPolicy.namespaceSelector }} + {{- if $ingressNSMatchLabels }} + - namespaceSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" $ingressNSMatchLabels "context" $ ) | nindent 14 }} + {{- $ingressNSPodMatchLabels := coalesce .Values.networkPolicy.ingressNSPodMatchLabels .Values.networkPolicy.podSelector }} + {{- if $ingressNSPodMatchLabels }} + podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" $ingressNSPodMatchLabels "context" $ ) | nindent 14 }} + {{- end }} + {{- end }} + {{- end }} + {{- $extraIngress := coalesce .Values.networkPolicy.extraIngress .Values.networkPolicy.customRules }} + {{- if $extraIngress }} + {{- include "common.tplvalues.render" ( dict "value" $extraIngress "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/prometheusrule.yaml b/utils/assets/charts/mongodb/templates/prometheusrule.yaml new file mode 100644 index 0000000..e0d0f28 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.prometheusRule.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.metrics.prometheusRule.additionalLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.prometheusRule.additionalLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "mongodb.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/psp.yaml b/utils/assets/charts/mongodb/templates/psp.yaml new file mode 100644 index 0000000..4b93f4f --- /dev/null +++ b/utils/assets/charts/mongodb/templates/psp.yaml @@ -0,0 +1,51 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: +{{- if .Values.podSecurityPolicy.spec }} +{{ include "common.tplvalues.render" ( dict "value" .Values.podSecurityPolicy.spec "context" $ ) | nindent 2 }} +{{- else }} + allowPrivilegeEscalation: {{ .Values.podSecurityPolicy.allowPrivilegeEscalation }} + fsGroup: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.podSecurityContext.fsGroup }} + max: {{ .Values.podSecurityContext.fsGroup }} + hostIPC: false + hostNetwork: false + hostPID: false + privileged: {{ .Values.podSecurityPolicy.privileged }} + readOnlyRootFilesystem: false + requiredDropCapabilities: + - ALL + runAsUser: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.containerSecurityContext.runAsUser }} + max: {{ .Values.containerSecurityContext.runAsUser }} + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: {{ .Values.containerSecurityContext.runAsUser }} + max: {{ .Values.containerSecurityContext.runAsUser }} + volumes: + - 'configMap' + - 'secret' + - 'emptyDir' + - 'persistentVolumeClaim' +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/replicaset/external-access-svc.yaml b/utils/assets/charts/mongodb/templates/replicaset/external-access-svc.yaml new file mode 100644 index 0000000..400db8e --- /dev/null +++ b/utils/assets/charts/mongodb/templates/replicaset/external-access-svc.yaml @@ -0,0 +1,73 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (not (eq .Values.externalAccess.service.type "ClusterIP")) }} +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%d-external" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + pod: {{ $targetPod }} + {{- if or $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations $root.Values.externalAccess.service.annotationsList }} + {{- $exclusiveAnnotations := dict }} + {{- if gt (len $root.Values.externalAccess.service.annotationsList) $i }} + {{- $exclusiveAnnotations = index $root.Values.externalAccess.service.annotationsList $i }} + {{- end }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations $exclusiveAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ $root.Values.externalAccess.service.type }} + {{- if eq $root.Values.externalAccess.service.type "LoadBalancer" }} + {{- if not (empty $root.Values.externalAccess.service.loadBalancerIPs) }} + loadBalancerIP: {{ index $root.Values.externalAccess.service.loadBalancerIPs $i }} + {{- end }} + {{- if and (eq $root.Values.externalAccess.service.type "LoadBalancer") $root.Values.externalAccess.service.loadBalancerClass }} + loadBalancerClass: {{ $root.Values.externalAccess.service.loadBalancerClass }} + {{- end }} + {{- if $root.Values.externalAccess.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + allocateLoadBalancerNodePorts: {{ $root.Values.externalAccess.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if (or (eq $root.Values.externalAccess.service.type "LoadBalancer") (eq $root.Values.externalAccess.service.type "NodePort")) }} + externalTrafficPolicy: {{ $root.Values.externalAccess.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if $root.Values.externalAccess.service.sessionAffinity }} + sessionAffinity: {{ $root.Values.externalAccess.service.sessionAffinity }} + {{- end }} + {{- if $root.Values.externalAccess.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + publishNotReadyAddresses: true + ports: + - name: {{ $root.Values.externalAccess.service.portName | quote }} + port: {{ $root.Values.externalAccess.service.ports.mongodb }} + {{- if not (empty $root.Values.externalAccess.service.nodePorts) }} + {{- $nodePort := index $root.Values.externalAccess.service.nodePorts $i }} + nodePort: {{ $nodePort }} + {{- else }} + nodePort: null + {{- end }} + targetPort: mongodb + {{- if $root.Values.externalAccess.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.externalAccess.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/replicaset/headless-svc.yaml b/utils/assets/charts/mongodb/templates/replicaset/headless-svc.yaml new file mode 100644 index 0000000..eb6337d --- /dev/null +++ b/utils/assets/charts/mongodb/templates/replicaset/headless-svc.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.commonAnnotations .Values.service.headless.annotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.headless.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.mongodb }} + targetPort: mongodb + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/replicaset/pdb.yaml b/utils/assets/charts/mongodb/templates/replicaset/pdb.yaml new file mode 100644 index 0000000..a193ed2 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/replicaset/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pdb.maxUnavailable (not .Values.pdb.minAvailable) }} + maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/replicaset/scripts-configmap.yaml b/utils/assets/charts/mongodb/templates/replicaset/scripts-configmap.yaml new file mode 100644 index 0000000..e0571ac --- /dev/null +++ b/utils/assets/charts/mongodb/templates/replicaset/scripts-configmap.yaml @@ -0,0 +1,322 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- if and .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + auto-discovery.sh: |- + #!/bin/bash + + SVC_NAME="${MY_POD_NAME}-external" + + # Auxiliary functions + retry_while() { + local -r cmd="${1:?cmd is missing}" + local -r retries="${2:-12}" + local -r sleep_time="${3:-5}" + local return_value=1 + + read -r -a command <<< "$cmd" + for ((i = 1 ; i <= retries ; i+=1 )); do + "${command[@]}" && return_value=0 && break + sleep "$sleep_time" + done + return $return_value + } + k8s_svc_lb_ip() { + local namespace=${1:?namespace is missing} + local service=${2:?service is missing} + local service_ip=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].ip}") + local service_hostname=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].hostname}") + + if [[ -n ${service_ip} ]]; then + echo "${service_ip}" + else + echo "${service_hostname}" + fi + } + k8s_svc_lb_ip_ready() { + local namespace=${1:?namespace is missing} + local service=${2:?service is missing} + [[ -n "$(k8s_svc_lb_ip "$namespace" "$service")" ]] + } + # Wait until LoadBalancer IP is ready + retry_while "k8s_svc_lb_ip_ready {{ $releaseNamespace }} $SVC_NAME" || exit 1 + # Obtain LoadBalancer external IP + k8s_svc_lb_ip "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE" + {{- end }} + setup.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/mongodb-env.sh + . /opt/bitnami/scripts/libfs.sh + . /opt/bitnami/scripts/liblog.sh + . /opt/bitnami/scripts/libvalidations.sh + + {{- if .Values.externalAccess.enabled }} + {{- if eq .Values.externalAccess.service.type "LoadBalancer" }} + {{- if .Values.externalAccess.autoDiscovery.enabled }} + export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})" + {{- else }} + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ coalesce .Values.externalAccess.service.publicNames .Values.externalAccess.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + {{- end }} + {{- else if eq .Values.externalAccess.service.type "NodePort" }} + ID="${MY_POD_NAME#"{{ $fullname }}-"}" + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + fi + {{- if .Values.externalAccess.service.domain }} + export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.service.domain }} + {{- else }} + export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.replicaSetConfigurationSettings.enabled }} + # placed here before root password env is overwritten + # makes no assumption about starting state + # ensures that any stepDown or non-default starting state is handled + /scripts/replicaSetConfigurationSettings.sh & + {{- end }} + + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER="$MONGODB_PORT_NUMBER" + fi + + info "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME" + info "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER" + + # Check for existing replica set in case there is no data in the PVC + # This is for cases where the PVC is lost or for MongoDB caches without + # persistence + current_primary="" + if is_dir_empty "${MONGODB_DATA_DIR}/db"; then + info "Data dir empty, checking if the replica set already exists" + {{- $replicaCount := int .Values.replicaCount }} + {{- $portNumber := int .Values.service.ports.mongodb }} + {{- $fullname := include "mongodb.fullname" . }} + {{- $serviceName := include "mongodb.service.nameOverride" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $mongoList := list }} + {{- range $e, $i := until $replicaCount }} + {{- $mongoList = append $mongoList (printf "%s-%d.%s.%s.svc.%s:%d" $fullname $i $serviceName $releaseNamespace $clusterDomain $portNumber) }} + {{- end }} + + {{- if .Values.externalAccess.externalMaster.enabled }} + current_primary={{ printf "%s:%d" (.Values.externalAccess.externalMaster.host) ( int .Values.externalAccess.externalMaster.port) }} + {{- else }} + current_primary=$(mongosh admin --host "{{ join "," $mongoList }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }}{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} --eval 'db.runCommand("ismaster")' | awk -F\' '/primary:/ {print $2}') + {{- end }} + if ! is_empty_value "$current_primary"; then + info "Detected existing primary: ${current_primary}" + fi + fi + + if ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" == "$current_primary" ]]; then + info "Advertised name matches current primary, configuring node as a primary" + export MONGODB_REPLICA_SET_MODE="primary" + elif ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" != "$current_primary" ]]; then + info "Current primary is different from this node. Configuring the node as replica of ${current_primary}" + export MONGODB_REPLICA_SET_MODE="secondary" + export MONGODB_INITIAL_PRIMARY_HOST="${current_primary%:*}" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="${current_primary#*:}" + export MONGODB_SET_SECONDARY_OK="yes" + elif [[ "$MY_POD_NAME" = "{{ $fullname }}-0" ]]; then + info "Pod name matches initial primary pod name, configuring node as a primary" + export MONGODB_REPLICA_SET_MODE="primary" + else + info "Pod name doesn't match initial primary pod name, configuring node as a secondary" + export MONGODB_REPLICA_SET_MODE="secondary" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER" + fi + + if [[ "$MONGODB_REPLICA_SET_MODE" == "secondary" ]]; then + export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER" + export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD" + export MONGODB_ROOT_PASSWORD="" + export MONGODB_EXTRA_USERNAMES="" + export MONGODB_EXTRA_DATABASES="" + export MONGODB_EXTRA_PASSWORDS="" + export MONGODB_ROOT_PASSWORD_FILE="" + export MONGODB_EXTRA_USERNAMES_FILE="" + export MONGODB_EXTRA_DATABASES_FILE="" + export MONGODB_EXTRA_PASSWORDS_FILE="" + fi + exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + setup-hidden.sh: |- + #!/bin/bash + + . /opt/bitnami/scripts/mongodb-env.sh + + {{- if .Values.externalAccess.hidden.enabled }} + {{- if eq .Values.externalAccess.hidden.service.type "LoadBalancer" }} + {{- if .Values.externalAccess.autoDiscovery.enabled }} + export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})" + {{- else }} + ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}" + export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ .Values.externalAccess.hidden.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + {{- end }} + {{- else if eq .Values.externalAccess.hidden.service.type "NodePort" }} + ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}" + if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then + export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") + fi + {{- if .Values.externalAccess.hidden.service.domain }} + export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.hidden.service.domain }} + {{- else }} + export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.replicaSetConfigurationSettings.enabled }} + # placed here before root password env is overwritten + # makes no assumption about starting state + # ensures that any stepDown or non-default starting state is handled + /scripts/replicaSetConfigurationSettings.sh & + {{- end }} + + echo "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME" + echo "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER" + echo "Configuring node as a hidden node" + export MONGODB_REPLICA_SET_MODE="hidden" + export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER" + export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD" + export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER" + export MONGODB_ROOT_PASSWORD="" + export MONGODB_EXTRA_USERNAMES="" + export MONGODB_EXTRA_DATABASES="" + export MONGODB_EXTRA_PASSWORDS="" + export MONGODB_ROOT_PASSWORD_FILE="" + export MONGODB_EXTRA_USERNAMES_FILE="" + export MONGODB_EXTRA_DATABASES_FILE="" + export MONGODB_EXTRA_PASSWORDS_FILE="" + exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh + {{- if .Values.replicaSetConfigurationSettings.enabled }} + replicaSetConfigurationSettings.sh: |- + #!/bin/bash + # This script to be called when pod starts. + # This script sets rs settings which can not be applied via conf file + + function logger () + #$1 is the line to be logged + { + echo "replicaSetConfigurationSettings.sh -- ${1}" >&1 + } + + SLEEP_PERIOD=10 + + {{- if and .Values.auth.enabled (or .Values.auth.rootPassword .Values.auth.existingSecret)}} + usernameAndPassword="{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} -u ${MONGODB_ROOT_USER} -p ${MONGODB_ROOT_PASSWORD}" + {{- else }} + usernameAndPassword="" + {{- end }} + + # load Values.replicaSetConfigurationSettings.configuration into associtive array which makes iterating and string manipulation easy + declare -A desiredRsConf + {{ range $setting, $value := .Values.replicaSetConfigurationSettings.configuration -}} + {{ printf "desiredRsConf[%s]='%v'" $setting $value }} + {{ end }} + + rsConfWriteAttempts=0 + rs_conf_configured_ok=unknown + + while [[ "${rs_conf_configured_ok}" != "true" ]]; do + + # give the rs setup a chance to succeed before attempting to read or configure + sleep ${SLEEP_PERIOD} + + counter=0 + while ! mongosh ${usernameAndPassword} --eval 'rs.conf()'; do + counter=$((${counter} +1)) + logger "not yet able to read rs.conf settings from the currently running rs (after ${counter} attempts)" + sleep ${SLEEP_PERIOD} + done + counter=$((${counter} +1)) + logger "rs.conf settings have been read from the currently running rs (after ${counter} attempts)" + + # read rs.conf again and store it. settings format is '"" : ,' + currentRsConf=$(mongosh ${usernameAndPassword} --eval 'rs.conf()') + + desiredEqualsActual=unknown + settingsToConfigure="" + for key in ${!desiredRsConf[@]}; do + value=${desiredRsConf[$key]} + if [[ $key =~ ^members\[[0-9]+\]\..+ ]]; then + # Replica set member specific setting + if [[ "$(mongosh --eval "cfg=${currentRsConf}; cfg.${key}" 2>/dev/null)" != "${value}" ]]; then + desiredEqualsActual=false + logger "rs conf: ${key} needs to be updated to desired value: ${value}" + settingsToConfigure="${settingsToConfigure}cfg.${key} = ${value}; " + else + logger "rs conf: ${key} is already at desired value: ${value}" + fi + else + # General rs setting + if [[ "$(mongosh --eval "cfg=${currentRsConf}; cfg.settings.${key}" 2>/dev/null)" != "${value}" ]]; then + desiredEqualsActual=false + logger "rs conf: ${key} needs to be updated to desired value: ${value}" + settingsToConfigure="${settingsToConfigure}cfg.settings.${key} = ${value}; " + else + logger "rs conf: ${key} is already at desired value: ${value}" + fi + fi + done + + if [[ "${desiredEqualsActual}" != "false" ]]; then + logger "replicaSetConfigurationSettings match the settings of the currently running rs" + desiredEqualsActual=true + rs_conf_configured_ok=true + logger "Current settings match desired settings (There have been ${rsConfWriteAttempts} attempts to write to mongoDB rs configuration)" + exit + fi + + # apply the settings only if this member is currently the mongo replicaset PRIMARY + # it might take a little time before any pod is PRIMARY + isMaster=unknown + if ! mongosh ${usernameAndPassword} --eval 'rs.isMaster()' | grep -q "ismaster: true"; then + isMaster=false + logger "This node is not yet PRIMARY - replicaSetConfigurationSettings will only be set on the member that is currently PRIMARY" + else + isMaster=true + logger "This node is PRIMARY" + fi + + if [[ "${isMaster}" == "true" ]]; then + logger "This node is currently PRIMARY - will apply rs.conf settings" + + # avoiding tricky string substitution with single quotes by making the eval string a set of vars + rsconf="cfg = rs.conf();" + rsreconf="rs.reconfig(cfg);" + rsCommand="${rsconf} ${settingsToConfigure} ${rsreconf}" + + mongosh ${usernameAndPassword} --eval "${rsCommand}" + if [ $? -ne 0 ]; then + logger "Failed to apply mongodb cfg.settings configuration" + else + logger "mongodb replicaset cfg.settings configuration applied" + logger "Will check rs conf" + # don't exit just yet - the settings will be checked in the next loop + fi + rsConfWriteAttempts=$((${rsConfWriteAttempts} + 1 )) + fi + done + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/replicaset/statefulset.yaml b/utils/assets/charts/mongodb/templates/replicaset/statefulset.yaml new file mode 100644 index 0000000..f457321 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/replicaset/statefulset.yaml @@ -0,0 +1,624 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if eq .Values.architecture "replicaset" }} +{{- $replicaCount := int .Values.replicaCount }} +{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} +{{- $publicNamesLength := len .Values.externalAccess.service.publicNames }} +{{- if not (and .Values.externalAccess.enabled (not .Values.externalAccess.autoDiscovery.enabled) (eq .Values.externalAccess.service.type "LoadBalancer") (not (eq $replicaCount $loadBalancerIPListLength)) (not (eq $replicaCount $publicNamesLength))) }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + serviceName: {{ include "mongodb.service.nameOverride" . }} + podManagementPolicy: {{ .Values.podManagementPolicy }} + replicas: {{ .Values.replicaCount }} + {{- if .Values.updateStrategy }} + updateStrategy: {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: mongodb + {{- if or (include "mongodb.createConfigmap" .) .Values.podAnnotations .Values.passwordUpdateJob.enabled }} + annotations: + {{- if (include "mongodb.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.passwordUpdateJob.enabled }} + charts.bitnami.com/password-last-update: {{ now | date "20060102150405" | quote }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + {{- include "mongodb.initContainer.volumePermissions" . | nindent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + {{- include "mongodb.initContainers.autoDiscovery" . | nindent 8 }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.service.publicNames }} + {{- include "mongodb.initContainers.dnsCheck" . | nindent 8 }} + {{- end }} + {{- include "mongodb.initContainer.prepareLogDir" . | nindent 8 }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.tls.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + {{- range $index, $_ := .Values.tls.replicaset.existingSecrets }} + - name: mongodb-certs-{{ $index }} + mountPath: /certs-{{ $index }} + {{- end }} + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- else }} + command: + - /scripts/setup.sh + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: SHARED_FILE + value: "/shared/info.txt" + {{- end }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: MONGODB_INITIAL_PRIMARY_HOST + value: {{ include "mongodb.initialPrimaryHost" . | quote }} + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.replicaSetName | quote }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.fips "global" .Values.global) | quote }} + {{- end }} + {{- if and .Values.replicaSetHostnames (not .Values.externalAccess.enabled) }} + - name: MONGODB_ADVERTISED_HOSTNAME + value: "$(MY_POD_NAME).{{ include "mongodb.service.nameOverride" . }}.$(MY_POD_NAMESPACE).svc.{{ .Values.clusterDomain }}" + {{- end }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_EXTRA_PASSWORDS_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-passwords" + {{- else }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + - name: MONGODB_REPLICA_SET_KEY_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-replica-set-key" + {{- else }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + - name: MONGODB_REPLICA_SET_KEY + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-replica-set-key + {{- end }} + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_METRICS_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-metrics-password" + {{- else }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - name: mongodb + containerPort: {{ .Values.containerPorts.mongodb }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.resources "context" $) | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /.mongodb + subPath: mongosh-home + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + - name: scripts + mountPath: /scripts/setup.sh + subPath: setup.sh + {{ if .Values.replicaSetConfigurationSettings.enabled }} + - name: scripts + mountPath: /scripts/replicaSetConfigurationSettings.sh + subPath: replicaSetConfigurationSettings.sh + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: shared + mountPath: /shared + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + {{- if .Values.metrics.username }} + export MONGODB_METRICS_PASSWORD="$(< $MONGODB_METRICS_PASSWORD_FILE)" + {{- else }} + export MONGODB_ROOT_PASSWORD="$(< $MONGODB_ROOT_PASSWORD_FILE)" + {{- end }} + {{- end }} + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --web.listen-address ":{{ .Values.metrics.containerPort }}" --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + {{- else }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_METRICS_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-metrics-password" + {{- else }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + {{- end }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.metrics.fips "global" .Values.global) | quote }} + - name: GODEBUG + value: {{ include "common.fips.config" (dict "tech" "golang" "fips" .Values.metrics.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPort }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.resources "context" $) | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + secret: + secretName: {{ include "mongodb.secretName" . }} + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.configmapName" . }} + {{- end }} + {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }} + - name: shared + emptyDir: {} + {{- end }} + - name: scripts + configMap: + name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0755 + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + {{- range $index, $secret := .Values.tls.replicaset.existingSecrets }} + - name: mongodb-certs-{{ $index }} + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" $secret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: datadir + {{- if .Values.persistence.medium }} + emptyDir: + medium: {{ .Values.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: datadir + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.volumeClaimTemplates.requests }} + {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.requests "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.persistence.volumeClaimTemplates.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.dataSource "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/replicaset/svc.yaml b/utils/assets/charts/mongodb/templates/replicaset/svc.yaml new file mode 100644 index 0000000..7ada019 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/replicaset/svc.yaml @@ -0,0 +1,42 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (eq .Values.architecture "replicaset") .Values.externalAccess.enabled (eq .Values.externalAccess.service.type "ClusterIP") }} + +{{- $fullName := include "mongodb.fullname" . }} +{{- $replicaCount := .Values.replicaCount | int }} +{{- $root := . }} + +{{- range $i, $e := until $replicaCount }} +{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} +{{- $_ := set $ "targetPod" $targetPod }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%d" $fullName $i }} + namespace: {{ include "mongodb.namespace" $ }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $root.Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or $root.Values.service.annotations $root.Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.service.annotations $root.Values.commonAnnotations ) "context" $ ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + publishNotReadyAddresses: {{ $root.Values.service.publishNotReadyAddresses }} + ports: + - name: {{ $root.Values.service.portName | quote }} + port: {{ $root.Values.service.ports.mongodb }} + targetPort: mongodb + {{- if $root.Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" $root.Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list $root.Values.podLabels $root.Values.commonLabels ) "context" $ ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + statefulset.kubernetes.io/pod-name: {{ $targetPod }} +--- +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/role.yaml b/utils/assets/charts/mongodb/templates/role.yaml new file mode 100644 index 0000000..651b963 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/role.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch +{{- if .Values.rbac.rules }} +{{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} +{{- end -}} +{{- if and (include "common.capabilities.psp.supported" .) .Values.podSecurityPolicy.create }} + - apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ include "mongodb.fullname" . }}] +{{- end -}} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/rolebinding.yaml b/utils/assets/charts/mongodb/templates/rolebinding.yaml new file mode 100644 index 0000000..7ff6b18 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/rolebinding.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} +roleRef: + kind: Role + name: {{ include "mongodb.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ include "mongodb.serviceAccountName" . }} + namespace: {{ include "mongodb.namespace" . | quote }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/secrets-ca.yaml b/utils/assets/charts/mongodb/templates/secrets-ca.yaml new file mode 100644 index 0000000..932b0e6 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/secrets-ca.yaml @@ -0,0 +1,33 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if (include "mongodb.createTlsSecret" .) }} +{{- $secretName := printf "%s" (include "mongodb.tlsSecretName" .) }} +{{- $fullname := include "mongodb.fullname" . }} +{{- $releaseNamespace := .Release.Namespace }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $cn := printf "%s.%s.svc.%s" $fullname .Release.Namespace $clusterDomain }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ template "mongodb.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if or .Values.tls.caCert .Values.tls.caKey (not .Values.tls.autoGenerated) }} + {{- $ca := buildCustomCert (required "A valid .Values.tls.caCert is required!" .Values.tls.caCert) (required "A valid .Values.tls.caKey is required!" .Values.tls.caKey) }} + mongodb-ca-cert: {{ b64enc $ca.Cert }} + mongodb-ca-key: {{ b64enc $ca.Key }} + {{- else }} + {{- $ca := genCA "myMongo-ca" 3650 }} + mongodb-ca-cert: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "mongodb-ca-cert" "defaultValue" $ca.Cert "context" $) }} + mongodb-ca-key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "mongodb-ca-key" "defaultValue" $ca.Key "context" $) }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/secrets.yaml b/utils/assets/charts/mongodb/templates/secrets.yaml new file mode 100644 index 0000000..c7526ef --- /dev/null +++ b/utils/assets/charts/mongodb/templates/secrets.yaml @@ -0,0 +1,128 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.auth.enabled }} +{{- $replicaCount := int .Values.replicaCount }} +{{- $port := .Values.service.ports.mongodb }} +{{- $host := include "mongodb.service.nameOverride" . }} +{{- $hostForURI := printf "%s:%s" (include "mongodb.service.nameOverride" .) (print $port) }} +{{- if (eq .Values.architecture "replicaset") }} + {{- $fullname := include "mongodb.fullname" . }} + {{- $releaseNamespace := include "mongodb.namespace" . }} + {{- $clusterDomain := .Values.clusterDomain }} + {{- $mongoList := list }} + {{- $mongoOnlyHostList := list }} + {{- range $e, $i := until $replicaCount }} + {{- $mongoOnlyHostList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s" $fullname $i $fullname $releaseNamespace $clusterDomain) }} + {{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%s" $fullname $i $fullname $releaseNamespace $clusterDomain (print $port)) }} + {{- end }} + {{- $host = (join "," $mongoOnlyHostList) }} + {{- $hostForURI = (join "," $mongoList) }} +{{- end }} + +{{/* Root user section. */}} +{{- $rootPassword := include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.secretName" .) "key" "mongodb-root-password" "providedValues" (list "auth.rootPassword" ) "honorProvidedValues" true "context" $) | trimAll "\"" | b64dec }} + +{{/* Custom user section. This chart allows creating multiple users */}} +{{- $customUsers := include "mongodb.customUsers" . }} +{{- $customDatabases := include "mongodb.customDatabases" . }} +{{- $customPasswords := include "mongodb.customPasswords" . }} +{{- $passwords := "" }} +{{- $passwordList := list -}} +{{- $customUsersList := list }} +{{- $customDatabasesList := list }} +{{- $customPasswordsList := list }} +{{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} +{{- $customUsersList = splitList "," $customUsers }} +{{- $customDatabasesList = splitList "," $customDatabases }} +{{- if not (empty $customPasswords) }} +{{- $passwordList = $customPasswords }} +{{- $customPasswordsList = splitList "," $customPasswords }} +{{- else }} +{{- range $customUsersList }} +{{- $customPasswordsList = append $customPasswordsList (randAlphaNum 10) }} +{{- end -}} +{{- $passwordList = (join "," $customPasswordsList) }} +{{- end }} +{{- $passwords = include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.secretName" .) "key" "mongodb-passwords" "providedValues" (list "mongodbPasswords") "honorProvidedValues" true "context" (set (deepCopy $) "Values" (dict "mongodbPasswords" $passwordList))) | trimAll "\"" | b64dec }} +{{- end }} + +{{- if (include "mongodb.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ template "mongodb.namespace" . }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + mongodb-root-password: {{ print $rootPassword | b64enc | quote }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + mongodb-passwords: {{ print $passwords | b64enc | quote }} + {{- end }} + {{- if .Values.metrics.username }} + mongodb-metrics-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.fullname" .) "key" "mongodb-metrics-password" "providedValues" (list "metrics.password" ) "honorProvidedValues" true "context" $) }} + {{- end }} + {{- if eq .Values.architecture "replicaset" }} + mongodb-replica-set-key: {{ include "common.secrets.passwords.manage" (dict "secret" (include "mongodb.fullname" .) "key" "mongodb-replica-set-key" "providedValues" (list "auth.replicaSetKey" ) "honorProvidedValues" true "context" $) }} + {{- end }} +{{- end }} +{{- if .Values.serviceBindings.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-svcbind-root + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mongodb +data: + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mongodb" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print .Values.auth.rootUser | b64enc | quote }} + password: {{ print $rootPassword | b64enc | quote }} + database: {{ print "admin" | b64enc | quote }} + uri: {{ printf "mongodb://%s:%s@%s/admin" .Values.auth.rootUser $rootPassword $hostForURI | b64enc | quote }} +{{- range $e, $i := until (len $customUsersList) }} +--- +{{- $currentSecret := printf "%s-svcbind-%d" (include "common.names.fullname" $) $i }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $currentSecret }} + namespace: {{ $.Release.Namespace | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: servicebinding.io/mongodb +data: + {{- $currentUser := index $customUsersList $i }} + {{- $currentDatabase := last $customDatabasesList }} + {{- if gt (len $customDatabasesList) $i }} + {{- $currentDatabase = index $customDatabasesList $i }} + {{- end }} + {{- $currentProvidedPassword := index $customPasswordsList $i }} + {{- $currentPassword := include "common.secrets.lookup" (dict "secret" $currentSecret "key" "password" "defaultValue" $currentProvidedPassword "context" $) | b64dec }} + provider: {{ print "bitnami" | b64enc | quote }} + type: {{ print "mongodb" | b64enc | quote }} + host: {{ print $host | b64enc | quote }} + port: {{ print $port | b64enc | quote }} + username: {{ print $currentUser | b64enc | quote }} + password: {{ print $currentPassword | b64enc | quote }} + database: {{ print $currentDatabase | b64enc | quote }} + uri: {{ printf "mongodb://%s:%s@%s/%s" $currentUser $currentPassword $hostForURI $currentDatabase | b64enc | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/serviceaccount.yaml b/utils/assets/charts/mongodb/templates/serviceaccount.yaml new file mode 100644 index 0000000..b54e8a0 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongodb.serviceAccountName" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +secrets: + - name: {{ include "mongodb.secretName" . }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/servicemonitor.yaml b/utils/assets/charts/mongodb/templates/servicemonitor.yaml new file mode 100644 index 0000000..7849d46 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/servicemonitor.yaml @@ -0,0 +1,48 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.serviceMonitor.namespace" . }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: metrics + endpoints: + - port: http-metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + namespaceSelector: + matchNames: + - "{{ include "mongodb.namespace" . }}" +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/standalone/dep-sts.yaml b/utils/assets/charts/mongodb/templates/standalone/dep-sts.yaml new file mode 100644 index 0000000..c7548e2 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/standalone/dep-sts.yaml @@ -0,0 +1,560 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not (eq .Values.architecture "replicaset") }} +apiVersion: {{ if .Values.useStatefulSet }}{{ include "common.capabilities.statefulset.apiVersion" . }}{{- else }}{{ include "common.capabilities.deployment.apiVersion" . }}{{- end }} +kind: {{ if .Values.useStatefulSet }}StatefulSet{{- else }}Deployment{{- end }} +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + {{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.labels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ gt (.Values.replicaCount | int) 1 | ternary 1 .Values.replicaCount }} + {{- if .Values.useStatefulSet }} + serviceName: {{ include "mongodb.service.nameOverride" . }} + {{- end }} + {{- if .Values.updateStrategy}} + {{- if .Values.useStatefulSet }} + updateStrategy: + {{- else }} + strategy: + {{- end }} + {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end}} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb + template: + metadata: + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/component: mongodb + {{- if or (include "mongodb.createConfigmap" .) .Values.podAnnotations .Values.passwordUpdateJob.enabled }} + annotations: + {{- if (include "mongodb.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.passwordUpdateJob.enabled }} + charts.bitnami.com/password-last-update: {{ now | date "20060102150405" | quote }} + {{- end }} + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "mongodb.serviceAccountName" . }} + {{- if .Values.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "component" "mongodb" "customLabels" $podLabels "topologyKey" .Values.topologyKey "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + {{ if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} + initContainers: + {{- if .Values.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + {{- include "mongodb.initContainer.volumePermissions" . | indent 8 }} + {{- end }} + {{- include "mongodb.initContainer.prepareLogDir" . | nindent 8 }} + {{- if .Values.tls.enabled }} + - name: generate-tls-certs + image: {{ include "mongodb.tls.image" . }} + imagePullPolicy: {{ .Values.tls.image.pullPolicy | quote }} + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.tls.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + mountPath: /certs/CAs + {{- else }} + - name: mongodb-certs-0 + mountPath: /certs-0 + {{- end }} + - name: certs + mountPath: /certs + - name: common-scripts + mountPath: /bitnami/scripts + command: + - /bitnami/scripts/generate-certs.sh + args: + - -s {{ include "mongodb.service.nameOverride" . }} + {{- if .Values.externalAccess.service.loadBalancerIPs }} + - -i {{ join "," .Values.externalAccess.service.loadBalancerIPs }} + {{- end }} + {{- if or .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames }} + - -n {{ join "," ( concat .Values.tls.extraDnsNames .Values.externalAccess.service.publicNames ) }} + {{- end }} + {{- if .Values.tls.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.tls.resources "context" $) | nindent 12 }} + {{- else if ne .Values.tls.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.tls.resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.tls.securityContext }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.tls.securityContext "context" $) | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: mongodb + image: {{ include "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + {{- $customUsers := include "mongodb.customUsers" . -}} + {{- $customDatabases := include "mongodb.customDatabases" . -}} + {{- if not (empty $customUsers) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + {{- end }} + {{- if not (empty $customDatabases) }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- end }} + {{- if .Values.auth.enabled }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_EXTRA_PASSWORDS_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-passwords" + {{- else }} + - name: MONGODB_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-passwords + {{- end }} + {{- end }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + {{- else }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + {{- end }} + {{- if and .Values.metrics.enabled (not (empty .Values.metrics.username)) }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.auth.enabled }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_METRICS_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-metrics-password" + {{- else }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + {{- end }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.fips "global" .Values.global) | quote }} + {{- end }} + - name: ALLOW_EMPTY_PASSWORD + value: {{ ternary "no" "yes" .Values.auth.enabled | quote }} + - name: MONGODB_SYSTEM_LOG_VERBOSITY + value: {{ .Values.systemLogVerbosity | quote }} + - name: MONGODB_DISABLE_SYSTEM_LOG + value: {{ ternary "yes" "no" .Values.disableSystemLog | quote }} + - name: MONGODB_DISABLE_JAVASCRIPT + value: {{ ternary "yes" "no" .Values.disableJavascript | quote }} + - name: MONGODB_ENABLE_JOURNAL + value: {{ ternary "yes" "no" .Values.enableJournal | quote }} + - name: MONGODB_PORT_NUMBER + value: {{ .Values.containerPorts.mongodb | quote }} + - name: MONGODB_ENABLE_IPV6 + value: {{ ternary "yes" "no" .Values.enableIPv6 | quote }} + - name: MONGODB_ENABLE_DIRECTORY_PER_DB + value: {{ ternary "yes" "no" .Values.directoryPerDB | quote }} + {{- $extraFlags := .Values.extraFlags | join " " -}} + {{- if .Values.tls.enabled }} + {{- if .Values.tls.mTLS.enabled }} + {{- $extraFlags = printf "--tlsCAFile=/certs/mongodb-ca-cert %s" $extraFlags }} + {{- end }} + {{- $extraFlags = printf "--tlsMode=%s --tlsCertificateKeyFile=/certs/mongodb.pem %s" .Values.tls.mode $extraFlags }} + {{- end }} + {{- if ne $extraFlags "" }} + - name: MONGODB_EXTRA_FLAGS + value: {{ $extraFlags | quote }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: MONGODB_CLIENT_EXTRA_FLAGS + value: --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.extraEnvVarsCM .Values.extraEnvVarsSecret }} + envFrom: + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ tpl .Values.extraEnvVarsCM . | quote }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ tpl .Values.extraEnvVarsSecret . | quote }} + {{- end }} + {{- end }} + ports: + - name: mongodb + containerPort: {{ .Values.containerPorts.mongodb }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/ping-mongodb.sh + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/readiness-probe.sh + {{- end }} + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bitnami/scripts/startup-probe.sh + {{- end }} + {{- end }} + {{- if .Values.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.resources "context" $) | nindent 12 }} + {{- else if ne .Values.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.resourcesPreset) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/conf + subPath: app-conf-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/tmp + subPath: app-tmp-dir + - name: empty-dir + mountPath: /opt/bitnami/mongodb/logs + subPath: app-logs-dir + - name: empty-dir + mountPath: /.mongodb + subPath: mongosh-home + - name: {{ .Values.persistence.name | default "datadir" }} + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + - name: common-scripts + mountPath: /bitnami/scripts + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + mountPath: /opt/bitnami/mongodb/conf/mongodb.conf + subPath: mongodb.conf + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "mongodb.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.metrics.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + {{- if .Values.metrics.username }} + export MONGODB_METRICS_PASSWORD="$(< $MONGODB_METRICS_PASSWORD_FILE)" + {{- else }} + export MONGODB_ROOT_PASSWORD="$(< $MONGODB_ROOT_PASSWORD_FILE)" + {{- end }} + {{- end }} + /bin/mongodb_exporter {{ include "mongodb.exporterArgs" $ }} --mongodb.direct-connect --mongodb.global-conn-pool --web.listen-address ":{{ .Values.metrics.containerPort }}" --mongodb.uri "{{ include "mongodb.mongodb_exporter.uri" . }}" {{ .Values.metrics.extraFlags }} + {{- end }} + env: + {{- if .Values.auth.enabled }} + {{- if not .Values.metrics.username }} + - name: MONGODB_ROOT_USER + value: {{ .Values.auth.rootUser | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_ROOT_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-root-password" + {{- else }} + - name: MONGODB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-root-password + {{- end }} + {{- else }} + - name: MONGODB_METRICS_USERNAME + value: {{ .Values.metrics.username | quote }} + {{- if .Values.usePasswordFiles }} + - name: MONGODB_METRICS_PASSWORD_FILE + value: "/opt/bitnami/mongodb/secrets/mongodb-metrics-password" + {{- else }} + - name: MONGODB_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mongodb.secretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + {{- end }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.metrics.fips "global" .Values.global) | quote }} + - name: GODEBUG + value: {{ include "common.fips.config" (dict "tech" "golang" "fips" .Values.metrics.fips "global" .Values.global) | quote }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /tmp + subPath: tmp-dir + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + mountPath: /opt/bitnami/mongodb/secrets + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /certs + {{- end }} + {{- if .Values.metrics.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + ports: + - name: metrics + containerPort: {{ .Values.metrics.containerPort }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: metrics + {{- end }} + {{- if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: metrics + {{- end }} + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.resources "context" $) | nindent 12 }} + {{- else if ne .Values.metrics.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.metrics.resourcesPreset) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + - name: common-scripts + configMap: + name: {{ printf "%s-common-scripts" (include "mongodb.fullname" .) }} + defaultMode: 0550 + {{- if and .Values.usePasswordFiles .Values.auth.enabled }} + - name: mongodb-secrets + secret: + secretName: {{ include "mongodb.secretName" . }} + {{- end }} + {{- if or .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "mongodb.initdbScriptsCM" . }} + {{- end }} + {{- if or .Values.configuration .Values.existingConfigmap }} + - name: config + configMap: + name: {{ include "mongodb.configmapName" . }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if (include "mongodb.autoGenerateCerts" .) }} + - name: certs-volume + secret: + secretName: {{ template "mongodb.tlsSecretName" . }} + items: + - key: mongodb-ca-cert + path: mongodb-ca-cert + mode: 0600 + - key: mongodb-ca-key + path: mongodb-ca-key + mode: 0600 + {{- else }} + - name: mongodb-certs-0 + secret: + secretName: {{ include "common.tplvalues.render" ( dict "value" .Values.tls.standalone.existingSecret "context" $) }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: {{ .Values.persistence.name | default "datadir" }} + {{- if .Values.persistence.medium }} + emptyDir: + medium: {{ .Values.persistence.medium | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else if .Values.persistence.existingClaim }} + - name: {{ .Values.persistence.name | default "datadir" }} + persistentVolumeClaim: + claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }} + {{- else if not .Values.useStatefulSet }} + - name: {{ .Values.persistence.name | default "datadir" }} + persistentVolumeClaim: + claimName: {{ template "mongodb.fullname" . }} + {{- else }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + volumeClaimTemplates: + - metadata: + name: {{ .Values.persistence.name | default "datadir" }} + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.persistence.labels }} + labels: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.labels "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/standalone/pdb.yaml b/utils/assets/charts/mongodb/templates/standalone/pdb.yaml new file mode 100644 index 0000000..d11b39a --- /dev/null +++ b/utils/assets/charts/mongodb/templates/standalone/pdb.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (not (eq .Values.architecture "replicaset")) .Values.pdb.create }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if or .Values.pdb.maxUnavailable (not .Values.pdb.minAvailable) }} + maxUnavailable: {{ .Values.pdb.maxUnavailable | default 1 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: + matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/standalone/pvc.yaml b/utils/assets/charts/mongodb/templates/standalone/pvc.yaml new file mode 100644 index 0000000..1609858 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/standalone/pvc.yaml @@ -0,0 +1,31 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (not (eq .Values.architecture "replicaset")) (not .Values.useStatefulSet) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "mongodb.fullname" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + annotations: + {{- if .Values.persistence.resourcePolicy }} + helm.sh/resource-policy: {{ .Values.persistence.resourcePolicy | quote }} + {{- end }} + {{- if or .Values.persistence.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.persistence.annotations .Values.commonAnnotations ) "context" . ) }} + {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/standalone/svc.yaml b/utils/assets/charts/mongodb/templates/standalone/svc.yaml new file mode 100644 index 0000000..84869a3 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/standalone/svc.yaml @@ -0,0 +1,63 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not (eq .Values.architecture "replicaset") }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mongodb.service.nameOverride" . }} + namespace: {{ include "mongodb.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb + {{- if or .Values.service.annotations .Values.commonAnnotations }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.service.loadBalancerClass }} + {{- end }} + {{- if .Values.service.externalIPs }} + externalIPs: {{ toYaml .Values.service.externalIPs | nindent 4 }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + {{- if (eq .Values.service.type "LoadBalancer") }} + allocateLoadBalancerNodePorts: {{ .Values.service.allocateLoadBalancerNodePorts }} + {{- end }} + {{- if ne .Values.service.sessionAffinity "None" }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + {{- end }} + {{- if (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + publishNotReadyAddresses: {{ .Values.service.publishNotReadyAddresses }} + ports: + - name: {{ .Values.service.portName | quote }} + port: {{ .Values.service.ports.mongodb }} + targetPort: mongodb + {{- if and (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) .Values.service.nodePorts.mongodb }} + nodePort: {{ .Values.service.nodePorts.mongodb }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }} + selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/component: mongodb +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/update-password/job.yaml b/utils/assets/charts/mongodb/templates/update-password/job.yaml new file mode 100644 index 0000000..56e0a49 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/update-password/job.yaml @@ -0,0 +1,249 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.passwordUpdateJob.enabled }} +{{- $customUsers := include "mongodb.customUsers" . }} +{{- $customDatabases := include "mongodb.customDatabases" . }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-password-update" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: mongodb + app.kubernetes.io/component: update-job + {{- $defaultAnnotations := dict "helm.sh/hook" "pre-upgrade" "helm.sh/hook-delete-policy" "hook-succeeded" }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonAnnotations $defaultAnnotations .Values.passwordUpdateJob.annotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} +spec: + backoffLimit: {{ .Values.passwordUpdateJob.backoffLimit }} + template: + metadata: + {{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.passwordUpdateJob.podLabels .Values.commonLabels ) "context" . ) }} + labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }} + app.kubernetes.io/part-of: mongodb + app.kubernetes.io/component: update-job + {{- if .Values.passwordUpdateJob.podAnnotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.podAnnotations "context" $) | nindent 8 }} + {{- end }} + spec: + {{- include "mongodb.imagePullSecrets" . | nindent 6 }} + restartPolicy: OnFailure + {{- if .Values.passwordUpdateJob.podSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.passwordUpdateJob.podSecurityContext "context" $) | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.passwordUpdateJob.automountServiceAccountToken }} + {{- if .Values.passwordUpdateJob.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.hostAliases "context" $) | nindent 8 }} + {{- end }} + initContainers: + {{- if .Values.passwordUpdateJob.initContainers }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.initContainers "context" $) | nindent 8 }} + {{- end }} + containers: + - name: update-credentials + image: {{ template "mongodb.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.passwordUpdateJob.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.command "context" $) | nindent 12 }} + {{- else }} + command: + - /bin/bash + - -ec + {{- end }} + {{- if .Values.passwordUpdateJob.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.args "context" $) | nindent 12 }} + {{- else }} + args: + - | + {{- if .Values.usePasswordFiles }} + # We need to load all the secret env vars to the system + for file in $(find /bitnami/mongodb/secrets -type f); do + env_var_name="$(basename $file)" + echo "Exporting $env_var_name" + export $env_var_name="$(< $file)" + done + {{- end }} + + . /opt/bitnami/scripts/mongodb-env.sh + . /opt/bitnami/scripts/libmongodb.sh + . /opt/bitnami/scripts/liblog.sh + + protocol=mongodb + {{- if eq .Values.architecture "replicaset" }} + replicaset={{- range $i, $_ := until (int .Values.replicaCount) }}{{- if ne $i 0 }},{{- end }}{{ include "common.names.fullname" $ }}-{{ $i }}.{{ include "mongodb.service.nameOverride" $ }}:{{ $.Values.containerPorts.mongodb }}{{- end }} + {{- else }} + replicaset={{ include "common.names.fullname" . }}:{{ .Values.service.ports.mongodb }} + {{- end }} + + info "Starting password update job" + if [[ -f /job-status/root-password-changed ]]; then + info "Root password already updated. Skipping" + else + info "Updating root password" + mongosh "${protocol}://$MONGODB_ROOT_USER:$MONGODB_PREVIOUS_ROOT_PASSWORD@$replicaset/admin" --eval "db.changeUserPassword('$MONGODB_ROOT_USER', '$MONGODB_NEW_ROOT_PASSWORD')" + touch /job-status/root-password-changed + info "Root password successfully updated" + fi + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + + databases_extra=() + usernames_extra=() + IFS="$(mongodb_field_separator "$MONGODB_EXTRA_DATABASES")" read -r -a databases_extra <<<"$MONGODB_EXTRA_DATABASES" + IFS="$(mongodb_field_separator "$MONGODB_EXTRA_USERNAMES")" read -r -a usernames_extra <<<"$MONGODB_EXTRA_USERNAMES" + new_passwords_extra=() + IFS="$(mongodb_field_separator "$MONGODB_NEW_EXTRA_PASSWORDS")" read -r -a new_passwords_extra <<<"$MONGODB_NEW_EXTRA_PASSWORDS" + + for ((i = 0; i < ${#usernames_extra[@]}; i++)); do + if [[ -f /job-status/password-${usernames_extra[i]}-changed ]]; then + info "User ${usernames_extra[i]} password already updated. Skipping" + else + info "Updating user ${usernames_extra[i]} password" + mongosh "${protocol}://$MONGODB_ROOT_USER:$MONGODB_NEW_ROOT_PASSWORD@$replicaset/${databases_extra[i]}?authSource=admin" --eval "db.changeUserPassword('${usernames_extra[i]}', '${new_passwords_extra[i]}');" + touch /job-status/password-${usernames_extra[i]}-changed + info "User ${usernames_extra[i]} password successfully updated" + fi + done + + {{- end }} + + {{- if .Values.metrics.username }} + if [[ -f /job-status/metrics-password-changed ]]; then + info "Metrics password already updated. Skipping" + else + info "Updating metrics password" + mongosh "${protocol}://$MONGODB_ROOT_USER:$MONGODB_NEW_ROOT_PASSWORD@$replicaset/admin" --eval "db.changeUserPassword('$MONGODB_METRICS_USER', '$MONGODB_NEW_METRICS_PASSWORD')" + touch /job-status/root-password-changed + info "Metrics password successfully updated" + fi + {{- end }} + + {{- if .Values.passwordUpdateJob.extraCommands }} + info "Running extra commmands" + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraCommands "context" $) | nindent 14 }} + {{- end }} + info "Password update job finished successfully" + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + {{- if not .Values.usePasswordFiles }} + - name: MONGODB_PREVIOUS_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mongodb.update-job.previousSecretName" . }} + key: mongodb-root-password + - name: MONGODB_NEW_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mongodb.update-job.newSecretName" . }} + key: mongodb-root-password + {{- end }} + {{- if include "common.fips.enabled" . }} + - name: OPENSSL_FIPS + value: {{ include "common.fips.config" (dict "tech" "openssl" "fips" .Values.passwordUpdateJob.fips "global" .Values.global) | quote }} + {{- end }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - name: MONGODB_EXTRA_USERNAMES + value: {{ $customUsers | quote }} + - name: MONGODB_EXTRA_DATABASES + value: {{ $customDatabases | quote }} + {{- if not .Values.usePasswordFiles }} + - name: MONGODB_NEW_EXTRA_PASSWORDS + valueFrom: + secretKeyRef: + name: {{ template "mongodb.update-job.newSecretName" . }} + key: mongodb-passwords + {{- end }} + {{- end }} + {{- if .Values.metrics.username }} + - name: MONGODB_METRICS_USER + value: {{ .Values.metrics.username | quote }} + {{- if not .Values.usePasswordFiles }} + - name: MONGODB_PREVIOUS_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mongodb.update-job.previousSecretName" . }} + key: mongodb-metrics-password + - name: MONGODB_NEW_METRICS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "mongodb.update-job.newSecretName" . }} + key: mongodb-metrics-password + {{- end }} + {{- end }} + {{- if .Values.passwordUpdateJob.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.passwordUpdateJob.extraEnvVarsCM .Values.passwordUpdateJob.extraEnvVarsSecret }} + envFrom: + {{- if .Values.passwordUpdateJob.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.passwordUpdateJob.extraEnvVarsCM }} + {{- end }} + {{- if .Values.passwordUpdateJob.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.passwordUpdateJob.extraEnvVarsSecret }} + {{- end }} + {{- end }} + {{- if .Values.passwordUpdateJob.containerSecurityContext.enabled }} + securityContext: {{- include "common.compatibility.renderSecurityContext" (dict "secContext" .Values.passwordUpdateJob.containerSecurityContext "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.customStartupProbe "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + - name: empty-dir + mountPath: /job-status + subPath: job-dir + {{- if .Values.usePasswordFiles }} + - name: mongodb-previous-credentials + mountPath: /bitnami/mongodb/secrets/previous + - name: mongodb-new-credentials + mountPath: /bitnami/mongodb/secrets/new + {{- end }} + {{- if .Values.passwordUpdateJob.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.passwordUpdateJob.resources }} + resources: {{- toYaml .Values.passwordUpdateJob.resources | nindent 12 }} + {{- else if ne .Values.passwordUpdateJob.resourcesPreset "none" }} + resources: {{- include "common.resources.preset" (dict "type" .Values.passwordUpdateJob.resourcesPreset) | nindent 12 }} + {{- end }} + volumes: + - name: empty-dir + emptyDir: {} + {{- if and .Values.usePasswordFiles }} + - name: mongodb-previous-credentials + secret: + secretName: {{ template "mongodb.update-job.previousSecretName" . }} + items: + - key: mongodb-root-password + path: MONGODB_PREVIOUS_ROOT_PASSWORD + - name: mongodb-new-credentials + secret: + secretName: {{ template "mongodb.update-job.newSecretName" . }} + items: + - key: mongodb-root-password + path: MONGODB_NEW_ROOT_PASSWORD + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + - key: mongodb-passwords + path: MONGODB_NEW_EXTRA_PASSWORDS + {{- end }} + {{- if .Values.metrics.username }} + - key: mongodb-metrics-password + path: MONGODB_NEW_METRICS_PASSWORD + {{- end }} + {{- end }} + {{- if .Values.passwordUpdateJob.extraVolumes }} + {{- include "common.tplvalues.render" (dict "value" .Values.passwordUpdateJob.extraVolumes "context" $) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/update-password/new-secret.yaml b/utils/assets/charts/mongodb/templates/update-password/new-secret.yaml new file mode 100644 index 0000000..0e0386a --- /dev/null +++ b/utils/assets/charts/mongodb/templates/update-password/new-secret.yaml @@ -0,0 +1,32 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.passwordUpdateJob.enabled (include "mongodb.createSecret" .) (not ( include "mongodb.createPreviousSecret" . )) (not .Values.passwordUpdateJob.previousPasswords.existingSecret) }} +{{- $rootPassword := .Values.auth.rootPassword }} +{{- $metricsPassword := .Values.metrics.password }} +{{- $customUsers := include "mongodb.customUsers" . }} +{{- $customPasswords := join "," (include "mongodb.customPasswords" .) }} +{{- $customDatabases := include "mongodb.customDatabases" . }} +{{- $replicationPassword := .Values.auth.replicationPassword }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-new-secret" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: mongodb + {{- $defaultAnnotations := dict "helm.sh/hook" "pre-upgrade" "helm.sh/hook-delete-policy" "hook-succeeded" }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonAnnotations $defaultAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} +type: Opaque +data: + mongodb-root-password: {{ required "The new root password is required!" $rootPassword | b64enc | quote }} + {{- if and (not (empty $customUsers)) (not (empty $customDatabases)) }} + mongodb-passwords: {{ required "The new custom passwords are required!" $customPasswords | b64enc | quote }} + {{- end }} + {{- if .Values.metrics.username }} + mongodb-metrics-password: {{ required "The new metrics password is required!" $metricsPassword | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/mongodb/templates/update-password/previous-secret.yaml b/utils/assets/charts/mongodb/templates/update-password/previous-secret.yaml new file mode 100644 index 0000000..a1db9f8 --- /dev/null +++ b/utils/assets/charts/mongodb/templates/update-password/previous-secret.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright Broadcom, Inc. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.passwordUpdateJob.enabled (eq ( include "mongodb.createPreviousSecret" . ) "true") }} +{{- $rootPassword := .Values.passwordUpdateJob.previousPasswords.rootPassword }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-previous-secret" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }} + app.kubernetes.io/part-of: mongodb + {{- $defaultAnnotations := dict "helm.sh/hook" "pre-upgrade" "helm.sh/hook-delete-policy" "hook-succeeded" }} + {{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.commonAnnotations $defaultAnnotations ) "context" . ) }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $ ) | nindent 4 }} +type: Opaque +data: + mongodb-root-password: {{ required "The previous root password is required!" $rootPassword | b64enc | quote }} +{{- end }} diff --git a/utils/assets/charts/mongodb/values.schema.json b/utils/assets/charts/mongodb/values.schema.json new file mode 100644 index 0000000..3eb6a64 --- /dev/null +++ b/utils/assets/charts/mongodb/values.schema.json @@ -0,0 +1,232 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "MongoDB® architecture", + "form": true, + "description": "Allowed values: `standalone` or `replicaset`" + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Authentication", + "form": true + }, + "rootUser": { + "type": "string", + "title": "MongoDB® admin user", + "form": true, + "description": "Name of the admin user. Default is root" + }, + "rootPassword": { + "type": "string", + "title": "MongoDB® admin password", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + }, + "database": { + "type": "string", + "title": "MongoDB® custom database", + "description": "Name of the custom database to be created during the 1st initialization of MongoDB®", + "form": true + }, + "username": { + "type": "string", + "title": "MongoDB® custom user", + "description": "Name of the custom user to be created during the 1st initialization of MongoDB®. This user only has permissions on the MongoDB® custom database", + "form": true + }, + "password": { + "type": "string", + "title": "Password for MongoDB® custom user", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": false, + "path": "auth/enabled" + } + }, + "replicaSetKey": { + "type": "string", + "title": "Key used for replica set authentication", + "form": true, + "description": "Defaults to a random 10-character alphanumeric string if not set", + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "replicaCount": { + "type": "integer", + "form": true, + "title": "Number of MongoDB® replicas", + "hidden": { + "value": "standalone", + "path": "architecture" + } + }, + "configuration": { + "type": "string", + "title": "MongoDB® Custom Configuration", + "form": true, + "render": "textArea" + }, + "arbiter": { + "type": "object", + "title": "Arbiter configuration", + "form": true, + "properties": { + "configuration": { + "type": "string", + "title": "Arbiter Custom Configuration", + "form": true, + "render": "textArea", + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "networkPolicy": { + "type": "object", + "title": "Network policy configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable network policy", + "description": "Enable network policy using Kubernetes native NP", + "hidden": { + "value": false, + "path": "networkPolicy/enabled" + } + }, + "ingress": { + "type": "object", + "properties": { + "namespaceSelector": { + "type": "object", + "title": "Namespace selector label that is allowed to access this instance", + "hidden": { + "value": {}, + "path": "networkPolicy/ingress/namespaceSelector" + } + }, + "podSelector": { + "type": "object", + "title": "Pod selector label that is allowed to access this instance", + "hidden": { + "value": {}, + "path": "networkPolicy/ingress/podSelector" + } + }, + "customRules": { + "type": "array", + "title": "Custom rules for ingress network policy", + "hidden": { + "value": [], + "path": "networkPolicy/ingress/customRules" + } + } + } + }, + "egress": { + "type": "object", + "properties": { + "customRules": { + "type": "array", + "title": "Custom rules for egress network policy", + "hidden": { + "value": [], + "path": "networkPolicy/egress/customRules" + } + } + } + } + } + }, + "persistence": { + "type": "object", + "title": "Persistence configuration", + "form": true, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable persistence", + "description": "Enable persistence using Persistent Volume Claims" + }, + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi", + "hidden": { + "value": false, + "path": "persistence/enabled" + } + } + } + }, + "volumePermissions": { + "type": "object", + "hidden": { + "value": false, + "path": "persistence/enabled" + }, + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" + } + } + }, + "metrics": { + "type": "object", + "form": true, + "title": "Prometheus metrics details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus metrics exporter", + "description": "Create a side-car container to expose Prometheus metrics", + "form": true + }, + "serviceMonitor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Create Prometheus Operator ServiceMonitor", + "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", + "form": true, + "hidden": { + "value": false, + "path": "metrics/enabled" + } + } + } + } + } + } + } +} diff --git a/utils/assets/charts/mongodb/values.yaml b/utils/assets/charts/mongodb/values.yaml new file mode 100644 index 0000000..f740ff7 --- /dev/null +++ b/utils/assets/charts/mongodb/values.yaml @@ -0,0 +1,2711 @@ +# Copyright Broadcom, Inc. All Rights Reserved. +# SPDX-License-Identifier: APACHE-2.0 + +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s) +## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead +## @param global.namespaceOverride Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride +## @param global.defaultFips Default value for the FIPS configuration (allowed values: '', restricted, relaxed, off). Can be overriden by the 'fips' object +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + defaultStorageClass: "" + storageClass: "" + ## Security parameters + ## + security: + ## @param global.security.allowInsecureImages Allows skipping image verification + allowInsecureImages: false + namespaceOverride: "" + ## Compatibility adaptations for Kubernetes platforms + ## + compatibility: + ## Compatibility adaptations for Openshift + ## + openshift: + ## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation) + ## + adaptSecurityContext: auto + ## Configure FIPS mode: '', 'restricted', 'relaxed', 'off' + ## + defaultFips: restricted +## @section Common parameters +## + +## @param nameOverride String to partially override mongodb.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override mongodb.fullname template +## +fullnameOverride: "" +## @param namespaceOverride String to fully override common.names.namespace +## +namespaceOverride: "" +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param clusterDomain Default Kubernetes cluster domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## extraDeploy: +## This needs to be uncommented and added to 'extraDeploy' in order to use the replicaset 'mongo-labeler' sidecar +## for dynamically discovering the mongodb primary pod +## suggestion is to use a hard-coded and predictable TCP port for the primary mongodb pod (here is 30001, choose your own) +## - apiVersion: v1 +## kind: Service +## metadata: +## name: mongodb-primary +## namespace: the-mongodb-namespace +## labels: +## app.kubernetes.io/component: mongodb +## app.kubernetes.io/instance: mongodb +## app.kubernetes.io/managed-by: Helm +## app.kubernetes.io/name: mongodb +## spec: +## type: NodePort +## externalTrafficPolicy: Cluster +## ports: +## - name: mongodb +## port: 30001 +## nodePort: 30001 +## protocol: TCP +## targetPort: mongodb +## selector: +## app.kubernetes.io/component: mongodb +## app.kubernetes.io/instance: mongodb +## app.kubernetes.io/name: mongodb +## primary: "true" +## +extraDeploy: [] +## @param commonLabels Add labels to all the deployed resources (sub-charts are not considered). Evaluated as a template +## +commonLabels: {} +## @param commonAnnotations Common annotations to add to all Mongo resources (sub-charts are not considered). Evaluated as a template +## +commonAnnotations: {} +## @param topologyKey Override common lib default topology key. If empty - "kubernetes.io/hostname" is used +## i.e. topologyKey: topology.kubernetes.io/zone +## +topologyKey: "" +## @param serviceBindings.enabled Create secret for service binding (Experimental) +## Ref: https://servicebinding.io/service-provider/ +## +serviceBindings: + enabled: false +## @param enableServiceLinks Whether information about services should be injected into pod's environment variable +## The environment variables injected by service links are not used, but can lead to slow boot times or slow running of the scripts when there are many services in the current namespace. +## If you experience slow pod startups or slow running of the scripts you probably want to set this to `false`. +## +enableServiceLinks: true +## @param usePasswordFiles Mount credentials as files instead of using environment variables +## +usePasswordFiles: true +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity +## @section MongoDB(®) parameters +## + +## Bitnami MongoDB(®) image +## ref: https://hub.docker.com/r/bitnami/mongodb/tags/ +## @param image.registry [default: REGISTRY_NAME] MongoDB(®) image registry +## @param image.repository [default: REPOSITORY_NAME/mongodb] MongoDB(®) image registry +## @skip image.tag MongoDB(®) image tag (immutable tags are recommended) +## @param image.digest MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag +## @param image.pullPolicy MongoDB(®) image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Set to true if you would like to see extra information on logs +## +image: + registry: registry-1.docker.io + repository: bitnami/mongodb + tag: latest + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false +## @param schedulerName Name of the scheduler (other than default) to dispatch pods +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param architecture MongoDB(®) architecture (`standalone` or `replicaset`) +## +architecture: standalone +## @param useStatefulSet Set to true to use a StatefulSet instead of a Deployment (only when `architecture=standalone`) +## +useStatefulSet: false +## MongoDB(®) Authentication parameters +## +auth: + ## @param auth.enabled Enable authentication + ## ref: https://docs.mongodb.com/manual/tutorial/enable-authentication/ + ## + enabled: true + ## @param auth.rootUser MongoDB(®) root user + ## + rootUser: root + ## @param auth.rootPassword MongoDB(®) root password + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#setting-the-root-user-and-password-on-first-run + ## + rootPassword: "" + ## MongoDB(®) custom users and databases + ## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#creating-a-user-and-database-on-first-run + ## @param auth.usernames List of custom users to be created during the initialization + ## @param auth.passwords List of passwords for the custom users set at `auth.usernames` + ## @param auth.databases List of custom databases to be created during the initialization + ## + usernames: [] + passwords: [] + databases: [] + ## @param auth.username DEPRECATED: use `auth.usernames` instead + ## @param auth.password DEPRECATED: use `auth.passwords` instead + ## @param auth.database DEPRECATED: use `auth.databases` instead + ## + username: "" + password: "" + database: "" + ## @param auth.replicaSetKey Key used for authentication in the replicaset (only when `architecture=replicaset`) + ## + replicaSetKey: "" + ## @param auth.existingSecret Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) + ## NOTE: When it's set the previous parameters are ignored. + ## + existingSecret: "" +tls: + ## @param tls.enabled Enable MongoDB(®) TLS support between nodes in the cluster as well as between mongo clients and nodes + ## + enabled: false + mTLS: + ## @param tls.mTLS.enabled IF TLS support is enabled, require clients to provide certificates + enabled: true + ## @param tls.autoGenerated Generate a custom CA and self-signed certificates + ## + autoGenerated: true + ## @param tls.existingSecret Existing secret with TLS certificates (keys: `mongodb-ca-cert`, `mongodb-ca-key`) + ## NOTE: When it's set it will disable secret creation. + ## + existingSecret: "" + ## Add Custom CA certificate + ## @param tls.caCert Custom CA certificated (base64 encoded) + ## @param tls.caKey CA certificate private key (base64 encoded) + ## + caCert: "" + caKey: "" + ## @param tls.pemChainIncluded Flag to denote that the Certificate Authority (CA) certificates are bundled with the endpoint cert. + ## Certificates must be in proper order, where the top certificate is the leaf and the bottom certificate is the top-most intermediate CA. + ## + pemChainIncluded: false + standalone: + ## @param tls.standalone.existingSecret Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecret: "" + replicaset: + ## @param tls.replicaset.existingSecrets Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## existingSecrets: + ## - "mySecret-0" + ## - "mySecret-1" + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecrets: [] + hidden: + ## @param tls.hidden.existingSecrets Array of existing secrets with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## existingSecrets: + ## - "mySecret-0" + ## - "mySecret-1" + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecrets: [] + arbiter: + ## @param tls.arbiter.existingSecret Existing secret with TLS certificates (`tls.key`, `tls.crt`, `ca.crt`) or (`tls.key`, `tls.crt`) with tls.pemChainIncluded set as enabled. + ## NOTE: When it's set it will disable certificate self-generation from existing CA. + ## + existingSecret: "" + ## Bitnami Nginx image + ## @param tls.image.registry [default: REGISTRY_NAME] Init container TLS certs setup image registry + ## @param tls.image.repository [default: REPOSITORY_NAME/nginx] Init container TLS certs setup image repository + ## @skip tls.image.tag Init container TLS certs setup image tag (immutable tags are recommended) + ## @param tls.image.digest Init container TLS certs setup image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param tls.image.pullPolicy Init container TLS certs setup image pull policy + ## @param tls.image.pullSecrets Init container TLS certs specify docker-registry secret names as an array + ## @param tls.extraDnsNames Add extra dns names to the CA, can solve x509 auth issue for pod clients + ## + image: + registry: registry-1.docker.io + repository: bitnami/nginx + tag: latest + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## e.g: + ## extraDnsNames + ## "DNS.6": "$my_host" + ## "DNS.7": "$test" + ## + extraDnsNames: [] + ## @param tls.mode Allows to set the tls mode which should be used when tls is enabled (options: `allowTLS`, `preferTLS`, `requireTLS`) + ## + mode: requireTLS + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param tls.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if tls.resources is set (tls.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param tls.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param tls.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## Init Container securityContext + ## ref: https://kubernetes.io/docs/concepts/security/pod-security-policy/ + ## @param tls.securityContext Init container generate-tls-cert Security context + ## + securityContext: {} + ## Example: + ## allowPrivilegeEscalation: false + ## capabilities: + ## drop: ["ALL"] + ## +## @param automountServiceAccountToken Mount Service Account token in pod +## +automountServiceAccountToken: false +## @param hostAliases Add deployment host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## @param replicaSetName Name of the replica set (only when `architecture=replicaset`) +## Ignored when mongodb.architecture=standalone +## +replicaSetName: rs0 +## @param replicaSetHostnames Enable DNS hostnames in the replicaset config (only when `architecture=replicaset`) +## Ignored when mongodb.architecture=standalone +## Ignored when externalAccess.enabled=true +## +replicaSetHostnames: true +## @param enableIPv6 Switch to enable/disable IPv6 on MongoDB(®) +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#enablingdisabling-ipv6 +## +enableIPv6: false +## @param directoryPerDB Switch to enable/disable DirectoryPerDB on MongoDB(®) +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#enablingdisabling-directoryperdb +## +directoryPerDB: false +## MongoDB(®) System Log configuration +## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#configuring-system-log-verbosity-level +## @param systemLogVerbosity MongoDB(®) system log verbosity level +## @param disableSystemLog Switch to enable/disable MongoDB(®) system log +## +systemLogVerbosity: 0 +disableSystemLog: false +## @param disableJavascript Switch to enable/disable MongoDB(®) server-side JavaScript execution +## ref: https://docs.mongodb.com/manual/core/server-side-javascript/ +## +disableJavascript: false +## @param enableJournal Switch to enable/disable MongoDB(®) Journaling +## ref: https://docs.mongodb.com/manual/reference/configuration-options/#mongodb-setting-storage.journal.enabled +## +enableJournal: true +## @param configuration MongoDB(®) configuration file to be used for Primary and Secondary nodes +## For documentation of all options, see: http://docs.mongodb.org/manual/reference/configuration-options/ +## Example: +## configuration: |- +## # where and how to store data. +## storage: +## dbPath: /bitnami/mongodb/data/db +## journal: +## enabled: true +## directoryPerDB: false +## # where to write logging data +## systemLog: +## destination: file +## quiet: false +## logAppend: true +## logRotate: reopen +## path: /opt/bitnami/mongodb/logs/mongodb.log +## verbosity: 0 +## # network interfaces +## net: +## port: 27017 +## unixDomainSocket: +## enabled: true +## pathPrefix: /opt/bitnami/mongodb/tmp +## ipv6: false +## bindIpAll: true +## # replica set options +## #replication: +## #replSetName: replicaset +## #enableMajorityReadConcern: true +## # process management options +## processManagement: +## fork: false +## pidFilePath: /opt/bitnami/mongodb/tmp/mongodb.pid +## # set parameter options +## setParameter: +## enableLocalhostAuthBypass: true +## # security options +## security: +## authorization: disabled +## #keyFile: /opt/bitnami/mongodb/conf/keyfile +## +configuration: "" +## @section replicaSetConfigurationSettings settings applied during runtime (not via configuration file) +## If enabled, these are applied by a script which is called within setup.sh +## for documentation see https://docs.mongodb.com/manual/reference/replica-configuration/#replica-set-configuration-fields +## @param replicaSetConfigurationSettings.enabled Enable MongoDB(®) Switch to enable/disable configuring MongoDB(®) run time rs.conf settings +## @param replicaSetConfigurationSettings.configuration run-time rs.conf settings +## +replicaSetConfigurationSettings: + enabled: false + configuration: {} +## Custom configurations for individual replica set members. +## Use the prefix 'members[X].' to apply settings to the member X of the replica set. +## Example: 'members[0].priority: 3' sets the priority of the first replica set member to 3. +## The index X in 'members[X]' corresponds to the member's position in the replica set. +## members[0].priority: 3 +## chainingAllowed : false +## heartbeatTimeoutSecs : 10 +## heartbeatIntervalMillis : 2000 +## electionTimeoutMillis : 10000 +## catchUpTimeoutMillis : 30000 +## @param existingConfigmap Name of existing ConfigMap with MongoDB(®) configuration for Primary and Secondary nodes +## NOTE: When it's set the arbiter.configuration parameter is ignored +## +existingConfigmap: "" +## @param initdbScripts Dictionary of initdb scripts +## Specify dictionary of scripts to be run at first boot +## Example: +## initdbScripts: +## my_init_script.sh: | +## #!/bin/bash +## echo "Do something." +## +initdbScripts: {} +## @param initdbScriptsConfigMap Existing ConfigMap with custom initdb scripts +## +initdbScriptsConfigMap: "" +## Command and args for running the container (set to default if not set). Use array form +## @param command Override default container command (useful when using custom images) +## @param args Override default container args (useful when using custom images) +## +command: [] +args: [] +## @param extraFlags MongoDB(®) additional command line flags +## Example: +## extraFlags: +## - "--wiredTigerCacheSizeGB=2" +## +extraFlags: [] +## @param extraEnvVars Extra environment variables to add to MongoDB(®) pods +## E.g: +## extraEnvVars: +## - name: FOO +## value: BAR +## +extraEnvVars: [] +## @param extraEnvVarsCM Name of existing ConfigMap containing extra env vars +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) +## +extraEnvVarsSecret: "" +## @section MongoDB(®) statefulset parameters +## + +## @param annotations Additional labels to be added to the MongoDB(®) statefulset. Evaluated as a template +## +annotations: {} +## @param labels Annotations to be added to the MongoDB(®) statefulset. Evaluated as a template +## +labels: {} +## @param replicaCount Number of MongoDB(®) nodes +## When `mongodb.architecture=replicaset`, the number of replicas is taken in account +## When `mongodb.architecture=standalone`, the number of replicas can only be 0 or 1 (value higher then 1 will not be taken in account) +## +replicaCount: 2 +## @param updateStrategy.type Strategy to use to replace existing MongoDB(®) pods. When architecture=standalone and useStatefulSet=false, +## this parameter will be applied on a deployment object. In other case it will be applied on a statefulset object +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +## Example: +## updateStrategy: +## type: RollingUpdate +## rollingUpdate: +## maxSurge: 25% +## maxUnavailable: 25% +## +updateStrategy: + type: RollingUpdate +## @param podManagementPolicy Pod management policy for MongoDB(®) +## Should be initialized one by one when building the replicaset for the first time +## +podManagementPolicy: OrderedReady +## @param podAffinityPreset MongoDB(®) Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset MongoDB(®) Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft +## Node affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type MongoDB(®) Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key MongoDB(®) Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param nodeAffinityPreset.values MongoDB(®) Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] +## @param affinity MongoDB(®) Affinity for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param nodeSelector MongoDB(®) Node labels for pod assignment +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ +## +nodeSelector: {} +## @param tolerations MongoDB(®) Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## @param topologySpreadConstraints MongoDB(®) Spread Constraints for Pods +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## +topologySpreadConstraints: [] +## @param lifecycleHooks LifecycleHook for the MongoDB(®) container(s) to automate configuration before or after startup +## +lifecycleHooks: {} +## @param terminationGracePeriodSeconds MongoDB(®) Termination Grace Period +## +terminationGracePeriodSeconds: "" +## @param podLabels MongoDB(®) pod labels +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations MongoDB(®) Pod annotations +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param priorityClassName Name of the existing priority class to be used by MongoDB(®) pod(s) +## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +priorityClassName: "" +## @param runtimeClassName Name of the runtime class to be used by MongoDB(®) pod(s) +## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ +## +runtimeClassName: "" +## MongoDB(®) pods' Security Context. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enable MongoDB(®) pod(s)' Security Context +## @param podSecurityContext.fsGroupChangePolicy Set filesystem group change policy +## @param podSecurityContext.supplementalGroups Set filesystem extra groups +## @param podSecurityContext.fsGroup Group ID for the volumes of the MongoDB(®) pod(s) +## @param podSecurityContext.sysctls sysctl settings of the MongoDB(®) pod(s)' +## +podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] +## MongoDB(®) containers' Security Context (main and metrics container). +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## @param containerSecurityContext.enabled Enabled containers' Security Context +## @param containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container +## @param containerSecurityContext.runAsUser Set containers' Security Context runAsUser +## @param containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup +## @param containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot +## @param containerSecurityContext.privileged Set container's Security Context privileged +## @param containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem +## @param containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation +## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped +## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile +## +containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" +## MongoDB(®) containers' resource requests and limits. +## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ +## We usually recommend not to specify default resources and to leave this as a conscious +## choice for the user. This also increases chances charts run on environments with little +## resources, such as Minikube. If you do want to specify resources, uncomment the following +## lines, adjust them as necessary, and remove the curly braces after 'resources:'. +## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). +## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 +## +resourcesPreset: "small" +## @param resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) +## Example: +## resources: +## requests: +## cpu: 2 +## memory: 512Mi +## limits: +## cpu: 3 +## memory: 1024Mi +## +resources: {} +## @param fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used +## +fips: + openssl: "" +## @param containerPorts.mongodb MongoDB(®) container port +## +containerPorts: + mongodb: 27017 +## MongoDB(®) pods' liveness probe. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 +## MongoDB(®) pods' readiness probe. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 +## Slow starting containers can be protected through startup probes +## Startup probes are available in Kubernetes version 1.16 and above +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + successThreshold: 1 + failureThreshold: 30 +## @param customLivenessProbe Override default liveness probe for MongoDB(®) containers +## Ignored when livenessProbe.enabled=true +## +customLivenessProbe: {} +## @param customReadinessProbe Override default readiness probe for MongoDB(®) containers +## Ignored when readinessProbe.enabled=true +## +customReadinessProbe: {} +## @param customStartupProbe Override default startup probe for MongoDB(®) containers +## Ignored when startupProbe.enabled=true +## +customStartupProbe: {} +## @param initContainers Add additional init containers for the hidden node pod(s) +## Example: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: [] +## @param sidecars Add additional sidecar containers for the MongoDB(®) pod(s) +## Example: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## This is an optional 'mongo-labeler' sidecar container that tracks replica-set for the primary mongodb pod +## and labels it dynamically with ' primary: "true" ' in order for an extra-deployed service to always expose +## and attach to the primary pod, this needs to be uncommented along with the suggested 'extraDeploy' example +## and the suggested rbac example for the pod to be allowed adding labels to mongo replica pods +## search 'mongo-labeler' through this file to find the sections that needs to be uncommented to make it work +## +## - name: mongo-labeler +## image: korenlev/k8s-mongo-labeler-sidecar +## imagePullPolicy: Always +## env: +## - name: LABEL_SELECTOR +## value: "app.kubernetes.io/component=mongodb,app.kubernetes.io/instance=mongodb,app.kubernetes.io/name=mongodb" +## - name: NAMESPACE +## value: "the-mongodb-namespace" +## - name: DEBUG +## value: "true" +## +sidecars: [] +## @param extraVolumeMounts Optionally specify extra list of additional volumeMounts for the MongoDB(®) container(s) +## Examples: +## extraVolumeMounts: +## - name: extras +## mountPath: /usr/share/extras +## readOnly: true +## +extraVolumeMounts: [] +## @param extraVolumes Optionally specify extra list of additional volumes to the MongoDB(®) statefulset +## extraVolumes: +## - name: extras +## emptyDir: {} +## +extraVolumes: [] +## MongoDB(®) Pod Disruption Budget configuration +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +## +pdb: + ## @param pdb.create Enable/disable a Pod Disruption Budget creation for MongoDB(®) pod(s) + ## + create: true + ## @param pdb.minAvailable Minimum number/percentage of MongoDB(®) pods that must still be available after the eviction + ## + minAvailable: "" + ## @param pdb.maxUnavailable Maximum number/percentage of MongoDB(®) pods that may be made unavailable after the eviction. Defaults to `1` if both `pdb.minAvailable` and `pdb.maxUnavailable` are empty. + ## + maxUnavailable: "" +## @section Traffic exposure parameters +## + +## Service parameters +## +service: + ## @param service.nameOverride MongoDB(®) service name + ## + nameOverride: "" + ## @param service.type Kubernetes Service type (only for standalone architecture) + ## + type: ClusterIP + ## @param service.portName MongoDB(®) service port name (only for standalone architecture) + ## + portName: mongodb + ## @param service.ports.mongodb MongoDB(®) service port. + ## + ports: + mongodb: 27017 + ## @param service.nodePorts.mongodb Port to bind to for NodePort and LoadBalancer service types (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + mongodb: "" + ## @param service.clusterIP MongoDB(®) service cluster IP (only for standalone architecture) + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.externalIPs Specify the externalIP value ClusterIP service type (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + ## @param service.loadBalancerIP loadBalancerIP for MongoDB(®) Service (only for standalone architecture) + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerClass loadBalancerClass for MongoDB(®) Service (only for standalone architecture) + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer (only for standalone architecture) + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + loadBalancerSourceRanges: [] + ## @param service.allocateLoadBalancerNodePorts Wheter to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## @param service.externalTrafficPolicy service external traffic policy (only for standalone architecture) + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param service.sessionAffinity Control where client requests go, to the same pod or round-robin. Allowed values: `ClientIP` or `None` + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity. Ignored if `service.sessionAffinity` is `None` + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## Headless service properties + ## + headless: + ## @param service.headless.annotations Annotations for the headless service. + ## + annotations: {} + ## @param service.publishNotReadyAddresses Indicates that any agent which deals with endpoints for this Service should disregard any indications of ready/not-ready + ## ref: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/ + ## + publishNotReadyAddresses: false +## External Access to MongoDB(®) nodes configuration +## +externalAccess: + ## @param externalAccess.enabled Enable Kubernetes external cluster access to MongoDB(®) nodes (only for replicaset architecture) + ## + enabled: false + ## External IPs auto-discovery configuration + ## An init container is used to auto-detect LB IPs or node ports by querying the K8s API + ## Note: RBAC might be required + ## + autoDiscovery: + ## @param externalAccess.autoDiscovery.enabled Enable using an init container to auto-detect external IPs by querying the K8s API + ## + enabled: false + ## Bitnami Kubectl image + ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ + ## @param externalAccess.autoDiscovery.image.registry [default: REGISTRY_NAME] Init container auto-discovery image registry + ## @param externalAccess.autoDiscovery.image.repository [default: REPOSITORY_NAME/kubectl] Init container auto-discovery image repository + ## @skip externalAccess.autoDiscovery.image.tag Init container auto-discovery image tag (immutable tags are recommended) + ## @param externalAccess.autoDiscovery.image.digest Init container auto-discovery image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param externalAccess.autoDiscovery.image.pullPolicy Init container auto-discovery image pull policy + ## @param externalAccess.autoDiscovery.image.pullSecrets Init container auto-discovery image pull secrets + ## + image: + registry: registry-1.docker.io + repository: bitnami/kubectl + tag: latest + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param externalAccess.autoDiscovery.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param externalAccess.autoDiscovery.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param externalAccess.autoDiscovery.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## Init container what mission is ensure public names can be resolved. + ## + dnsCheck: + ## Bitnami os-shell image + ## ref: https://hub.docker.com/r/bitnami/os-shell/tags/ + ## @param externalAccess.dnsCheck.image.registry [default: REGISTRY_NAME] Init container dns-check image registry + ## @param externalAccess.dnsCheck.image.repository [default: REPOSITORY_NAME/kubectl] Init container dns-check image repository + ## @skip externalAccess.dnsCheck.image.tag Init container dns-check image tag (immutable tags are recommended) + ## @param externalAccess.dnsCheck.image.digest Init container dns-check image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param externalAccess.dnsCheck.image.pullPolicy Init container dns-check image pull policy + ## @param externalAccess.dnsCheck.image.pullSecrets Init container dns-check image pull secrets + ## + image: + registry: registry-1.docker.io + repository: bitnami/os-shell + tag: latest + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param externalAccess.dnsCheck.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if externalAccess.autoDiscovery.resources is set (externalAccess.autoDiscovery.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param externalAccess.dnsCheck.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param externalAccess.dnsCheck.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## Parameters to configure a set of Pods that connect to an existing MongoDB(®) deployment that lies outside of Kubernetes. + ## @param externalAccess.externalMaster.enabled Use external master for bootstrapping + ## @param externalAccess.externalMaster.host External master host to bootstrap from + ## @param externalAccess.externalMaster.port Port for MongoDB(®) service external master host + ## + externalMaster: + enabled: false + host: "" + port: 27017 + ## Parameters to configure K8s service(s) used to externally access MongoDB(®) + ## A new service per broker will be created + ## + service: + ## @param externalAccess.service.type Kubernetes Service type for external access. Allowed values: NodePort, LoadBalancer or ClusterIP + ## + type: LoadBalancer + ## @param externalAccess.service.portName MongoDB(®) port name used for external access when service type is LoadBalancer + ## + portName: "mongodb" + ## @param externalAccess.service.ports.mongodb MongoDB(®) port used for external access when service type is LoadBalancer + ## + ports: + mongodb: 27017 + ## @param externalAccess.service.loadBalancerIPs Array of load balancer IPs for MongoDB(®) nodes + ## Example: + ## loadBalancerIPs: + ## - X.X.X.X + ## - Y.Y.Y.Y + ## + loadBalancerIPs: [] + ## @param externalAccess.service.publicNames Array of public names. The size should be equal to the number of replicas. + ## + publicNames: [] + ## @param externalAccess.service.loadBalancerClass loadBalancerClass when service type is LoadBalancer + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param externalAccess.service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## Example: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param externalAccess.service.allocateLoadBalancerNodePorts Whether to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param externalAccess.service.externalTrafficPolicy MongoDB(®) service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param externalAccess.service.nodePorts Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort + ## Example: + ## nodePorts: + ## - 30001 + ## - 30002 + ## + nodePorts: [] + ## @param externalAccess.service.domain Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort + ## If not specified, the container will try to get the kubernetes node external IP + ## e.g: + ## domain: mydomain.com + ## + domain: "" + ## @param externalAccess.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param externalAccess.service.annotations Service annotations for external access. These annotations are common for all services created. + ## + annotations: {} + ## @param externalAccess.service.annotationsList Service annotations for eache external service. This value contains a list allowing different annotations per each external service. + ## Eg: + ## annotationsList: + ## - external-dns.alpha.kubernetes.io/hostname: mongodb-0.example.com + ## - external-dns.alpha.kubernetes.io/hostname: mongodb-1.example.com + ## + annotationsList: [] + ## @param externalAccess.service.sessionAffinity Control where client requests go, to the same pod or round-robin. Allowed values: `ClientIP` or `None` + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param externalAccess.service.sessionAffinityConfig Additional settings for the sessionAffinity. Ignored if `externalAccess.service.sessionAffinity` is `None` + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## External Access to MongoDB(®) Hidden nodes configuration + ## + hidden: + ## @param externalAccess.hidden.enabled Enable Kubernetes external cluster access to MongoDB(®) hidden nodes + ## + enabled: false + ## Parameters to configure K8s service(s) used to externally access MongoDB(®) + ## A new service per broker will be created + ## + service: + ## @param externalAccess.hidden.service.type Kubernetes Service type for external access. Allowed values: NodePort or LoadBalancer + ## + type: LoadBalancer + ## @param externalAccess.hidden.service.portName MongoDB(®) port name used for external access when service type is LoadBalancer + ## + portName: "mongodb" + ## @param externalAccess.hidden.service.ports.mongodb MongoDB(®) port used for external access when service type is LoadBalancer + ## + ports: + mongodb: 27017 + ## @param externalAccess.hidden.service.loadBalancerIPs Array of load balancer IPs for MongoDB(®) nodes + ## Example: + ## loadBalancerIPs: + ## - X.X.X.X + ## - Y.Y.Y.Y + ## + loadBalancerIPs: [] + ## @param externalAccess.hidden.service.loadBalancerClass loadBalancerClass when service type is LoadBalancer + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + loadBalancerClass: "" + ## @param externalAccess.hidden.service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## Example: + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param externalAccess.hidden.service.allocateLoadBalancerNodePorts Wheter to allocate node ports when service type is LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: true + ## @param externalAccess.hidden.service.externalTrafficPolicy MongoDB(®) service external traffic policy + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Local + ## @param externalAccess.hidden.service.nodePorts Array of node ports used to configure MongoDB(®) advertised hostname when service type is NodePort. Length must be the same as replicaCount + ## Example: + ## nodePorts: + ## - 30001 + ## - 30002 + ## + nodePorts: [] + ## @param externalAccess.hidden.service.domain Domain or external IP used to configure MongoDB(®) advertised hostname when service type is NodePort + ## If not specified, the container will try to get the kubernetes node external IP + ## e.g: + ## domain: mydomain.com + ## + domain: "" + ## @param externalAccess.hidden.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param externalAccess.hidden.service.annotations Service annotations for external access + ## + annotations: {} + ## @param externalAccess.hidden.service.sessionAffinity Control where client requests go, to the same pod or round-robin. Allowed values: `ClientIP` or `None` + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/ + ## + sessionAffinity: None + ## @param externalAccess.hidden.service.sessionAffinityConfig Additional settings for the sessionAffinity. Ignored if `externalAccess.hidden.service.sessionAffinity` is `None` + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} +## @section Password update job +## +passwordUpdateJob: + ## @param passwordUpdateJob.enabled Enable password update job + ## + enabled: false + ## @param passwordUpdateJob.backoffLimit set backoff limit of the job + ## + backoffLimit: 10 + ## @param passwordUpdateJob.command Override default container command on mysql Primary container(s) (useful when using custom images) + ## + command: [] + ## @param passwordUpdateJob.args Override default container args on mysql Primary container(s) (useful when using custom images) + ## + args: [] + ## @param passwordUpdateJob.extraCommands Extra commands to pass to the generation job + ## + extraCommands: "" + ## @param passwordUpdateJob.previousPasswords.rootPassword Previous root password (set if the password secret was already changed) + ## @param passwordUpdateJob.previousPasswords.existingSecret Name of a secret containing the previous passwords (set if the password secret was already changed) + previousPasswords: + rootPassword: "" + existingSecret: "" + ## Configure Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param passwordUpdateJob.containerSecurityContext.enabled Enabled containers' Security Context + ## @param passwordUpdateJob.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param passwordUpdateJob.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param passwordUpdateJob.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param passwordUpdateJob.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param passwordUpdateJob.containerSecurityContext.privileged Set container's Security Context privileged + ## @param passwordUpdateJob.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param passwordUpdateJob.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param passwordUpdateJob.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param passwordUpdateJob.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## Configure Pods Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param passwordUpdateJob.podSecurityContext.enabled Enabled credential init job pods' Security Context + ## @param passwordUpdateJob.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param passwordUpdateJob.podSecurityContext.sysctls Set kernel settings using the sysctl interface + ## @param passwordUpdateJob.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param passwordUpdateJob.podSecurityContext.fsGroup Set credential init job pod's Security Context fsGroup + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + sysctls: [] + supplementalGroups: [] + fsGroup: 1001 + ## @param passwordUpdateJob.extraEnvVars Array containing extra env vars to configure the credential init job + ## For example: + ## extraEnvVars: + ## - name: GF_DEFAULT_INSTANCE_NAME + ## value: my-instance + ## + extraEnvVars: [] + ## @param passwordUpdateJob.extraEnvVarsCM ConfigMap containing extra env vars to configure the credential init job + ## + extraEnvVarsCM: "" + ## @param passwordUpdateJob.extraEnvVarsSecret Secret containing extra env vars to configure the credential init job (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param passwordUpdateJob.extraVolumes Optionally specify extra list of additional volumes for the credential init job + ## + extraVolumes: [] + ## @param passwordUpdateJob.extraVolumeMounts Array of extra volume mounts to be added to the jwt Container (evaluated as template). Normally used with `extraVolumes`. + ## + extraVolumeMounts: [] + ## @param passwordUpdateJob.initContainers Add additional init containers for the mysql Primary pod(s) + ## + initContainers: [] + ## Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## @param passwordUpdateJob.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if passwordUpdateJob.resources is set (passwordUpdateJob.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param passwordUpdateJob.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param passwordUpdateJob.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## @param passwordUpdateJob.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param passwordUpdateJob.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param passwordUpdateJob.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param passwordUpdateJob.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param passwordUpdateJob.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param passwordUpdateJob.annotations [object] Add annotations to the job + ## + annotations: {} + ## @param passwordUpdateJob.podLabels Additional pod labels + ## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param passwordUpdateJob.podAnnotations Additional pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} +## @section Network policy parameters +## + +## Network Policies +## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Specifies whether a NetworkPolicy should be created + ## + enabled: true + ## @param networkPolicy.allowExternal Don't require server label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## server label will have network access to the ports server is listening + ## on. When true, server will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations. + ## + allowExternalEgress: true + ## @param networkPolicy.addExternalClientAccess Allow access from pods with client label set to "true". Ignored if `networkPolicy.allowExternal` is true. + ## + addExternalClientAccess: true + ## @param networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraIngress: + ## - ports: + ## - port: 1234 + ## from: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + extraIngress: [] + ## @param networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy + ## e.g: + ## extraEgress: + ## - ports: + ## - port: 1234 + ## to: + ## - podSelector: + ## - matchLabels: + ## - role: frontend + ## - podSelector: + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + extraEgress: [] + ## @param networkPolicy.ingressPodMatchLabels [object] Labels to match to allow traffic from other pods. Ignored if `networkPolicy.allowExternal` is true. + ## e.g: + ## ingressPodMatchLabels: + ## my-client: "true" + # + ingressPodMatchLabels: {} + ## @param networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## @param networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces. Ignored if `networkPolicy.allowExternal` is true. + ## + ingressNSMatchLabels: {} + ingressNSPodMatchLabels: {} +persistence: + ## @param persistence.enabled Enable MongoDB(®) data persistence using PVC + ## + enabled: true + ## @param persistence.name Name of the PVC and mounted volume + ## + name: "datadir" + ## @param persistence.medium Provide a medium for `emptyDir` volumes. + ## Requires persistence.enabled: false + ## + medium: "" + ## @param persistence.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## Requires persistence.enabled: true + ## If defined, PVC must be created manually before volume will be bound + ## Ignored when mongodb.architecture=replicaset + ## + existingClaim: "" + ## @param persistence.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param persistence.storageClass PVC Storage Class for MongoDB(®) data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + storageClass: "" + ## @param persistence.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size PVC Storage Request for MongoDB(®) data volume + ## + size: 8Gi + ## @param persistence.annotations PVC annotations + ## + annotations: {} + ## @param persistence.labels PVC labels + ## + labels: {} + ## @param persistence.mountPath Path to mount the volume at + ## MongoDB(®) images. + ## + mountPath: /bitnami/mongodb + ## @param persistence.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param persistence.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param persistence.volumeClaimTemplates.requests Custom PVC requests attributes + ## Sometime cloud providers use additional requests attributes to provision custom storage instance + ## See https://cloud.ibm.com/docs/containers?topic=containers-file_storage#file_dynamic_statefulset + ## + requests: {} + ## @param persistence.volumeClaimTemplates.dataSource Add dataSource to the VolumeClaimTemplate + ## + dataSource: {} +## Persistent Volume Claim Retention Policy +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention +## +persistentVolumeClaimRetentionPolicy: + ## @param persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for MongoDB(®) Statefulset + ## + enabled: false + ## @param persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + ## + whenScaled: Retain + ## @param persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + ## + whenDeleted: Retain +## @section Backup parameters +## This section implements a trivial logical dump cronjob of the database. +## This only comes with the consistency guarantees of the dump program. +## This is not a snapshot based roll forward/backward recovery backup. +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ +## +backup: + ## @param backup.enabled Enable the logical dump of the database "regularly" + ## + enabled: false + ## Fine tuning cronjob's config + ## + cronjob: + ## @param backup.cronjob.schedule Set the cronjob parameter schedule + ## + schedule: "@daily" + ## @param backup.cronjob.timeZone Set the cronjob parameter timeZone + ## + timeZone: "" + ## @param backup.cronjob.concurrencyPolicy Set the cronjob parameter concurrencyPolicy + ## + concurrencyPolicy: Allow + ## @param backup.cronjob.failedJobsHistoryLimit Set the cronjob parameter failedJobsHistoryLimit + ## + failedJobsHistoryLimit: 1 + ## @param backup.cronjob.successfulJobsHistoryLimit Set the cronjob parameter successfulJobsHistoryLimit + ## + successfulJobsHistoryLimit: 3 + ## @param backup.cronjob.startingDeadlineSeconds Set the cronjob parameter startingDeadlineSeconds + ## + startingDeadlineSeconds: "" + ## @param backup.cronjob.ttlSecondsAfterFinished Set the cronjob parameter ttlSecondsAfterFinished + ## + ttlSecondsAfterFinished: "" + ## @param backup.cronjob.restartPolicy Set the cronjob parameter restartPolicy + ## + restartPolicy: OnFailure + ## @param backup.cronjob.backoffLimit Set the cronjob parameter backoffLimit + backoffLimit: 6 + ## @param backup.cronjob.serviceAccount.name Set the cronjob parameter serviceAccountName. If you change from the default values make sure that the SA already exists. + serviceAccount: + name: "default" + ## backup container's Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param backup.cronjob.containerSecurityContext.enabled Enabled containers' Security Context + ## @param backup.cronjob.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param backup.cronjob.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param backup.cronjob.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param backup.cronjob.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param backup.cronjob.containerSecurityContext.privileged Set container's Security Context privileged + ## @param backup.cronjob.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param backup.cronjob.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param backup.cronjob.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param backup.cronjob.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## backup container's resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param backup.cronjob.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "none" + ## @param backup.cronjob.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param backup.cronjob.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## @param backup.cronjob.command Set backup container's command to run + ## + command: [] + ## @param backup.cronjob.labels Set the cronjob labels + ## + labels: {} + ## @param backup.cronjob.annotations Set the cronjob annotations + ## + annotations: {} + ## Backup container's + ## + storage: + ## @param backup.cronjob.storage.existingClaim Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) + ## If defined, PVC must be created manually before volume will be bound + ## + existingClaim: "" + ## @param backup.cronjob.storage.resourcePolicy Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted + ## + resourcePolicy: "" + ## @param backup.cronjob.storage.storageClass PVC Storage Class for the backup data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + storageClass: "" + ## @param backup.cronjob.storage.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param backup.cronjob.storage.size PVC Storage Request for the backup data volume + ## + size: 8Gi + ## @param backup.cronjob.storage.annotations PVC annotations + ## + annotations: {} + ## @param backup.cronjob.storage.mountPath Path to mount the volume at + ## + mountPath: /backup/mongodb + ## @param backup.cronjob.storage.subPath Subdirectory of the volume to mount at + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param backup.cronjob.storage.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} +## @section RBAC parameters +## + +## ServiceAccount +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable creation of ServiceAccount for MongoDB(®) pods + ## + create: true + ## @param serviceAccount.name Name of the created serviceAccount + ## If not set and create is true, a name is generated using the mongodb.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional Service Account annotations + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created + ## Can be set to false if pods using this serviceAccount do not need to use K8s API + ## + automountServiceAccountToken: false +## Role Based Access +## ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## @param rbac.create Whether to create & use RBAC resources or not + ## binding MongoDB(®) ServiceAccount to a role + ## that allows MongoDB(®) pods querying the K8s API + ## this needs to be set to 'true' to enable the mongo-labeler sidecar primary mongodb discovery + ## + create: false + ## @param rbac.rules Custom rules to create following the role specification + ## The example below needs to be uncommented to use the 'mongo-labeler' sidecar for dynamic discovery of the primary mongodb pod: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## - watch + ## - update + ## + rules: [] +## PodSecurityPolicy configuration +## Be sure to also set rbac.create to true, otherwise Role and RoleBinding won't be created. +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + ## @param podSecurityPolicy.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later + ## + create: false + ## @param podSecurityPolicy.allowPrivilegeEscalation Enable privilege escalation + ## Either use predefined policy with some adjustments or use `podSecurityPolicy.spec` + ## + allowPrivilegeEscalation: false + ## @param podSecurityPolicy.privileged Allow privileged + ## + privileged: false + ## @param podSecurityPolicy.spec Specify the full spec to use for Pod Security Policy + ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## Defining a spec ignores the above values. + ## + spec: {} + ## Example: + ## allowPrivilegeEscalation: false + ## fsGroup: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## hostIPC: false + ## hostNetwork: false + ## hostPID: false + ## privileged: false + ## readOnlyRootFilesystem: true + ## requiredDropCapabilities: + ## - ALL + ## runAsUser: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## seLinux: + ## rule: 'RunAsAny' + ## supplementalGroups: + ## rule: 'MustRunAs' + ## ranges: + ## - min: 1001 + ## max: 1001 + ## volumes: + ## - 'configMap' + ## - 'secret' + ## - 'emptyDir' + ## - 'persistentVolumeClaim' + ## +## @section Volume Permissions parameters +## +## Init Container parameters +## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component +## values from the securityContext section of the component +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + enabled: false + ## @param volumePermissions.image.registry [default: REGISTRY_NAME] Init container volume-permissions image registry + ## @param volumePermissions.image.repository [default: REPOSITORY_NAME/os-shell] Init container volume-permissions image repository + ## @skip volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.digest Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: registry-1.docker.io + repository: bitnami/os-shell + tag: latest + digest: "" + ## Specify a imagePullPolicy + ## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param volumePermissions.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if volumePermissions.resources is set (volumePermissions.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param volumePermissions.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param volumePermissions.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## Init container Security Context + ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser + ## and not the below volumePermissions.securityContext.runAsUser + ## When runAsUser is set to special value "auto", init container will try to chwon the + ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). + ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with + ## podSecurityContext.enabled=false,containerSecurityContext.enabled=false and shmVolume.chmod.enabled=false + ## @param volumePermissions.securityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param volumePermissions.securityContext.runAsUser User ID for the volumePermissions container + ## + securityContext: + seLinuxOptions: {} + runAsUser: 0 +## @section Arbiter parameters +## +arbiter: + ## @param arbiter.enabled Enable deploying the arbiter + ## https://docs.mongodb.com/manual/tutorial/add-replica-set-arbiter/ + ## + enabled: true + ## @param arbiter.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param arbiter.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param arbiter.configuration Arbiter configuration file to be used + ## http://docs.mongodb.org/manual/reference/configuration-options/ + ## + configuration: "" + ## @param arbiter.existingConfigmap Name of existing ConfigMap with Arbiter configuration + ## NOTE: When it's set the arbiter.configuration parameter is ignored + ## + existingConfigmap: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param arbiter.command Override default container command (useful when using custom images) + ## @param arbiter.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## @param arbiter.extraFlags Arbiter additional command line flags + ## Example: + ## extraFlags: + ## - "--wiredTigerCacheSizeGB=2" + ## + extraFlags: [] + ## @param arbiter.extraEnvVars Extra environment variables to add to Arbiter pods + ## E.g: + ## extraEnvVars: + ## - name: FOO + ## value: BAR + ## + extraEnvVars: [] + ## @param arbiter.extraEnvVarsCM Name of existing ConfigMap containing extra env vars + ## + extraEnvVarsCM: "" + ## @param arbiter.extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param arbiter.annotations Additional labels to be added to the Arbiter statefulset + ## + annotations: {} + ## @param arbiter.labels Annotations to be added to the Arbiter statefulset + ## + labels: {} + ## @param arbiter.topologySpreadConstraints MongoDB(®) Spread Constraints for arbiter Pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + ## @param arbiter.lifecycleHooks LifecycleHook for the Arbiter container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param arbiter.terminationGracePeriodSeconds Arbiter Termination Grace Period + ## + terminationGracePeriodSeconds: "" + ## @param arbiter.updateStrategy.type Strategy that will be employed to update Pods in the StatefulSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param arbiter.podManagementPolicy Pod management policy for MongoDB(®) + ## Should be initialized one by one when building the replicaset for the first time + ## + podManagementPolicy: OrderedReady + ## @param arbiter.schedulerName Name of the scheduler (other than default) to dispatch pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param arbiter.podAffinityPreset Arbiter Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param arbiter.podAntiAffinityPreset Arbiter Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param arbiter.nodeAffinityPreset.type Arbiter Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param arbiter.nodeAffinityPreset.key Arbiter Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param arbiter.nodeAffinityPreset.values Arbiter Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param arbiter.affinity Arbiter Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: arbiter.podAffinityPreset, arbiter.podAntiAffinityPreset, and arbiter.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param arbiter.nodeSelector Arbiter Node labels for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param arbiter.tolerations Arbiter Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param arbiter.podLabels Arbiter pod labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param arbiter.podAnnotations Arbiter Pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param arbiter.priorityClassName Name of the existing priority class to be used by Arbiter pod(s) + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param arbiter.runtimeClassName Name of the runtime class to be used by Arbiter pod(s) + ## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ + ## + runtimeClassName: "" + ## MongoDB(®) Arbiter pods' Security Context. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param arbiter.podSecurityContext.enabled Enable Arbiter pod(s)' Security Context + ## @param arbiter.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param arbiter.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param arbiter.podSecurityContext.fsGroup Group ID for the volumes of the Arbiter pod(s) + ## @param arbiter.podSecurityContext.sysctls sysctl settings of the Arbiter pod(s)' + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] + ## MongoDB(®) Arbiter containers' Security Context (only main container). + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param arbiter.containerSecurityContext.enabled Enabled containers' Security Context + ## @param arbiter.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param arbiter.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param arbiter.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param arbiter.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param arbiter.containerSecurityContext.privileged Set container's Security Context privileged + ## @param arbiter.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param arbiter.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param arbiter.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param arbiter.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MongoDB(®) Arbiter containers' resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param arbiter.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if arbiter.resources is set (arbiter.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "small" + ## @param arbiter.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param arbiter.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## @param arbiter.containerPorts.mongodb MongoDB(®) arbiter container port + ## + containerPorts: + mongodb: 27017 + ## MongoDB(®) Arbiter pods' liveness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.livenessProbe.enabled Enable livenessProbe + ## @param arbiter.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param arbiter.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param arbiter.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param arbiter.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param arbiter.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Arbiter pods' readiness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.readinessProbe.enabled Enable readinessProbe + ## @param arbiter.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param arbiter.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param arbiter.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param arbiter.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param arbiter.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Arbiter pods' startup probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param arbiter.startupProbe.enabled Enable startupProbe + ## @param arbiter.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param arbiter.startupProbe.periodSeconds Period seconds for startupProbe + ## @param arbiter.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param arbiter.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param arbiter.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param arbiter.customLivenessProbe Override default liveness probe for Arbiter containers + ## Ignored when arbiter.livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param arbiter.customReadinessProbe Override default readiness probe for Arbiter containers + ## Ignored when arbiter.readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param arbiter.customStartupProbe Override default startup probe for Arbiter containers + ## Ignored when arbiter.startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param arbiter.initContainers Add additional init containers for the Arbiter pod(s) + ## Example: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + initContainers: [] + ## @param arbiter.sidecars Add additional sidecar containers for the Arbiter pod(s) + ## Example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param arbiter.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the Arbiter container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## @param arbiter.extraVolumes Optionally specify extra list of additional volumes to the Arbiter statefulset + ## extraVolumes: + ## - name: extras + ## emptyDir: {} + ## + extraVolumes: [] + ## MongoDB(®) Arbiter Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param arbiter.pdb.create Enable/disable a Pod Disruption Budget creation for Arbiter pod(s) + ## + create: true + ## @param arbiter.pdb.minAvailable Minimum number/percentage of Arbiter pods that should remain scheduled + ## + minAvailable: "" + ## @param arbiter.pdb.maxUnavailable Maximum number/percentage of Arbiter pods that may be made unavailable. Defaults to `1` if both `arbiter.pdb.minAvailable` and `arbiter.pdb.maxUnavailable` are empty. + ## + maxUnavailable: "" + ## MongoDB(®) Arbiter service parameters + ## + service: + ## @param arbiter.service.nameOverride The arbiter service name + ## + nameOverride: "" + ## @param arbiter.service.ports.mongodb MongoDB(®) service port + ## + ports: + mongodb: 27017 + ## @param arbiter.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param arbiter.service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## Headless service properties + ## + headless: + ## @param arbiter.service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## @section Hidden Node parameters +## +hidden: + ## @param hidden.enabled Enable deploying the hidden nodes + ## https://docs.mongodb.com/manual/tutorial/configure-a-hidden-replica-set-member/ + ## + enabled: false + ## @param hidden.automountServiceAccountToken Mount Service Account token in pod + ## + automountServiceAccountToken: false + ## @param hidden.hostAliases Add deployment host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param hidden.configuration Hidden node configuration file to be used + ## http://docs.mongodb.org/manual/reference/configuration-options/ + ## + configuration: "" + ## @param hidden.existingConfigmap Name of existing ConfigMap with Hidden node configuration + ## NOTE: When it's set the hidden.configuration parameter is ignored + ## + existingConfigmap: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param hidden.command Override default container command (useful when using custom images) + ## @param hidden.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## @param hidden.extraFlags Hidden node additional command line flags + ## Example: + ## extraFlags: + ## - "--wiredTigerCacheSizeGB=2" + ## + extraFlags: [] + ## @param hidden.extraEnvVars Extra environment variables to add to Hidden node pods + ## E.g: + ## extraEnvVars: + ## - name: FOO + ## value: BAR + ## + extraEnvVars: [] + ## @param hidden.extraEnvVarsCM Name of existing ConfigMap containing extra env vars + ## + extraEnvVarsCM: "" + ## @param hidden.extraEnvVarsSecret Name of existing Secret containing extra env vars (in case of sensitive data) + ## + extraEnvVarsSecret: "" + ## @param hidden.annotations Additional labels to be added to thehidden node statefulset + ## + annotations: {} + ## @param hidden.labels Annotations to be added to the hidden node statefulset + ## + labels: {} + ## @param hidden.topologySpreadConstraints MongoDB(®) Spread Constraints for hidden Pods + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + ## @param hidden.lifecycleHooks LifecycleHook for the Hidden container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## @param hidden.replicaCount Number of hidden nodes (only when `architecture=replicaset`) + ## Ignored when mongodb.architecture=standalone + ## + replicaCount: 1 + ## @param hidden.terminationGracePeriodSeconds Hidden Termination Grace Period + ## + terminationGracePeriodSeconds: "" + ## @param hidden.updateStrategy.type Strategy that will be employed to update Pods in the StatefulSet + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## updateStrategy: + ## type: RollingUpdate + ## rollingUpdate: + ## maxSurge: 25% + ## maxUnavailable: 25% + ## + updateStrategy: + type: RollingUpdate + ## @param hidden.podManagementPolicy Pod management policy for hidden node + ## + podManagementPolicy: OrderedReady + ## @param hidden.schedulerName Name of the scheduler (other than default) to dispatch pods + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param hidden.podAffinityPreset Hidden node Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param hidden.podAntiAffinityPreset Hidden node Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## Node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## Allowed values: soft, hard + ## + nodeAffinityPreset: + ## @param hidden.nodeAffinityPreset.type Hidden Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param hidden.nodeAffinityPreset.key Hidden Node label key to match Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param hidden.nodeAffinityPreset.values Hidden Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param hidden.affinity Hidden node Affinity for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param hidden.nodeSelector Hidden node Node labels for pod assignment + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + ## @param hidden.tolerations Hidden node Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param hidden.podLabels Hidden node pod labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + ## + podLabels: {} + ## @param hidden.podAnnotations Hidden node Pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: {} + ## @param hidden.priorityClassName Name of the existing priority class to be used by hidden node pod(s) + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + ## + priorityClassName: "" + ## @param hidden.runtimeClassName Name of the runtime class to be used by hidden node pod(s) + ## ref: https://kubernetes.io/docs/concepts/containers/runtime-class/ + ## + runtimeClassName: "" + ## MongoDB(®) Hidden pods' Security Context. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod + ## @param hidden.podSecurityContext.enabled Enable Hidden pod(s)' Security Context + ## @param hidden.podSecurityContext.fsGroupChangePolicy Set filesystem group change policy + ## @param hidden.podSecurityContext.supplementalGroups Set filesystem extra groups + ## @param hidden.podSecurityContext.fsGroup Group ID for the volumes of the Hidden pod(s) + ## @param hidden.podSecurityContext.sysctls sysctl settings of the Hidden pod(s)' + ## + podSecurityContext: + enabled: true + fsGroupChangePolicy: Always + supplementalGroups: [] + fsGroup: 1001 + ## sysctl settings + ## Example: + ## sysctls: + ## - name: net.core.somaxconn + ## value: "10000" + ## + sysctls: [] + ## MongoDB(®) Hidden containers' Security Context (only main container). + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param hidden.containerSecurityContext.enabled Enabled containers' Security Context + ## @param hidden.containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container + ## @param hidden.containerSecurityContext.runAsUser Set containers' Security Context runAsUser + ## @param hidden.containerSecurityContext.runAsGroup Set containers' Security Context runAsGroup + ## @param hidden.containerSecurityContext.runAsNonRoot Set container's Security Context runAsNonRoot + ## @param hidden.containerSecurityContext.privileged Set container's Security Context privileged + ## @param hidden.containerSecurityContext.readOnlyRootFilesystem Set container's Security Context readOnlyRootFilesystem + ## @param hidden.containerSecurityContext.allowPrivilegeEscalation Set container's Security Context allowPrivilegeEscalation + ## @param hidden.containerSecurityContext.capabilities.drop List of capabilities to be dropped + ## @param hidden.containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile + ## + containerSecurityContext: + enabled: true + seLinuxOptions: {} + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + privileged: false + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" + ## MongoDB(®) Hidden containers' resource requests and limits. + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param hidden.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if hidden.resources is set (hidden.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "micro" + ## @param hidden.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param hidden.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + ## @param hidden.containerPorts.mongodb MongoDB(®) hidden container port + ## + containerPorts: + mongodb: 27017 + ## MongoDB(®) Hidden pods' liveness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param hidden.livenessProbe.enabled Enable livenessProbe + ## @param hidden.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param hidden.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param hidden.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param hidden.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param hidden.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## MongoDB(®) Hidden pods' readiness probe. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes + ## @param hidden.readinessProbe.enabled Enable readinessProbe + ## @param hidden.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param hidden.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param hidden.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param hidden.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param hidden.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 10 + failureThreshold: 6 + successThreshold: 1 + ## Slow starting containers can be protected through startup probes + ## Startup probes are available in Kubernetes version 1.16 and above + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + ## @param hidden.startupProbe.enabled Enable startupProbe + ## @param hidden.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param hidden.startupProbe.periodSeconds Period seconds for startupProbe + ## @param hidden.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param hidden.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param hidden.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param hidden.customLivenessProbe Override default liveness probe for hidden node containers + ## Ignored when hidden.livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param hidden.customReadinessProbe Override default readiness probe for hidden node containers + ## Ignored when hidden.readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param hidden.customStartupProbe Override default startup probe for MongoDB(®) containers + ## Ignored when hidden.startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param hidden.initContainers Add init containers to the MongoDB(®) Hidden pods. + ## Example: + ## initContainers: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + initContainers: [] + ## @param hidden.sidecars Add additional sidecar containers for the hidden node pod(s) + ## Example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param hidden.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the hidden node container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## @param hidden.extraVolumes Optionally specify extra list of additional volumes to the hidden node statefulset + ## extraVolumes: + ## - name: extras + ## emptyDir: {} + ## + extraVolumes: [] + ## MongoDB(®) Hidden Pod Disruption Budget configuration + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: + ## @param hidden.pdb.create Enable/disable a Pod Disruption Budget creation for hidden node pod(s) + ## + create: true + ## @param hidden.pdb.minAvailable Minimum number/percentage of hidden node pods that should remain scheduled + ## + minAvailable: "" + ## @param hidden.pdb.maxUnavailable Maximum number/percentage of hidden node pods that may be made unavailable. Defaults to `1` if both `hidden.pdb.minAvailable` and `hidden.pdb.maxUnavailable` are empty. + ## + maxUnavailable: "" + ## Enable persistence using Persistent Volume Claims + ## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ + ## + persistence: + ## @param hidden.persistence.enabled Enable hidden node data persistence using PVC + ## + enabled: true + ## @param hidden.persistence.medium Provide a medium for `emptyDir` volumes. + ## Requires hidden.persistence.enabled: false + ## + medium: "" + ## @param hidden.persistence.storageClass PVC Storage Class for hidden node data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + storageClass: "" + ## @param hidden.persistence.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param hidden.persistence.size PVC Storage Request for hidden node data volume + ## + size: 8Gi + ## @param hidden.persistence.annotations PVC annotations + ## + annotations: {} + ## @param hidden.persistence.mountPath The path the volume will be mounted at, useful when using different MongoDB(®) images. + ## + mountPath: /bitnami/mongodb + ## @param hidden.persistence.subPath The subdirectory of the volume to mount to, useful in dev environments + ## and one PV for multiple services. + ## + subPath: "" + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param hidden.persistence.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param hidden.persistence.volumeClaimTemplates.requests Custom PVC requests attributes + ## Sometime cloud providers use additional requests attributes to provision custom storage instance + ## See https://cloud.ibm.com/docs/containers?topic=containers-file_storage#file_dynamic_statefulset + ## + requests: {} + ## @param hidden.persistence.volumeClaimTemplates.dataSource Set volumeClaimTemplate dataSource + ## + dataSource: {} + service: + ## @param hidden.service.nameOverride The hidden service name + ## + nameOverride: "" + ## @param hidden.service.portName MongoDB(®) service port name + ## + portName: "mongodb" + ## @param hidden.service.ports.mongodb MongoDB(®) service port + ## + ports: + mongodb: 27017 + ## @param hidden.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param hidden.service.annotations Provide any additional annotations that may be required + ## + annotations: {} + ## Headless service properties + ## + headless: + ## @param hidden.service.headless.annotations Annotations for the headless service. + ## + annotations: {} +## @section Metrics parameters +## +metrics: + ## @param metrics.enabled Enable using a sidecar Prometheus exporter + ## + enabled: false + ## Bitnami MongoDB(®) Promtheus Exporter image + ## ref: https://hub.docker.com/r/bitnami/mongodb-exporter/tags/ + ## @param metrics.image.registry [default: REGISTRY_NAME] MongoDB(®) Prometheus exporter image registry + ## @param metrics.image.repository [default: REPOSITORY_NAME/mongodb-exporter] MongoDB(®) Prometheus exporter image repository + ## @skip metrics.image.tag MongoDB(®) Prometheus exporter image tag (immutable tags are recommended) + ## @param metrics.image.digest MongoDB(®) image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag + ## @param metrics.image.pullPolicy MongoDB(®) Prometheus exporter image pull policy + ## @param metrics.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: registry-1.docker.io + repository: bitnami/mongodb-exporter + tag: latest + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.username String with username for the metrics exporter + ## If undefined the root user will be used for the metrics exporter + ## + username: "" + ## @param metrics.password String with password for the metrics exporter + ## If undefined but metrics.username is defined, a random password will be generated + ## + password: "" + ## @param metrics.compatibleMode Enables old style mongodb-exporter metrics + compatibleMode: true + collector: + ## @param metrics.collector.all Enable all collectors. Same as enabling all individual metrics + ## Enabling all metrics will cause significant CPU load on mongod + all: false + ## @param metrics.collector.diagnosticdata Boolean Enable collecting metrics from getDiagnosticData + diagnosticdata: true + ## @param metrics.collector.replicasetstatus Boolean Enable collecting metrics from replSetGetStatus + replicasetstatus: true + ## @param metrics.collector.dbstats Boolean Enable collecting metrics from dbStats + dbstats: false + ## @param metrics.collector.topmetrics Boolean Enable collecting metrics from top admin command + topmetrics: false + ## @param metrics.collector.indexstats Boolean Enable collecting metrics from $indexStats + indexstats: false + ## @param metrics.collector.collstats Boolean Enable collecting metrics from $collStats + collstats: false + ## @param metrics.collector.collstatsColls List of \.\ to get $collStats + collstatsColls: [] + ## @param metrics.collector.indexstatsColls List - List of \.\ to get $indexStats + indexstatsColls: [] + ## @param metrics.collector.collstatsLimit Number - Disable collstats, dbstats, topmetrics and indexstats collector if there are more than \ collections. 0=No limit + collstatsLimit: 0 + ## @param metrics.extraFlags String with extra flags to the metrics exporter + ## ref: https://github.com/percona/mongodb_exporter/blob/main/main.go + ## + extraFlags: "" + ## Command and args for running the container (set to default if not set). Use array form + ## @param metrics.command Override default container command (useful when using custom images) + ## @param metrics.args Override default container args (useful when using custom images) + ## + command: [] + args: [] + ## Metrics exporter container resource requests and limits + ## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production). + ## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15 + ## + resourcesPreset: "nano" + ## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) + ## Example: + ## resources: + ## requests: + ## cpu: 2 + ## memory: 512Mi + ## limits: + ## cpu: 3 + ## memory: 1024Mi + ## + resources: {} + ## @param metrics.fips.openssl Configure OpenSSL FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## @param metrics.fips.golang Configure Golang FIPS mode: '', 'restricted', 'relaxed', 'off'. If empty (""), 'global.defaultFips' would be used + ## + fips: + openssl: "" + golang: relaxed + ## @param metrics.containerPort Port of the Prometheus metrics container + ## + containerPort: 9216 + ## Prometheus Exporter service configuration + ## + service: + ## @param metrics.service.annotations [object] Annotations for Prometheus Exporter pods. Evaluated as a template. + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.ports.metrics }}" + prometheus.io/path: "/metrics" + ## @param metrics.service.type Type of the Prometheus metrics service + ## + type: ClusterIP + ## @param metrics.service.ports.metrics Port of the Prometheus metrics service + ## + ports: + metrics: 9216 + ## @param metrics.service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## Metrics exporter liveness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param metrics.livenessProbe.enabled Enable livenessProbe + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 15 + periodSeconds: 5 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + ## Metrics exporter readiness probe + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## @param metrics.readinessProbe.enabled Enable readinessProbe + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + ## Slow starting containers can be protected through startup probes + ## Startup probes are available in Kubernetes version 1.16 and above + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes + ## @param metrics.startupProbe.enabled Enable startupProbe + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 30 + ## @param metrics.customLivenessProbe Override default liveness probe for MongoDB(®) containers + ## Ignored when livenessProbe.enabled=true + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Override default readiness probe for MongoDB(®) containers + ## Ignored when readinessProbe.enabled=true + ## + customReadinessProbe: {} + ## @param metrics.customStartupProbe Override default startup probe for MongoDB(®) containers + ## Ignored when startupProbe.enabled=true + ## + customStartupProbe: {} + ## @param metrics.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the metrics container(s) + ## Examples: + ## extraVolumeMounts: + ## - name: extras + ## mountPath: /usr/share/extras + ## readOnly: true + ## + extraVolumeMounts: [] + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using Prometheus Operator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace which Prometheus is running in + ## + namespace: "" + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped + ## + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout Specify the timeout after which the scrape is ended + ## e.g: + ## scrapeTimeout: 30s + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping. + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricsRelabelConfigs to apply to samples before ingestion. + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.labels Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + labels: {} + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/main/bitnami/prometheus-operator#prometheus-configuration + ## + selector: {} + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## Custom PrometheusRule to be defined + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Set this to true to create prometheusRules for Prometheus operator + ## + enabled: false + ## @param metrics.prometheusRule.additionalLabels Additional labels that can be used so prometheusRules will be discovered by Prometheus + ## + additionalLabels: {} + ## @param metrics.prometheusRule.namespace Namespace where prometheusRules resource should be created + ## + namespace: "" + ## @param metrics.prometheusRule.rules Rules to be created, check values for an example + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#rulegroup + ## https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ + ## + ## This is an example of a rule, you should add the below code block under the "rules" param, removing the brackets + ## rules: + ## - alert: HighRequestLatency + ## expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 + ## for: 10m + ## labels: + ## severity: page + ## annotations: + ## summary: High request latency + ## + rules: [] diff --git a/utils/assets/charts/nats/.helmignore b/utils/assets/charts/nats/.helmignore new file mode 100644 index 0000000..240dfde --- /dev/null +++ b/utils/assets/charts/nats/.helmignore @@ -0,0 +1,26 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +# template tests +/test diff --git a/utils/assets/charts/nats/Chart.yaml b/utils/assets/charts/nats/Chart.yaml new file mode 100644 index 0000000..400ad07 --- /dev/null +++ b/utils/assets/charts/nats/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +appVersion: 2.10.22 +description: A Helm chart for the NATS.io High Speed Cloud Native Distributed Communications + Technology. +home: http://github.com/nats-io/k8s +icon: https://nats.io/img/nats-icon-color.png +keywords: +- nats +- messaging +- cncf +maintainers: +- email: info@nats.io + name: The NATS Authors + url: https://github.com/nats-io +name: nats +version: 1.2.6 diff --git a/utils/assets/charts/nats/README.md b/utils/assets/charts/nats/README.md new file mode 100644 index 0000000..0916999 --- /dev/null +++ b/utils/assets/charts/nats/README.md @@ -0,0 +1,329 @@ +# NATS Server + +--- + +[NATS](https://nats.io) is a simple, secure and performant communications system for digital systems, services and devices. +NATS is part of the Cloud Native Computing Foundation ([CNCF](https://cncf.io)). +NATS has over [30 client language implementations](https://nats.io/download/), and its server can run on-premise, in the cloud, at the edge, and even on a Raspberry Pi. +NATS can secure and simplify design and operation of modern distributed systems. + +```shell +helm repo add nats https://nats-io.github.io/k8s/helm/charts/ +helm upgrade --install nats nats/nats +``` + +## Upgrade Nodes + +- **Upgrading from 0.x**: The `values.yaml` schema changed significantly from 0.x to 1.x. Read [UPGRADING.md](UPGRADING.md) for instructions on upgrading a 0.x release to 1.x. + +## Values + +There are a handful of explicitly defined options which are documented with comments in the [values.yaml](values.yaml) file. + +Everything in the NATS Config or Kubernetes Resources can be overridden by `merge` and `patch`, which is supported for the following values: + +| key | type | enabled by default | +|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------| +| `config` | [NATS Config](https://docs.nats.io/running-a-nats-service/configuration) | yes | +| `config.cluster` | [NATS Cluster](https://docs.nats.io/running-a-nats-service/configuration/clustering/cluster_config) | no | +| `config.cluster.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.jetstream` | [NATS JetStream](https://docs.nats.io/running-a-nats-service/configuration#jetstream) | no | +| `config.jetstream.fileStore.pvc` | [k8s PVC](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core) | yes, when `config.jetstream` is enabled | +| `config.nats.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.leafnodes` | [NATS LeafNodes](https://docs.nats.io/running-a-nats-service/configuration/leafnodes/leafnode_conf) | no | +| `config.leafnodes.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.websocket` | [NATS WebSocket](https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf) | no | +| `config.websocket.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.websocket.ingress` | [k8s Ingress](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#ingress-v1-networking-k8s-io) | no | +| `config.mqtt` | [NATS MQTT](https://docs.nats.io/running-a-nats-service/configuration/mqtt/mqtt_config) | no | +| `config.mqtt.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.gateway` | [NATS Gateway](https://docs.nats.io/running-a-nats-service/configuration/gateways/gateway#gateway-configuration-block) | no | +| `config.gateway.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.resolver` | [NATS Resolver](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/jwt/resolver) | no | +| `config.resolver.pvc` | [k8s PVC](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core) | yes, when `config.resolver` is enabled | +| `container` | nats [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes | +| `reloader` | config reloader [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes | +| `promExporter` | prometheus exporter [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | no | +| `promExporter.podMonitor` | [prometheus PodMonitor](https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitor) | no | +| `service` | [k8s Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core) | yes | +| `statefulSet` | [k8s StatefulSet](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#statefulset-v1-apps) | yes | +| `podTemplate` | [k8s PodTemplate](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core) | yes | +| `headlessService` | [k8s Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core) | yes | +| `configMap` | [k8s ConfigMap](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#configmap-v1-core) | yes | +| `natsBox.contexts.default` | [NATS Context](https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts) | yes | +| `natsBox.contexts.[name]` | [NATS Context](https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts) | no | +| `natsBox.container` | nats-box [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes | +| `natsBox.deployment` | [k8s Deployment](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#deployment-v1-apps) | yes | +| `natsBox.podTemplate` | [k8s PodTemplate](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core) | yes | +| `natsBox.contextsSecret` | [k8s Secret](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core) | yes | +| `natsBox.contentsSecret` | [k8s Secret](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core) | yes | + +### Merge + +Merging is performed using the Helm `merge` function. Example - add NATS accounts and container resources: + +```yaml +config: + merge: + accounts: + A: + users: + - {user: a, password: a} + B: + users: + - {user: b, password: b} +natsBox: + contexts: + a: + merge: {user: a, password: a} + b: + merge: {user: b, password: b} + defaultContextName: a +``` + +## Patch + +Patching is performed using [JSON Patch](https://jsonpatch.com/). Example - add additional route to end of route list: + +```yaml +config: + cluster: + enabled: true + patch: + - op: add + path: /routes/- + value: nats://demo.nats.io:6222 +``` + +## Common Configurations + +### JetStream Cluster on 3 separate hosts + +```yaml +config: + cluster: + enabled: true + replicas: 3 + jetstream: + enabled: true + fileStore: + pvc: + size: 10Gi + +podTemplate: + topologySpreadConstraints: + kubernetes.io/hostname: + maxSkew: 1 + whenUnsatisfiable: DoNotSchedule +``` + +### NATS Container Resources + +```yaml +container: + env: + # different from k8s units, suffix must be B, KiB, MiB, GiB, or TiB + # should be ~90% of memory limit + GOMEMLIMIT: 7GiB + merge: + # recommended limit is at least 2 CPU cores and 8Gi Memory for production JetStream clusters + resources: + requests: + cpu: "2" + memory: 8Gi + limits: + cpu: "2" + memory: 8Gi +``` + +### Specify Image Version + +```yaml +container: + image: + tag: x.y.z-alpine +``` + +### Operator Mode with NATS Resolver + +Run `nsc generate config --nats-resolver` and replace the `OPERATOR_JWT`, `SYS_ACCOUNT_ID`, and `SYS_ACCOUNT_JWT` with your values. +Make sure that you do not include the trailing `,` in the `SYS_ACCOUNT_JWT`. + +``` +config: + resolver: + enabled: true + merge: + type: full + interval: 2m + timeout: 1.9s + merge: + operator: OPERATOR_JWT + system_account: SYS_ACCOUNT_ID + resolver_preload: + SYS_ACCOUNT_ID: SYS_ACCOUNT_JWT +``` + + +## Accessing NATS + +The chart contains 2 services by default, `service` and `headlessService`. + +### `service` + +The `service` is intended to be accessed by NATS Clients. It is a `ClusterIP` service by default, however it can easily be changed to a different service type. + +The `nats`, `websocket`, `leafnodes`, and `mqtt` ports will be exposed through this service by default if they are enabled. + +Example: change this service type to a `LoadBalancer`: + +```yaml +service: + merge: + spec: + type: LoadBalancer +``` + +### `headlessService` + +The `headlessService` is used for NATS Servers in the Stateful Set to discover one another. It is primarily intended to be used for Cluster Route connections. + +### TLS Considerations + +The TLS Certificate used for Client Connections should have a SAN covering DNS Name that clients access the `service` at. + +The TLS Certificate used for Cluster Route Connections should have a SAN covering the DNS Name that routes access each other on the `headlessService` at. This is `*.` by default. + +## Advanced Features + +### Templating Values + +Anything in `values.yaml` can be templated: + +- maps matching the following syntax will be templated and parsed as YAML: + ```yaml + $tplYaml: | + yaml template + ``` +- maps matching the follow syntax will be templated, parsed as YAML, and spread into the parent map/slice + ```yaml + $tplYamlSpread: | + yaml template + ``` + +Example - change service name: + +```yaml +service: + name: + $tplYaml: >- + {{ include "nats.fullname" . }}-svc +``` + +### NATS Config Units and Variables + +NATS configuration extends JSON, and can represent Units and Variables. They must be wrapped in `<< >>` in order to template correctly. Example: + +```yaml +config: + merge: + authorization: + # variable + token: << $TOKEN >> + # units + max_payload: << 2MB >> +``` + +templates to the `nats.conf`: + +``` +{ + "authorization": { + "token": $TOKEN + }, + "max_payload": 2MB, + "port": 4222, + ... +} +``` + +### NATS Config Includes + +Any NATS Config key ending in `$include` will be replaced with an include directive. Included files should be in paths relative to `/etc/nats-config`. Multiple `$include` keys are supported by using a prefix, and will be sorted alphabetically. Example: + +```yaml +config: + merge: + 00$include: auth.conf + 01$include: params.conf +configMap: + merge: + data: + auth.conf: | + accounts: { + A: { + users: [ + {user: a, password: a} + ] + }, + B: { + users: [ + {user: b, password: b} + ] + }, + } + params.conf: | + max_payload: 2MB +``` + +templates to the `nats.conf`: + +``` +include auth.conf; +"port": 4222, +... +include params.conf; +``` + +### Extra Resources + +Enables adding additional arbitrary resources. Example - expose WebSocket via VirtualService in Istio: + +```yaml +config: + websocket: + enabled: true +extraResources: +- apiVersion: networking.istio.io/v1beta1 + kind: VirtualService + metadata: + namespace: + $tplYamlSpread: > + {{ include "nats.metadataNamespace" $ }} + name: + $tplYaml: > + {{ include "nats.fullname" $ | quote }} + labels: + $tplYaml: | + {{ include "nats.labels" $ }} + spec: + hosts: + - demo.nats.io + gateways: + - my-gateway + http: + - name: default + match: + - name: root + uri: + exact: / + route: + - destination: + host: + $tplYaml: > + {{ .Values.service.name | quote }} + port: + number: + $tplYaml: > + {{ .Values.config.websocket.port }} +``` diff --git a/utils/assets/charts/nats/UPGRADING.md b/utils/assets/charts/nats/UPGRADING.md new file mode 100644 index 0000000..9cc1779 --- /dev/null +++ b/utils/assets/charts/nats/UPGRADING.md @@ -0,0 +1,155 @@ +# Upgrading from 0.x to 1.x + +Instructions for upgrading an existing `nats` 0.x release to 1.x. + +## Rename Immutable Fields + +There are a number of immutable fields in the NATS Stateful Set and NATS Box deployment. All 1.x `values.yaml` files targeting an existing 0.x release will require some or all of these settings: + +```yaml +config: + # required if using JetStream file storage + jetstream: + # uncomment the next line if using JetStream file storage + # enabled: true + fileStore: + pvc: + name: + $tplYaml: >- + {{ include "nats.fullname" . }}-js-pvc + # set other PVC options here to make it match 0.x, refer to values.yaml for schema + + # required if using a full or cache resolver + resolver: + # uncomment the next line if using a full or cache resolver + # enabled: true + pvc: + name: nats-jwt-pvc + # set other PVC options here to make it match 0.x, refer to values.yaml for schema + +# required +statefulSet: + patch: + - op: remove + path: /spec/selector/matchLabels/app.kubernetes.io~1component + - $tplYamlSpread: |- + {{- if and + .Values.config.jetstream.enabled + .Values.config.jetstream.fileStore.enabled + .Values.config.jetstream.fileStore.pvc.enabled + .Values.config.resolver.enabled + .Values.config.resolver.pvc.enabled + }} + - op: move + from: /spec/volumeClaimTemplates/0 + path: /spec/volumeClaimTemplates/1 + {{- else}} + [] + {{- end }} + +# required +headlessService: + name: + $tplYaml: >- + {{ include "nats.fullname" . }} + +# required unless 0.x values explicitly set nats.serviceAccount.create=false +serviceAccount: + enabled: true + +# required to use new ClusterIP service for Clients accessing NATS +# if using TLS, this may require adding another SAN +service: + # uncomment the next line to disable the new ClusterIP service + # enabled: false + name: + $tplYaml: >- + {{ include "nats.fullname" . }}-svc + +# required if using NatsBox +natsBox: + deployment: + patch: + - op: replace + path: /spec/selector/matchLabels + value: + app: nats-box + - op: add + path: /spec/template/metadata/labels/app + value: nats-box +``` + +## Update NATS Config to new values.yaml schema + +Most values that control the NATS Config have changed and moved under the `config` key. Refer to the 1.x Chart's [values.yaml](values.yaml) for the complete schema. + +After migrating to the new values schema, ensure that changes you expect in the NATS Config files match by templating the old and new config files. + +Template your old 0.x Config Map, this example uses a file called `values-old.yaml`: + +```sh +helm template \ + --version "0.x" \ + -f values-old.yaml \ + -s templates/configmap.yaml \ + nats \ + nats/nats +``` + +Template your new 1.x Config Map, this example uses a file called `values.yaml`: + +```sh +helm template \ + --version "^1-beta" \ + -f values.yaml \ + -s templates/config-map.yaml \ + nats \ + nats/nats +``` + +## Update Kubernetes Resources to new values.yaml schema + +Most values that control Kubernetes Resources have been changed. Refer to the 1.x Chart's [values.yaml](values.yaml) for the complete schema. + +After migrating to the new values schema, ensure that changes you expect in resources match by templating the old and new resources. + +| Resource | 0.x Template File | 1.x Template File | +|-------------------------|---------------------------------|-------------------------------------------| +| Config Map | `templates/configmap.yaml` | `templates/config-map.yaml` | +| Stateful Set | `templates/statefulset.yaml` | `templates/stateful-set.yaml` | +| Headless Service | `templates/service.yaml` | `templates/headless-service.yaml` | +| ClusterIP Service | N/A | `templates/service.yaml` | +| Network Policy | `templates/networkpolicy.yaml` | N/A | +| Pod Disruption Budget | `templates/pdb.yaml` | `templates/pod-disruption-budget.yaml` | +| Service Account | `templates/rbac.yaml` | `templates/service-account.yaml` | +| Resource | `templates/` | `templates/` | +| Resource | `templates/` | `templates/` | +| Prometheus Monitor | `templates/serviceMonitor.yaml` | `templates/pod-monitor.yaml` | +| NatsBox Deployment | `templates/nats-box.yaml` | `templates/nats-box/deployment.yaml` | +| NatsBox Service Account | N/A | `templates/nats-box/service-account.yaml` | +| NatsBox Contents Secret | N/A | `templates/nats-box/contents-secret.yaml` | +| NatsBox Contexts Secret | N/A | `templates/nats-box/contexts-secret.yaml` | + +For example, to check that the Stateful Set matches: + +Template your old 0.x Stateful Set, this example uses a file called `values-old.yaml`: + +```sh +helm template \ + --version "0.x" \ + -f values-old.yaml \ + -s templates/statefulset.yaml \ + nats \ + nats/nats +``` + +Template your new 1.x Stateful Set, this example uses a file called `values.yaml`: + +```sh +helm template \ + --version "^1-beta" \ + -f values.yaml \ + -s templates/stateful-set.yaml \ + nats \ + nats/nats +``` diff --git a/utils/assets/charts/nats/files/config-map.yaml b/utils/assets/charts/nats/files/config-map.yaml new file mode 100644 index 0000000..89ee3c2 --- /dev/null +++ b/utils/assets/charts/nats/files/config-map.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.configMap.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +data: + nats.conf: | + {{- include "nats.formatConfig" .config | nindent 4 }} diff --git a/utils/assets/charts/nats/files/config/cluster.yaml b/utils/assets/charts/nats/files/config/cluster.yaml new file mode 100644 index 0000000..719cb8a --- /dev/null +++ b/utils/assets/charts/nats/files/config/cluster.yaml @@ -0,0 +1,32 @@ +{{- with .Values.config.cluster }} +name: {{ $.Values.statefulSet.name }} +port: {{ .port }} +no_advertise: true +routes: +{{- $proto := ternary "tls" "nats" .tls.enabled }} +{{- $auth := "" }} +{{- if and .routeURLs.user .routeURLs.password }} + {{- $auth = printf "%s:%s@" (urlquery .routeURLs.user) (urlquery .routeURLs.password) -}} +{{- end }} +{{- $domain := $.Values.headlessService.name }} +{{- if .routeURLs.useFQDN }} + {{- $domain = printf "%s.%s.svc.%s" $domain (include "nats.namespace" $) .routeURLs.k8sClusterDomain }} +{{- end }} +{{- $port := (int .port) }} +{{- range $i, $_ := until (int .replicas) }} +- {{ printf "%s://%s%s-%d.%s:%d" $proto $auth $.Values.statefulSet.name $i $domain $port }} +{{- end }} + +{{- if and .routeURLs.user .routeURLs.password }} +authorization: + user: {{ .routeURLs.user | quote }} + password: {{ .routeURLs.password | quote }} +{{- end }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/config.yaml b/utils/assets/charts/nats/files/config/config.yaml new file mode 100644 index 0000000..92fd96f --- /dev/null +++ b/utils/assets/charts/nats/files/config/config.yaml @@ -0,0 +1,114 @@ +{{- with .Values.config }} + +server_name: << $SERVER_NAME >> +lame_duck_grace_period: 10s +lame_duck_duration: 30s +pid_file: /var/run/nats/nats.pid + +######################################## +# NATS +######################################## +{{- with .nats }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} + +######################################## +# leafnodes +######################################## +{{- with .leafnodes }} +{{- if .enabled }} +leafnodes: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/leafnodes.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# websocket +######################################## +{{- with .websocket }} +{{- if .enabled }} +websocket: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/websocket.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# MQTT +######################################## +{{- with .mqtt }} +{{- if .enabled }} +mqtt: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/mqtt.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# cluster +######################################## +{{- with .cluster }} +{{- if .enabled }} +cluster: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/cluster.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# gateway +######################################## +{{- with .gateway }} +{{- if .enabled }} +gateway: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/gateway.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# monitor +######################################## +{{- with .monitor }} +{{- if .enabled }} +{{- if .tls.enabled }} +https_port: {{ .port }} +{{- else }} +http_port: {{ .port }} +{{- end }} +{{- end }} +{{- end }} + +######################################## +# profiling +######################################## +{{- with .profiling }} +{{- if .enabled }} +prof_port: {{ .port }} +{{- end }} +{{- end }} + +######################################## +# jetstream +######################################## +{{- with $.Values.config.jetstream -}} +{{- if .enabled }} +jetstream: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/jetstream.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# resolver +######################################## +{{- with $.Values.config.resolver -}} +{{- if .enabled }} +resolver: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/resolver.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +{{- end }} diff --git a/utils/assets/charts/nats/files/config/gateway.yaml b/utils/assets/charts/nats/files/config/gateway.yaml new file mode 100644 index 0000000..32d4ed9 --- /dev/null +++ b/utils/assets/charts/nats/files/config/gateway.yaml @@ -0,0 +1,11 @@ +{{- with .Values.config.gateway }} +name: {{ $.Values.statefulSet.name }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/jetstream.yaml b/utils/assets/charts/nats/files/config/jetstream.yaml new file mode 100644 index 0000000..17262f6 --- /dev/null +++ b/utils/assets/charts/nats/files/config/jetstream.yaml @@ -0,0 +1,23 @@ +{{- with .Values.config.jetstream }} +{{- with .memoryStore }} +{{- if .enabled }} +{{- with .maxSize }} +max_memory_store: << {{ . }} >> +{{- end }} +{{- else }} +max_memory_store: 0 +{{- end }} +{{- end }} +{{- with .fileStore }} +{{- if .enabled }} +store_dir: {{ .dir }} +{{- if .maxSize }} +max_file_store: << {{ .maxSize }} >> +{{- else if .pvc.enabled }} +max_file_store: << {{ .pvc.size }} >> +{{- end }} +{{- else }} +max_file_store: 0 +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/leafnodes.yaml b/utils/assets/charts/nats/files/config/leafnodes.yaml new file mode 100644 index 0000000..3a1d9a1 --- /dev/null +++ b/utils/assets/charts/nats/files/config/leafnodes.yaml @@ -0,0 +1,11 @@ +{{- with .Values.config.leafnodes }} +port: {{ .port }} +no_advertise: true + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/mqtt.yaml b/utils/assets/charts/nats/files/config/mqtt.yaml new file mode 100644 index 0000000..e25d8a3 --- /dev/null +++ b/utils/assets/charts/nats/files/config/mqtt.yaml @@ -0,0 +1,10 @@ +{{- with .Values.config.mqtt }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/protocol.yaml b/utils/assets/charts/nats/files/config/protocol.yaml new file mode 100644 index 0000000..288c80d --- /dev/null +++ b/utils/assets/charts/nats/files/config/protocol.yaml @@ -0,0 +1,10 @@ +{{- with .protocol }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/resolver.yaml b/utils/assets/charts/nats/files/config/resolver.yaml new file mode 100644 index 0000000..a6761c4 --- /dev/null +++ b/utils/assets/charts/nats/files/config/resolver.yaml @@ -0,0 +1,3 @@ +{{- with .Values.config.resolver }} +dir: {{ .dir }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/tls.yaml b/utils/assets/charts/nats/files/config/tls.yaml new file mode 100644 index 0000000..26aee01 --- /dev/null +++ b/utils/assets/charts/nats/files/config/tls.yaml @@ -0,0 +1,16 @@ +# tls +{{- with .tls }} +{{- if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +cert_file: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }} +key_file: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }} +{{- end }} +{{- end }} + +# tlsCA +{{- with $.Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +{{- $dir := trimSuffix "/" .dir }} +ca_file: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/config/websocket.yaml b/utils/assets/charts/nats/files/config/websocket.yaml new file mode 100644 index 0000000..afcd178 --- /dev/null +++ b/utils/assets/charts/nats/files/config/websocket.yaml @@ -0,0 +1,12 @@ +{{- with .Values.config.websocket }} +port: {{ .port }} + +{{- if .tls.enabled }} +{{- with .tls }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- else }} +no_tls: true +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/headless-service.yaml b/utils/assets/charts/nats/files/headless-service.yaml new file mode 100644 index 0000000..da6552b --- /dev/null +++ b/utils/assets/charts/nats/files/headless-service.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Service +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.headlessService.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + {{- include "nats.selectorLabels" $ | nindent 4 }} + clusterIP: None + publishNotReadyAddresses: true + ports: + {{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }} + {{- $configProtocol := get $.Values.config $protocol }} + {{- if or (eq $protocol "nats") $configProtocol.enabled }} + {{- $tlsEnabled := false }} + {{- if hasKey $configProtocol "tls" }} + {{- $tlsEnabled = $configProtocol.tls.enabled }} + {{- end }} + {{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }} + - {{ dict "name" $protocol "port" $configProtocol.port "targetPort" $protocol "appProtocol" $appProtocol | toYaml | nindent 4 }} + {{- end }} + {{- end }} diff --git a/utils/assets/charts/nats/files/ingress.yaml b/utils/assets/charts/nats/files/ingress.yaml new file mode 100644 index 0000000..b59f0fa --- /dev/null +++ b/utils/assets/charts/nats/files/ingress.yaml @@ -0,0 +1,34 @@ +{{- with .Values.config.websocket.ingress }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + {{- with .className }} + ingressClassName: {{ . | quote }} + {{- end }} + rules: + {{- $path := .path }} + {{- $pathType := .pathType }} + {{- range .hosts }} + - host: {{ . | quote }} + http: + paths: + - path: {{ $path | quote }} + pathType: {{ $pathType | quote }} + backend: + service: + name: {{ $.Values.service.name }} + port: + name: websocket + {{- end }} + {{- if .tlsSecretName }} + tls: + - secretName: {{ .tlsSecretName | quote }} + hosts: + {{- toYaml .hosts | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/nats-box/contents-secret.yaml b/utils/assets/charts/nats/files/nats-box/contents-secret.yaml new file mode 100644 index 0000000..6e8fdb2 --- /dev/null +++ b/utils/assets/charts/nats/files/nats-box/contents-secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Secret +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.contentsSecret.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +type: Opaque +stringData: + {{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} + {{- range $secretKey, $secretVal := dict "creds" "creds" "nkey" "nk" }} + {{- $secret := get $ctxVal $secretKey }} + {{- if and $secret $secret.contents }} + "{{ $ctxKey }}.{{ $secretVal }}": {{ $secret.contents | quote }} + {{- end }} + {{- end }} + {{- end }} diff --git a/utils/assets/charts/nats/files/nats-box/contexts-secret/context.yaml b/utils/assets/charts/nats/files/nats-box/contexts-secret/context.yaml new file mode 100644 index 0000000..54480ea --- /dev/null +++ b/utils/assets/charts/nats/files/nats-box/contexts-secret/context.yaml @@ -0,0 +1,51 @@ +{{- $contextName := .contextName }} + +# url +{{- if .Values.service.enabled }} +url: nats://{{ .Values.service.name }} +{{- else }} +url: nats://{{ .Values.headlessService.name }} +{{- end }} + +{{- with .context }} + +# creds +{{- with .creds}} +{{- if .contents }} +creds: /etc/nats-contents/{{ $contextName }}.creds +{{- else if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +creds: {{ printf "%s/%s" $dir (.key | default "nats.creds") | quote }} +{{- end }} +{{- end }} + +# nkey +{{- with .nkey}} +{{- if .contents }} +nkey: /etc/nats-contents/{{ $contextName }}.nk +{{- else if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +nkey: {{ printf "%s/%s" $dir (.key | default "nats.nk") | quote }} +{{- end }} +{{- end }} + +# tls +{{- with .tls }} +{{- if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +cert: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }} +key: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }} +{{- end }} +{{- end }} + +# tlsCA +{{- if $.Values.config.nats.tls.enabled }} +{{- with $.Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +{{- $dir := trimSuffix "/" .dir }} +ca: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{- end }} diff --git a/utils/assets/charts/nats/files/nats-box/contexts-secret/contexts-secret.yaml b/utils/assets/charts/nats/files/nats-box/contexts-secret/contexts-secret.yaml new file mode 100644 index 0000000..0ce8d1d --- /dev/null +++ b/utils/assets/charts/nats/files/nats-box/contexts-secret/contexts-secret.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Secret +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.contextsSecret.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +type: Opaque +stringData: +{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} + "{{ $ctxKey }}.json": | + {{- include "toPrettyRawJson" (include "nats.loadMergePatch" (dict "file" "nats-box/contexts-secret/context.yaml" "merge" (.merge | default dict) "patch" (.patch | default list) "ctx" (merge (dict "contextName" $ctxKey "context" $ctxVal) $)) | fromYaml) | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/nats/files/nats-box/deployment/container.yaml b/utils/assets/charts/nats/files/nats-box/deployment/container.yaml new file mode 100644 index 0000000..aa1753b --- /dev/null +++ b/utils/assets/charts/nats/files/nats-box/deployment/container.yaml @@ -0,0 +1,46 @@ +name: nats-box +{{ include "nats.image" (merge (pick $.Values "global") .Values.natsBox.container.image) }} + +{{- with .Values.natsBox.container.env }} +env: +{{- include "nats.env" . }} +{{- end }} + +command: +- sh +- -ec +- | + work_dir="$(pwd)" + mkdir -p "$XDG_CONFIG_HOME/nats" + cd "$XDG_CONFIG_HOME/nats" + if ! [ -s context ]; then + ln -s /etc/nats-contexts context + fi + {{- if .Values.natsBox.defaultContextName }} + if ! [ -f context.txt ]; then + echo -n {{ .Values.natsBox.defaultContextName | quote }} > context.txt + fi + {{- end }} + cd "$work_dir" + exec /entrypoint.sh "$@" +- -- +args: +- sh +- -ec +- trap true INT TERM; sleep infinity & wait +volumeMounts: +# contexts secret +- name: contexts + mountPath: /etc/nats-contexts +# contents secret +{{- if .hasContentsSecret }} +- name: contents + mountPath: /etc/nats-contents +{{- end }} +# tlsCA +{{- include "nats.tlsCAVolumeMount" $ }} +# secrets +{{- range (include "natsBox.secretNames" $ | fromJson).secretNames }} +- name: {{ .name | quote }} + mountPath: {{ .dir | quote }} +{{- end }} diff --git a/utils/assets/charts/nats/files/nats-box/deployment/deployment.yaml b/utils/assets/charts/nats/files/nats-box/deployment/deployment.yaml new file mode 100644 index 0000000..bf39dd8 --- /dev/null +++ b/utils/assets/charts/nats/files/nats-box/deployment/deployment.yaml @@ -0,0 +1,16 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.deployment.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "natsBox.selectorLabels" $ | nindent 6 }} + replicas: 1 + template: + {{- with .Values.natsBox.podTemplate }} + {{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/pod-template.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} diff --git a/utils/assets/charts/nats/files/nats-box/deployment/pod-template.yaml b/utils/assets/charts/nats/files/nats-box/deployment/pod-template.yaml new file mode 100644 index 0000000..71056bf --- /dev/null +++ b/utils/assets/charts/nats/files/nats-box/deployment/pod-template.yaml @@ -0,0 +1,44 @@ +metadata: + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +spec: + containers: + {{- with .Values.natsBox.container }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/container.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + + # service discovery uses DNS; don't need service env vars + enableServiceLinks: false + + {{- with .Values.global.image.pullSecretNames }} + imagePullSecrets: + {{- range . }} + - name: {{ . | quote }} + {{- end }} + {{- end }} + + {{- with .Values.natsBox.serviceAccount }} + {{- if .enabled }} + serviceAccountName: {{ .name | quote }} + {{- end }} + {{- end }} + + volumes: + # contexts secret + - name: contexts + secret: + secretName: {{ .Values.natsBox.contextsSecret.name }} + # contents secret + {{- if .hasContentsSecret }} + - name: contents + secret: + secretName: {{ .Values.natsBox.contentsSecret.name }} + {{- end }} + # tlsCA + {{- include "nats.tlsCAVolume" $ | nindent 2 }} + # secrets + {{- range (include "natsBox.secretNames" $ | fromJson).secretNames }} + - name: {{ .name | quote }} + secret: + secretName: {{ .secretName | quote }} + {{- end }} diff --git a/utils/assets/charts/nats/files/nats-box/service-account.yaml b/utils/assets/charts/nats/files/nats-box/service-account.yaml new file mode 100644 index 0000000..c31e52f --- /dev/null +++ b/utils/assets/charts/nats/files/nats-box/service-account.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.serviceAccount.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} diff --git a/utils/assets/charts/nats/files/pod-disruption-budget.yaml b/utils/assets/charts/nats/files/pod-disruption-budget.yaml new file mode 100644 index 0000000..fd1fdea --- /dev/null +++ b/utils/assets/charts/nats/files/pod-disruption-budget.yaml @@ -0,0 +1,12 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.podDisruptionBudget.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + maxUnavailable: 1 + selector: + matchLabels: + {{- include "nats.selectorLabels" $ | nindent 6 }} diff --git a/utils/assets/charts/nats/files/pod-monitor.yaml b/utils/assets/charts/nats/files/pod-monitor.yaml new file mode 100644 index 0000000..c6c8eae --- /dev/null +++ b/utils/assets/charts/nats/files/pod-monitor.yaml @@ -0,0 +1,13 @@ +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.promExporter.podMonitor.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "nats.selectorLabels" $ | nindent 6 }} + podMetricsEndpoints: + - port: prom-metrics diff --git a/utils/assets/charts/nats/files/service-account.yaml b/utils/assets/charts/nats/files/service-account.yaml new file mode 100644 index 0000000..22c18cc --- /dev/null +++ b/utils/assets/charts/nats/files/service-account.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.serviceAccount.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} diff --git a/utils/assets/charts/nats/files/service.yaml b/utils/assets/charts/nats/files/service.yaml new file mode 100644 index 0000000..db08fe5 --- /dev/null +++ b/utils/assets/charts/nats/files/service.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.service.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + {{- include "nats.selectorLabels" $ | nindent 4 }} + ports: + {{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }} + {{- $configProtocol := get $.Values.config $protocol }} + {{- $servicePort := get $.Values.service.ports $protocol }} + {{- if and (or (eq $protocol "nats") $configProtocol.enabled) $servicePort.enabled }} + {{- $tlsEnabled := false }} + {{- if hasKey $configProtocol "tls" }} + {{- $tlsEnabled = $configProtocol.tls.enabled }} + {{- end }} + {{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }} + - {{ merge (dict "name" $protocol "targetPort" $protocol "appProtocol" $appProtocol) (omit $servicePort "enabled") (dict "port" $configProtocol.port) | toYaml | nindent 4 }} + {{- end }} + {{- end }} diff --git a/utils/assets/charts/nats/files/stateful-set/jetstream-pvc.yaml b/utils/assets/charts/nats/files/stateful-set/jetstream-pvc.yaml new file mode 100644 index 0000000..a43f200 --- /dev/null +++ b/utils/assets/charts/nats/files/stateful-set/jetstream-pvc.yaml @@ -0,0 +1,13 @@ +{{- with .Values.config.jetstream.fileStore.pvc }} +metadata: + name: {{ .name }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .size | quote }} + {{- with .storageClassName }} + storageClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/stateful-set/nats-container.yaml b/utils/assets/charts/nats/files/stateful-set/nats-container.yaml new file mode 100644 index 0000000..c5402ef --- /dev/null +++ b/utils/assets/charts/nats/files/stateful-set/nats-container.yaml @@ -0,0 +1,106 @@ +name: nats +{{ include "nats.image" (merge (pick $.Values "global") .Values.container.image) }} + +ports: +{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }} +{{- $configProtocol := get $.Values.config $protocol }} +{{- $containerPort := get $.Values.container.ports $protocol }} +{{- if or (eq $protocol "nats") $configProtocol.enabled }} +- {{ merge (dict "name" $protocol "containerPort" $configProtocol.port) $containerPort | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +args: +- --config +- /etc/nats-config/nats.conf + +env: +- name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name +- name: SERVER_NAME + value: {{ printf "%s$(POD_NAME)" .Values.config.serverNamePrefix | quote }} +{{- with .Values.container.env }} +{{- include "nats.env" . }} +{{- end }} + +lifecycle: + preStop: + exec: + # send the lame duck shutdown signal to trigger a graceful shutdown + command: + - nats-server + - -sl=ldm=/var/run/nats/nats.pid + +{{- with .Values.config.monitor }} +{{- if .enabled }} +startupProbe: + httpGet: + path: /healthz + port: monitor + {{- if .tls.enabled }} + scheme: HTTPS + {{- end}} + initialDelaySeconds: 10 + timeoutSeconds: 5 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 90 +readinessProbe: + httpGet: + path: /healthz?js-server-only=true + port: monitor + {{- if .tls.enabled }} + scheme: HTTPS + {{- end}} + initialDelaySeconds: 10 + timeoutSeconds: 5 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 +livenessProbe: + httpGet: + path: /healthz?js-enabled-only=true + port: monitor + {{- if .tls.enabled }} + scheme: HTTPS + {{- end}} + initialDelaySeconds: 10 + timeoutSeconds: 5 + periodSeconds: 30 + successThreshold: 1 + failureThreshold: 3 +{{- end }} +{{- end }} + +volumeMounts: +# nats config +- name: config + mountPath: /etc/nats-config +# PID volume +- name: pid + mountPath: /var/run/nats +# JetStream PVC +{{- with .Values.config.jetstream }} +{{- if and .enabled .fileStore.enabled .fileStore.pvc.enabled }} +{{- with .fileStore }} +- name: {{ .pvc.name }} + mountPath: {{ .dir | quote }} +{{- end }} +{{- end }} +{{- end }} +# resolver PVC +{{- with .Values.config.resolver }} +{{- if and .enabled .pvc.enabled }} +- name: {{ .pvc.name }} + mountPath: {{ .dir | quote }} +{{- end }} +{{- end }} +# tlsCA +{{- include "nats.tlsCAVolumeMount" $ }} +# secrets +{{- range (include "nats.secretNames" $ | fromJson).secretNames }} +- name: {{ .name | quote }} + mountPath: {{ .dir | quote }} +{{- end }} diff --git a/utils/assets/charts/nats/files/stateful-set/pod-template.yaml b/utils/assets/charts/nats/files/stateful-set/pod-template.yaml new file mode 100644 index 0000000..bb1d8d7 --- /dev/null +++ b/utils/assets/charts/nats/files/stateful-set/pod-template.yaml @@ -0,0 +1,71 @@ +metadata: + labels: + {{- include "nats.labels" $ | nindent 4 }} + annotations: + {{- if .Values.podTemplate.configChecksumAnnotation }} + {{- $configMap := include "nats.loadMergePatch" (merge (dict "file" "config-map.yaml" "ctx" $) $.Values.configMap) }} + checksum/config: {{ sha256sum $configMap }} + {{- end }} +spec: + containers: + # nats + {{- $nats := dict }} + {{- with .Values.container }} + {{- $nats = include "nats.loadMergePatch" (merge (dict "file" "stateful-set/nats-container.yaml" "ctx" $) .) | fromYaml }} + - {{ toYaml $nats | nindent 4 }} + {{- end }} + # reloader + {{- with .Values.reloader }} + {{- if .enabled }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/reloader-container.yaml" "ctx" (merge (dict "natsVolumeMounts" $nats.volumeMounts) $)) .) | nindent 4 }} + {{- end }} + {{- end }} + {{- with .Values.promExporter }} + {{- if .enabled }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/prom-exporter-container.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + {{- end }} + + # service discovery uses DNS; don't need service env vars + enableServiceLinks: false + + {{- with .Values.global.image.pullSecretNames }} + imagePullSecrets: + {{- range . }} + - name: {{ . | quote }} + {{- end }} + {{- end }} + + {{- with .Values.serviceAccount }} + {{- if .enabled }} + serviceAccountName: {{ .name | quote }} + {{- end }} + {{- end }} + + {{- if .Values.reloader.enabled }} + shareProcessNamespace: true + {{- end }} + + volumes: + # nats config + - name: config + configMap: + name: {{ .Values.configMap.name }} + # PID volume + - name: pid + emptyDir: {} + # tlsCA + {{- include "nats.tlsCAVolume" $ | nindent 2 }} + # secrets + {{- range (include "nats.secretNames" $ | fromJson).secretNames }} + - name: {{ .name | quote }} + secret: + secretName: {{ .secretName | quote }} + {{- end }} + + {{- with .Values.podTemplate.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $k, $v := . }} + - {{ merge (dict "topologyKey" $k "labelSelector" (dict "matchLabels" (include "nats.selectorLabels" $ | fromYaml))) $v | toYaml | nindent 4 }} + {{- end }} + {{- end}} diff --git a/utils/assets/charts/nats/files/stateful-set/prom-exporter-container.yaml b/utils/assets/charts/nats/files/stateful-set/prom-exporter-container.yaml new file mode 100644 index 0000000..c3e1b6f --- /dev/null +++ b/utils/assets/charts/nats/files/stateful-set/prom-exporter-container.yaml @@ -0,0 +1,30 @@ +name: prom-exporter +{{ include "nats.image" (merge (pick $.Values "global") .Values.promExporter.image) }} + +ports: +- name: prom-metrics + containerPort: {{ .Values.promExporter.port }} + +{{- with .Values.promExporter.env }} +env: +{{- include "nats.env" . }} +{{- end }} + +args: +- -port={{ .Values.promExporter.port }} +- -connz +- -routez +- -subz +- -varz +- -prefix=nats +- -use_internal_server_id +{{- if .Values.config.jetstream.enabled }} +- -jsz=all +{{- end }} +{{- if .Values.config.leafnodes.enabled }} +- -leafz +{{- end }} +{{- if .Values.config.gateway.enabled }} +- -gatewayz +{{- end }} +- http://localhost:{{ .Values.config.monitor.port }}/ diff --git a/utils/assets/charts/nats/files/stateful-set/reloader-container.yaml b/utils/assets/charts/nats/files/stateful-set/reloader-container.yaml new file mode 100644 index 0000000..9672204 --- /dev/null +++ b/utils/assets/charts/nats/files/stateful-set/reloader-container.yaml @@ -0,0 +1,27 @@ +name: reloader +{{ include "nats.image" (merge (pick $.Values "global") .Values.reloader.image) }} + +{{- with .Values.reloader.env }} +env: +{{- include "nats.env" . }} +{{- end }} + +args: +- -pid +- /var/run/nats/nats.pid +- -config +- /etc/nats-config/nats.conf +{{ include "nats.reloaderConfig" (dict "config" .config "dir" "/etc/nats-config") }} + +volumeMounts: +- name: pid + mountPath: /var/run/nats +{{- range $mnt := .natsVolumeMounts }} +{{- $found := false }} +{{- range $.Values.reloader.natsVolumeMountPrefixes }} +{{- if and (not $found) (hasPrefix . $mnt.mountPath) }} +{{- $found = true }} +- {{ toYaml $mnt | nindent 2}} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/stateful-set/resolver-pvc.yaml b/utils/assets/charts/nats/files/stateful-set/resolver-pvc.yaml new file mode 100644 index 0000000..3634cd8 --- /dev/null +++ b/utils/assets/charts/nats/files/stateful-set/resolver-pvc.yaml @@ -0,0 +1,13 @@ +{{- with .Values.config.resolver.pvc }} +metadata: + name: {{ .name }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .size | quote }} + {{- with .storageClassName }} + storageClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/files/stateful-set/stateful-set.yaml b/utils/assets/charts/nats/files/stateful-set/stateful-set.yaml new file mode 100644 index 0000000..cd8082c --- /dev/null +++ b/utils/assets/charts/nats/files/stateful-set/stateful-set.yaml @@ -0,0 +1,37 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.statefulSet.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "nats.selectorLabels" $ | nindent 6 }} + {{- if .Values.config.cluster.enabled }} + replicas: {{ .Values.config.cluster.replicas }} + {{- else }} + replicas: 1 + {{- end }} + serviceName: {{ .Values.headlessService.name }} + podManagementPolicy: Parallel + template: + {{- with .Values.podTemplate }} + {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/pod-template.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + volumeClaimTemplates: + {{- with .Values.config.jetstream }} + {{- if and .enabled .fileStore.enabled .fileStore.pvc.enabled }} + {{- with .fileStore.pvc }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/jetstream-pvc.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.config.resolver }} + {{- if and .enabled .pvc.enabled }} + {{- with .pvc }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/resolver-pvc.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + {{- end }} + {{- end }} diff --git a/utils/assets/charts/nats/templates/_helpers.tpl b/utils/assets/charts/nats/templates/_helpers.tpl new file mode 100644 index 0000000..ba83139 --- /dev/null +++ b/utils/assets/charts/nats/templates/_helpers.tpl @@ -0,0 +1,281 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "nats.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "nats.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "nats.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Print the namespace +*/}} +{{- define "nats.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride }} +{{- end }} + +{{/* +Print the namespace for the metadata section +*/}} +{{- define "nats.metadataNamespace" -}} +{{- with .Values.namespaceOverride }} +namespace: {{ . | quote }} +{{- end }} +{{- end }} + +{{/* +Set default values. +*/}} +{{- define "nats.defaultValues" }} +{{- if not .defaultValuesSet }} + {{- $name := include "nats.fullname" . }} + {{- with .Values }} + {{- $_ := set .config.jetstream.fileStore.pvc "name" (.config.jetstream.fileStore.pvc.name | default (printf "%s-js" $name)) }} + {{- $_ := set .config.resolver.pvc "name" (.config.resolver.pvc.name | default (printf "%s-resolver" $name)) }} + {{- $_ := set .config.websocket.ingress "name" (.config.websocket.ingress.name | default (printf "%s-ws" $name)) }} + {{- $_ := set .configMap "name" (.configMap.name | default (printf "%s-config" $name)) }} + {{- $_ := set .headlessService "name" (.headlessService.name | default (printf "%s-headless" $name)) }} + {{- $_ := set .natsBox.contentsSecret "name" (.natsBox.contentsSecret.name | default (printf "%s-box-contents" $name)) }} + {{- $_ := set .natsBox.contextsSecret "name" (.natsBox.contextsSecret.name | default (printf "%s-box-contexts" $name)) }} + {{- $_ := set .natsBox.deployment "name" (.natsBox.deployment.name | default (printf "%s-box" $name)) }} + {{- $_ := set .natsBox.serviceAccount "name" (.natsBox.serviceAccount.name | default (printf "%s-box" $name)) }} + {{- $_ := set .podDisruptionBudget "name" (.podDisruptionBudget.name | default $name) }} + {{- $_ := set .service "name" (.service.name | default $name) }} + {{- $_ := set .serviceAccount "name" (.serviceAccount.name | default $name) }} + {{- $_ := set .statefulSet "name" (.statefulSet.name | default $name) }} + {{- $_ := set .promExporter.podMonitor "name" (.promExporter.podMonitor.name | default $name) }} + {{- end }} + + {{- $values := get (include "tplYaml" (dict "doc" .Values "ctx" $) | fromJson) "doc" }} + {{- $_ := set . "Values" $values }} + + {{- $hasContentsSecret := false }} + {{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} + {{- range $secretKey, $secretVal := dict "creds" "nats-creds" "nkey" "nats-nkeys" "tls" "nats-certs" }} + {{- $secret := get $ctxVal $secretKey }} + {{- if $secret }} + {{- $_ := set $secret "dir" ($secret.dir | default (printf "/etc/%s/%s" $secretVal $ctxKey)) }} + {{- if and (ne $secretKey "tls") $secret.contents }} + {{- $hasContentsSecret = true }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- $_ := set $ "hasContentsSecret" $hasContentsSecret }} + + {{- with .Values.config }} + {{- $config := include "nats.loadMergePatch" (merge (dict "file" "config/config.yaml" "ctx" $) .) | fromYaml }} + {{- $_ := set $ "config" $config }} + {{- end }} + + {{- $_ := set . "defaultValuesSet" true }} +{{- end }} +{{- end }} + +{{/* +NATS labels +*/}} +{{- define "nats.labels" -}} +{{- with .Values.global.labels -}} +{{ toYaml . }} +{{ end -}} +helm.sh/chart: {{ include "nats.chart" . }} +{{ include "nats.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +NATS selector labels +*/}} +{{- define "nats.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nats.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: nats +{{- end }} + +{{/* +NATS Box labels +*/}} +{{- define "natsBox.labels" -}} +{{- with .Values.global.labels -}} +{{ toYaml . }} +{{ end -}} +helm.sh/chart: {{ include "nats.chart" . }} +{{ include "natsBox.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +NATS Box selector labels +*/}} +{{- define "natsBox.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nats.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: nats-box +{{- end }} + +{{/* +Print the image +*/}} +{{- define "nats.image" }} +{{- $image := printf "%s:%s" .repository .tag }} +{{- if or .registry .global.image.registry }} +{{- $image = printf "%s/%s" (.registry | default .global.image.registry) $image }} +{{- end -}} +image: {{ $image }} +{{- if or .pullPolicy .global.image.pullPolicy }} +imagePullPolicy: {{ .pullPolicy | default .global.image.pullPolicy }} +{{- end }} +{{- end }} + +{{- define "nats.secretNames" -}} +{{- $secrets := list }} +{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" }} + {{- $configProtocol := get $.Values.config $protocol }} + {{- if and (or (eq $protocol "nats") $configProtocol.enabled) $configProtocol.tls.enabled $configProtocol.tls.secretName }} + {{- $secrets = append $secrets (merge (dict "name" (printf "%s-tls" $protocol)) $configProtocol.tls) }} + {{- end }} +{{- end }} +{{- toJson (dict "secretNames" $secrets) }} +{{- end }} + +{{- define "natsBox.secretNames" -}} +{{- $secrets := list }} +{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} +{{- range $secretKey, $secretVal := dict "creds" "nats-creds" "nkey" "nats-nkeys" "tls" "nats-certs" }} + {{- $secret := get $ctxVal $secretKey }} + {{- if and $secret $secret.secretName }} + {{- $secrets = append $secrets (merge (dict "name" (printf "ctx-%s-%s" $ctxKey $secretKey)) $secret) }} + {{- end }} + {{- end }} +{{- end }} +{{- toJson (dict "secretNames" $secrets) }} +{{- end }} + +{{- define "nats.tlsCAVolume" -}} +{{- with .Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +- name: tls-ca +{{- if .configMapName }} + configMap: + name: {{ .configMapName | quote }} +{{- else if .secretName }} + secret: + secretName: {{ .secretName | quote }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "nats.tlsCAVolumeMount" -}} +{{- with .Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +- name: tls-ca + mountPath: {{ .dir | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +translates env var map to list +*/}} +{{- define "nats.env" -}} +{{- range $k, $v := . }} +{{- if kindIs "string" $v }} +- name: {{ $k | quote }} + value: {{ $v | quote }} +{{- else if kindIs "map" $v }} +- {{ merge (dict "name" $k) $v | toYaml | nindent 2 }} +{{- else }} +{{- fail (cat "env var" $k "must be string or map, got" (kindOf $v)) }} +{{- end }} +{{- end }} +{{- end }} + +{{- /* +nats.loadMergePatch +input: map with 4 keys: +- file: name of file to load +- ctx: context to pass to tpl +- merge: interface{} to merge +- patch: []interface{} valid JSON Patch document +output: JSON encoded map with 1 key: +- doc: interface{} patched json result +*/}} +{{- define "nats.loadMergePatch" -}} +{{- $doc := tpl (.ctx.Files.Get (printf "files/%s" .file)) .ctx | fromYaml | default dict -}} +{{- $doc = mergeOverwrite $doc (deepCopy (.merge | default dict)) -}} +{{- get (include "jsonpatch" (dict "doc" $doc "patch" (.patch | default list)) | fromJson ) "doc" | toYaml -}} +{{- end }} + + +{{- /* +nats.reloaderConfig +input: map with 2 keys: +- config: interface{} nats config +- dir: dir config file is in +output: YAML list of reloader config files +*/}} +{{- define "nats.reloaderConfig" -}} + {{- $dir := trimSuffix "/" .dir -}} + {{- with .config -}} + {{- if kindIs "map" . -}} + {{- range $k, $v := . -}} + {{- if or (eq $k "cert_file") (eq $k "key_file") (eq $k "ca_file") }} +- -config +- {{ $v }} + {{- else if hasSuffix "$include" $k }} +- -config +- {{ clean (printf "%s/%s" $dir $v) }} + {{- else }} + {{- include "nats.reloaderConfig" (dict "config" $v "dir" $dir) }} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} + + +{{- /* +nats.formatConfig +input: map[string]interface{} +output: string with following format rules +1. keys ending in $natsRaw are unquoted +2. keys ending in $natsInclude are converted to include directives +*/}} +{{- define "nats.formatConfig" -}} + {{- + (regexReplaceAll "\"<<\\s+(.*)\\s+>>\"" + (regexReplaceAll "\".*\\$include\": \"(.*)\",?" (include "toPrettyRawJson" .) "include ${1};") + "${1}") + -}} +{{- end -}} diff --git a/utils/assets/charts/nats/templates/_jsonpatch.tpl b/utils/assets/charts/nats/templates/_jsonpatch.tpl new file mode 100644 index 0000000..cd42c3b --- /dev/null +++ b/utils/assets/charts/nats/templates/_jsonpatch.tpl @@ -0,0 +1,219 @@ +{{- /* +jsonpatch +input: map with 2 keys: +- doc: interface{} valid JSON document +- patch: []interface{} valid JSON Patch document +output: JSON encoded map with 1 key: +- doc: interface{} patched json result +*/}} +{{- define "jsonpatch" -}} + {{- $params := fromJson (toJson .) -}} + {{- $patches := $params.patch -}} + {{- $docContainer := pick $params "doc" -}} + + {{- range $patch := $patches -}} + {{- if not (hasKey $patch "op") -}} + {{- fail "patch is missing op key" -}} + {{- end -}} + {{- if and (ne $patch.op "add") (ne $patch.op "remove") (ne $patch.op "replace") (ne $patch.op "copy") (ne $patch.op "move") (ne $patch.op "test") -}} + {{- fail (cat "patch has invalid op" $patch.op) -}} + {{- end -}} + {{- if not (hasKey $patch "path") -}} + {{- fail "patch is missing path key" -}} + {{- end -}} + {{- if and (or (eq $patch.op "add") (eq $patch.op "replace") (eq $patch.op "test")) (not (hasKey $patch "value")) -}} + {{- fail (cat "patch with op" $patch.op "is missing value key") -}} + {{- end -}} + {{- if and (or (eq $patch.op "copy") (eq $patch.op "move")) (not (hasKey $patch "from")) -}} + {{- fail (cat "patch with op" $patch.op "is missing from key") -}} + {{- end -}} + + {{- $opPathKeys := list "path" -}} + {{- if or (eq $patch.op "copy") (eq $patch.op "move") -}} + {{- $opPathKeys = append $opPathKeys "from" -}} + {{- end -}} + {{- $reSlice := list -}} + + {{- range $opPathKey := $opPathKeys -}} + {{- $obj := $docContainer -}} + {{- if and (eq $patch.op "copy") (eq $opPathKey "from") -}} + {{- $obj = (fromJson (toJson $docContainer)) -}} + {{- end -}} + {{- $key := "doc" -}} + {{- $lastMap := dict "root" $obj -}} + {{- $lastKey := "root" -}} + {{- $paths := (splitList "/" (get $patch $opPathKey)) -}} + {{- $firstPath := index $paths 0 -}} + {{- if ne (index $paths 0) "" -}} + {{- fail (cat "invalid" $opPathKey (get $patch $opPathKey) "must be empty string or start with /") -}} + {{- end -}} + {{- $paths = slice $paths 1 -}} + + {{- range $path := $paths -}} + {{- $path = replace "~1" "/" $path -}} + {{- $path = replace "~0" "~" $path -}} + + {{- if kindIs "slice" $obj -}} + {{- $mapObj := dict -}} + {{- range $i, $v := $obj -}} + {{- $_ := set $mapObj (toString $i) $v -}} + {{- end -}} + {{- $obj = $mapObj -}} + {{- $_ := set $lastMap $lastKey $obj -}} + {{- $reSlice = prepend $reSlice (dict "lastMap" $lastMap "lastKey" $lastKey "mapObj" $obj) -}} + {{- end -}} + + {{- if kindIs "map" $obj -}} + {{- if not (hasKey $obj $key) -}} + {{- fail (cat "key" $key "does not exist") -}} + {{- end -}} + {{- $lastKey = $key -}} + {{- $lastMap = $obj -}} + {{- $obj = index $obj $key -}} + {{- $key = $path -}} + {{- else -}} + {{- fail (cat "cannot iterate into path" $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- $_ := set $patch (printf "%sKey" $opPathKey) $key -}} + {{- $_ := set $patch (printf "%sLastKey" $opPathKey) $lastKey -}} + {{- $_ = set $patch (printf "%sLastMap" $opPathKey) $lastMap -}} + {{- end -}} + + {{- if eq $patch.op "move" }} + {{- if and (ne $patch.path $patch.from) (hasPrefix (printf "%s/" $patch.path) (printf "%s/" $patch.from)) -}} + {{- fail (cat "from" $patch.from "may not be a child of path" $patch.path) -}} + {{- end -}} + {{- end -}} + + {{- if or (eq $patch.op "move") (eq $patch.op "copy") (eq $patch.op "test") }} + {{- $key := $patch.fromKey -}} + {{- $lastMap := $patch.fromLastMap -}} + {{- $lastKey := $patch.fromLastKey -}} + {{- $setKey := "value" -}} + {{- if eq $patch.op "test" }} + {{- $key = $patch.pathKey -}} + {{- $lastMap = $patch.pathLastMap -}} + {{- $lastKey = $patch.pathLastKey -}} + {{- $setKey = "testValue" -}} + {{- end -}} + {{- $obj := index $lastMap $lastKey -}} + + {{- if kindIs "map" $obj -}} + {{- if not (hasKey $obj $key) -}} + {{- fail (cat $key "does not exist") -}} + {{- end -}} + {{- $_ := set $patch $setKey (index $obj $key) -}} + + {{- else if kindIs "slice" $obj -}} + {{- $i := atoi $key -}} + {{- if ne $key (toString $i) -}} + {{- fail (cat "cannot convert" $key "to int") -}} + {{- end -}} + {{- if lt $i 0 -}} + {{- fail "slice index <0" -}} + {{- else if lt $i (len $obj) -}} + {{- $_ := set $patch $setKey (index $obj $i) -}} + {{- else -}} + {{- fail "slice index >= slice length" -}} + {{- end -}} + + {{- else -}} + {{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- if or (eq $patch.op "remove") (eq $patch.op "replace") (eq $patch.op "move") }} + {{- $key := $patch.pathKey -}} + {{- $lastMap := $patch.pathLastMap -}} + {{- $lastKey := $patch.pathLastKey -}} + {{- if eq $patch.op "move" }} + {{- $key = $patch.fromKey -}} + {{- $lastMap = $patch.fromLastMap -}} + {{- $lastKey = $patch.fromLastKey -}} + {{- end -}} + {{- $obj := index $lastMap $lastKey -}} + + {{- if kindIs "map" $obj -}} + {{- if not (hasKey $obj $key) -}} + {{- fail (cat $key "does not exist") -}} + {{- end -}} + {{- $_ := unset $obj $key -}} + + {{- else if kindIs "slice" $obj -}} + {{- $i := atoi $key -}} + {{- if ne $key (toString $i) -}} + {{- fail (cat "cannot convert" $key "to int") -}} + {{- end -}} + {{- if lt $i 0 -}} + {{- fail "slice index <0" -}} + {{- else if eq $i 0 -}} + {{- $_ := set $lastMap $lastKey (slice $obj 1) -}} + {{- else if lt $i (sub (len $obj) 1) -}} + {{- $_ := set $lastMap $lastKey (concat (slice $obj 0 $i) (slice $obj (add $i 1) (len $obj))) -}} + {{- else if eq $i (sub (len $obj) 1) -}} + {{- $_ := set $lastMap $lastKey (slice $obj 0 (sub (len $obj) 1)) -}} + {{- else -}} + {{- fail "slice index >= slice length" -}} + {{- end -}} + + {{- else -}} + {{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- if or (eq $patch.op "add") (eq $patch.op "replace") (eq $patch.op "move") (eq $patch.op "copy") }} + {{- $key := $patch.pathKey -}} + {{- $lastMap := $patch.pathLastMap -}} + {{- $lastKey := $patch.pathLastKey -}} + {{- $value := $patch.value -}} + {{- $obj := index $lastMap $lastKey -}} + + {{- if kindIs "map" $obj -}} + {{- $_ := set $obj $key $value -}} + + {{- else if kindIs "slice" $obj -}} + {{- $i := 0 -}} + {{- if eq $key "-" -}} + {{- $i = len $obj -}} + {{- else -}} + {{- $i = atoi $key -}} + {{- if ne $key (toString $i) -}} + {{- fail (cat "cannot convert" $key "to int") -}} + {{- end -}} + {{- end -}} + {{- if lt $i 0 -}} + {{- fail "slice index <0" -}} + {{- else if eq $i 0 -}} + {{- $_ := set $lastMap $lastKey (prepend $obj $value) -}} + {{- else if lt $i (len $obj) -}} + {{- $_ := set $lastMap $lastKey (concat (append (slice $obj 0 $i) $value) (slice $obj $i)) -}} + {{- else if eq $i (len $obj) -}} + {{- $_ := set $lastMap $lastKey (append $obj $value) -}} + {{- else -}} + {{- fail "slice index > slice length" -}} + {{- end -}} + + {{- else -}} + {{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- if eq $patch.op "test" }} + {{- if not (deepEqual $patch.value $patch.testValue) }} + {{- fail (cat "test failed, expected" (toJson $patch.value) "but got" (toJson $patch.testValue)) -}} + {{- end -}} + {{- end -}} + + {{- range $reSliceOp := $reSlice -}} + {{- $sliceObj := list -}} + {{- range $i := until (len $reSliceOp.mapObj) -}} + {{- $sliceObj = append $sliceObj (index $reSliceOp.mapObj (toString $i)) -}} + {{- end -}} + {{- $_ := set $reSliceOp.lastMap $reSliceOp.lastKey $sliceObj -}} + {{- end -}} + + {{- end -}} + {{- toJson $docContainer -}} +{{- end -}} diff --git a/utils/assets/charts/nats/templates/_toPrettyRawJson.tpl b/utils/assets/charts/nats/templates/_toPrettyRawJson.tpl new file mode 100644 index 0000000..612a62f --- /dev/null +++ b/utils/assets/charts/nats/templates/_toPrettyRawJson.tpl @@ -0,0 +1,28 @@ +{{- /* +toPrettyRawJson +input: interface{} valid JSON document +output: pretty raw JSON string +*/}} +{{- define "toPrettyRawJson" -}} + {{- include "toPrettyRawJsonStr" (toPrettyJson .) -}} +{{- end -}} + +{{- /* +toPrettyRawJsonStr +input: pretty JSON string +output: pretty raw JSON string +*/}} +{{- define "toPrettyRawJsonStr" -}} + {{- $s := + (regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u003e" + (regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u003c" + (regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u0026" . "${1}&") + "${1}<") + "${1}>") + -}} + {{- if regexMatch "([^\\\\](?:\\\\\\\\)*)\\\\u00(26|3c|3e)" $s -}} + {{- include "toPrettyRawJsonStr" $s -}} + {{- else -}} + {{- $s -}} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/nats/templates/_tplYaml.tpl b/utils/assets/charts/nats/templates/_tplYaml.tpl new file mode 100644 index 0000000..f42b9c1 --- /dev/null +++ b/utils/assets/charts/nats/templates/_tplYaml.tpl @@ -0,0 +1,114 @@ +{{- /* +tplYaml +input: map with 2 keys: +- doc: interface{} +- ctx: context to pass to tpl function +output: JSON encoded map with 1 key: +- doc: interface{} with any keys called tpl or tplSpread values templated and replaced + +maps matching the following syntax will be templated and parsed as YAML +{ + $tplYaml: string +} + +maps matching the follow syntax will be templated, parsed as YAML, and spread into the parent map/slice +{ + $tplYamlSpread: string +} +*/}} +{{- define "tplYaml" -}} + {{- $patch := get (include "tplYamlItr" (dict "ctx" .ctx "parentKind" "" "parentPath" "" "path" "/" "value" .doc) | fromJson) "patch" -}} + {{- include "jsonpatch" (dict "doc" .doc "patch" $patch) -}} +{{- end -}} + +{{- /* +tplYamlItr +input: map with 4 keys: +- path: string JSONPath to current element +- parentKind: string kind of parent element +- parentPath: string JSONPath to parent element +- value: interface{} +- ctx: context to pass to tpl function +output: JSON encoded map with 1 key: +- patch: list of patches to apply in order to template +*/}} +{{- define "tplYamlItr" -}} + {{- $params := . -}} + {{- $kind := kindOf $params.value -}} + {{- $patch := list -}} + {{- $joinPath := $params.path -}} + {{- if eq $params.path "/" -}} + {{- $joinPath = "" -}} + {{- end -}} + {{- $joinParentPath := $params.parentPath -}} + {{- if eq $params.parentPath "/" -}} + {{- $joinParentPath = "" -}} + {{- end -}} + + {{- if eq $kind "slice" -}} + {{- $iAdj := 0 -}} + {{- range $i, $v := $params.value -}} + {{- $iPath := printf "%s/%d" $joinPath (add $i $iAdj) -}} + {{- $itrPatch := get (include "tplYamlItr" (dict "ctx" $params.ctx "parentKind" $kind "parentPath" $params.path "path" $iPath "value" $v) | fromJson) "patch" -}} + {{- $itrLen := len $itrPatch -}} + {{- if gt $itrLen 0 -}} + {{- $patch = concat $patch $itrPatch -}} + {{- if eq (get (index $itrPatch 0) "op") "remove" -}} + {{- $iAdj = add $iAdj (sub $itrLen 2) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- else if eq $kind "map" -}} + {{- if and (eq (len $params.value) 1) (or (hasKey $params.value "$tplYaml") (hasKey $params.value "$tplYamlSpread")) -}} + {{- $tpl := get $params.value "$tplYaml" -}} + {{- $spread := false -}} + {{- if hasKey $params.value "$tplYamlSpread" -}} + {{- if eq $params.path "/" -}} + {{- fail "cannot $tplYamlSpread on root object" -}} + {{- end -}} + {{- $tpl = get $params.value "$tplYamlSpread" -}} + {{- $spread = true -}} + {{- end -}} + + {{- $res := tpl $tpl $params.ctx -}} + {{- $res = get (fromYaml (tpl "tpl: {{ nindent 2 .res }}" (merge (dict "res" $res) $params.ctx))) "tpl" -}} + + {{- if eq $spread false -}} + {{- $patch = append $patch (dict "op" "replace" "path" $params.path "value" $res) -}} + {{- else -}} + {{- $resKind := kindOf $res -}} + {{- if and (ne $resKind "invalid") (ne $resKind $params.parentKind) -}} + {{- fail (cat "can only $tplYamlSpread slice onto a slice or map onto a map; attempted to spread" $resKind "on" $params.parentKind "at path" $params.path) -}} + {{- end -}} + {{- $patch = append $patch (dict "op" "remove" "path" $params.path) -}} + {{- if eq $resKind "invalid" -}} + {{- /* no-op */ -}} + {{- else if eq $resKind "slice" -}} + {{- range $v := reverse $res -}} + {{- $patch = append $patch (dict "op" "add" "path" $params.path "value" $v) -}} + {{- end -}} + {{- else -}} + {{- range $k, $v := $res -}} + {{- $kPath := replace "~" "~0" $k -}} + {{- $kPath = replace "/" "~1" $kPath -}} + {{- $kPath = printf "%s/%s" $joinParentPath $kPath -}} + {{- $patch = append $patch (dict "op" "add" "path" $kPath "value" $v) -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- else -}} + {{- range $k, $v := $params.value -}} + {{- $kPath := replace "~" "~0" $k -}} + {{- $kPath = replace "/" "~1" $kPath -}} + {{- $kPath = printf "%s/%s" $joinPath $kPath -}} + {{- $itrPatch := get (include "tplYamlItr" (dict "ctx" $params.ctx "parentKind" $kind "parentPath" $params.path "path" $kPath "value" $v) | fromJson) "patch" -}} + {{- if gt (len $itrPatch) 0 -}} + {{- $patch = concat $patch $itrPatch -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- toJson (dict "patch" $patch) -}} +{{- end -}} diff --git a/utils/assets/charts/nats/templates/config-map.yaml b/utils/assets/charts/nats/templates/config-map.yaml new file mode 100644 index 0000000..b95afda --- /dev/null +++ b/utils/assets/charts/nats/templates/config-map.yaml @@ -0,0 +1,4 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.configMap }} +{{- include "nats.loadMergePatch" (merge (dict "file" "config-map.yaml" "ctx" $) .) }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/extra-resources.yaml b/utils/assets/charts/nats/templates/extra-resources.yaml new file mode 100644 index 0000000..c11f008 --- /dev/null +++ b/utils/assets/charts/nats/templates/extra-resources.yaml @@ -0,0 +1,5 @@ +{{- include "nats.defaultValues" . }} +{{- range .Values.extraResources }} +--- +{{ . | toYaml }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/headless-service.yaml b/utils/assets/charts/nats/templates/headless-service.yaml new file mode 100644 index 0000000..f11a83d --- /dev/null +++ b/utils/assets/charts/nats/templates/headless-service.yaml @@ -0,0 +1,4 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.headlessService }} +{{- include "nats.loadMergePatch" (merge (dict "file" "headless-service.yaml" "ctx" $) .) }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/ingress.yaml b/utils/assets/charts/nats/templates/ingress.yaml new file mode 100644 index 0000000..eccd73f --- /dev/null +++ b/utils/assets/charts/nats/templates/ingress.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.config.websocket.ingress }} +{{- if and .enabled .hosts $.Values.config.websocket.enabled $.Values.service.enabled $.Values.service.ports.websocket.enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "ingress.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/nats-box/contents-secret.yaml b/utils/assets/charts/nats/templates/nats-box/contents-secret.yaml new file mode 100644 index 0000000..db629bf --- /dev/null +++ b/utils/assets/charts/nats/templates/nats-box/contents-secret.yaml @@ -0,0 +1,10 @@ +{{- include "nats.defaultValues" . }} +{{- if .hasContentsSecret }} +{{- with .Values.natsBox }} +{{- if .enabled }} +{{- with .contentsSecret}} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/contents-secret.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/nats-box/contexts-secret.yaml b/utils/assets/charts/nats/templates/nats-box/contexts-secret.yaml new file mode 100644 index 0000000..5ae20f4 --- /dev/null +++ b/utils/assets/charts/nats/templates/nats-box/contexts-secret.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.natsBox }} +{{- if .enabled }} +{{- with .contextsSecret}} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/contexts-secret/contexts-secret.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/nats-box/deployment.yaml b/utils/assets/charts/nats/templates/nats-box/deployment.yaml new file mode 100644 index 0000000..a063332 --- /dev/null +++ b/utils/assets/charts/nats/templates/nats-box/deployment.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.natsBox }} +{{- if .enabled }} +{{- with .deployment }} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/deployment.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/nats-box/service-account.yaml b/utils/assets/charts/nats/templates/nats-box/service-account.yaml new file mode 100644 index 0000000..e11bdd3 --- /dev/null +++ b/utils/assets/charts/nats/templates/nats-box/service-account.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- if .Values.natsBox.enabled }} +{{- with .Values.natsBox.serviceAccount }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/service-account.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/pod-disruption-budget.yaml b/utils/assets/charts/nats/templates/pod-disruption-budget.yaml new file mode 100644 index 0000000..9117226 --- /dev/null +++ b/utils/assets/charts/nats/templates/pod-disruption-budget.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.podDisruptionBudget }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "pod-disruption-budget.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/pod-monitor.yaml b/utils/assets/charts/nats/templates/pod-monitor.yaml new file mode 100644 index 0000000..0e42a43 --- /dev/null +++ b/utils/assets/charts/nats/templates/pod-monitor.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.promExporter }} +{{- if and .enabled .podMonitor.enabled }} +{{- with .podMonitor }} +{{- include "nats.loadMergePatch" (merge (dict "file" "pod-monitor.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/service-account.yaml b/utils/assets/charts/nats/templates/service-account.yaml new file mode 100644 index 0000000..6c763bd --- /dev/null +++ b/utils/assets/charts/nats/templates/service-account.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.serviceAccount }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "service-account.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/service.yaml b/utils/assets/charts/nats/templates/service.yaml new file mode 100644 index 0000000..04b0b37 --- /dev/null +++ b/utils/assets/charts/nats/templates/service.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.service }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "service.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/stateful-set.yaml b/utils/assets/charts/nats/templates/stateful-set.yaml new file mode 100644 index 0000000..bb19832 --- /dev/null +++ b/utils/assets/charts/nats/templates/stateful-set.yaml @@ -0,0 +1,4 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.statefulSet }} +{{- include "nats.loadMergePatch" (merge (dict "file" "stateful-set/stateful-set.yaml" "ctx" $) .) }} +{{- end }} diff --git a/utils/assets/charts/nats/templates/tests/request-reply.yaml b/utils/assets/charts/nats/templates/tests/request-reply.yaml new file mode 100644 index 0000000..3e06edc --- /dev/null +++ b/utils/assets/charts/nats/templates/tests/request-reply.yaml @@ -0,0 +1,37 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.natsBox | deepCopy }} +{{- $natsBox := . }} +{{- if .enabled -}} +apiVersion: v1 +kind: Pod +{{- with .container }} +{{- $_ := set . "merge" (dict + "args" (list + "sh" + "-ec" + "nats reply --echo echo & pid=\"$!\"; sleep 1; nats request echo hi > /tmp/resp; kill \"$pid\"; wait; grep -qF hi /tmp/resp" + ) +) }} +{{- $_ := set . "patch" list }} +{{- end }} +{{- with .podTemplate }} +{{- $_ := set . "merge" (dict + "metadata" (dict + "name" (printf "%s-test-request-reply" $.Values.statefulSet.name) + "labels" (dict + "app.kubernetes.io/component" "test-request-reply" + ) + "annotations" (dict + "helm.sh/hook" "test" + "helm.sh/hook-delete-policy" "before-hook-creation,hook-succeeded" + ) + ) + "spec" (dict + "restartPolicy" "Never" + ) +) }} +{{- $_ := set . "patch" list }} +{{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/pod-template.yaml" "ctx" (merge (dict "Values" (dict "natsBox" $natsBox)) $)) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/nats/values.yaml b/utils/assets/charts/nats/values.yaml new file mode 100644 index 0000000..6f19c84 --- /dev/null +++ b/utils/assets/charts/nats/values.yaml @@ -0,0 +1,669 @@ +################################################################################ +# Global options +################################################################################ +global: + image: + # global image pull policy to use for all container images in the chart + # can be overridden by individual image pullPolicy + pullPolicy: + # global list of secret names to use as image pull secrets for all pod specs in the chart + # secrets must exist in the same namespace + # https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + pullSecretNames: [] + # global registry to use for all container images in the chart + # can be overridden by individual image registry + registry: + + # global labels will be applied to all resources deployed by the chart + labels: {} + +################################################################################ +# Common options +################################################################################ +# override name of the chart +nameOverride: +# override full name of the chart+release +fullnameOverride: +# override the namespace that resources are installed into +namespaceOverride: + +# reference a common CA Certificate or Bundle in all nats config `tls` blocks and nats-box contexts +# note: `tls.verify` still must be set in the appropriate nats config `tls` blocks to require mTLS +tlsCA: + enabled: false + # set configMapName in order to mount an existing configMap to dir + configMapName: + # set secretName in order to mount an existing secretName to dir + secretName: + # directory to mount the configMap or secret to + dir: /etc/nats-ca-cert + # key in the configMap or secret that contains the CA Certificate or Bundle + key: ca.crt + +################################################################################ +# NATS Stateful Set and associated resources +################################################################################ + +############################################################ +# NATS config +############################################################ +config: + cluster: + enabled: false + port: 6222 + # must be 2 or higher when jetstream is enabled + replicas: 3 + + # apply to generated route URLs that connect to other pods in the StatefulSet + routeURLs: + # if both user and password are set, they will be added to route URLs + # and the cluster authorization block + user: + password: + # set to true to use FQDN in route URLs + useFQDN: false + k8sClusterDomain: cluster.local + + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/cluster + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the cluster config + # https://docs.nats.io/running-a-nats-service/configuration/clustering/cluster_config + merge: {} + patch: [] + + jetstream: + enabled: false + + fileStore: + enabled: true + dir: /data + + ############################################################ + # stateful set -> volume claim templates -> jetstream pvc + ############################################################ + pvc: + enabled: true + size: 10Gi + storageClassName: + + # merge or patch the jetstream pvc + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-js" + name: + + # defaults to the PVC size + maxSize: + + memoryStore: + enabled: false + # ensure that container has a sufficient memory limit greater than maxSize + maxSize: 1Gi + + # merge or patch the jetstream config + # https://docs.nats.io/running-a-nats-service/configuration#jetstream + merge: {} + patch: [] + + nats: + port: 4222 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/nats + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + leafnodes: + enabled: false + port: 7422 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/leafnodes + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the leafnodes config + # https://docs.nats.io/running-a-nats-service/configuration/leafnodes/leafnode_conf + merge: {} + patch: [] + + websocket: + enabled: false + port: 8080 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/websocket + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + ############################################################ + # ingress + ############################################################ + # service must be enabled also + ingress: + enabled: false + # must contain at least 1 host otherwise ingress will not be created + hosts: [] + path: / + pathType: Exact + # sets to the ingress class name + className: + # set to an existing secret name to enable TLS on the ingress; applies to all hosts + tlsSecretName: + + # merge or patch the ingress + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#ingress-v1-networking-k8s-io + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-ws" + name: + + # merge or patch the websocket config + # https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf + merge: {} + patch: [] + + mqtt: + enabled: false + port: 1883 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/mqtt + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the mqtt config + # https://docs.nats.io/running-a-nats-service/configuration/mqtt/mqtt_config + merge: {} + patch: [] + + gateway: + enabled: false + port: 7222 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/gateway + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the gateway config + # https://docs.nats.io/running-a-nats-service/configuration/gateways/gateway#gateway-configuration-block + merge: {} + patch: [] + + monitor: + enabled: true + port: 8222 + tls: + # config.nats.tls must be enabled also + # when enabled, monitoring port will use HTTPS with the options from config.nats.tls + enabled: false + + profiling: + enabled: false + port: 65432 + + resolver: + enabled: false + dir: /data/resolver + + ############################################################ + # stateful set -> volume claim templates -> resolver pvc + ############################################################ + pvc: + enabled: true + size: 1Gi + storageClassName: + + # merge or patch the pvc + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-resolver" + name: + + # merge or patch the resolver + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/jwt/resolver + merge: {} + patch: [] + + # adds a prefix to the server name, which defaults to the pod name + # helpful for ensuring server name is unique in a super cluster + serverNamePrefix: "" + + # merge or patch the nats config + # https://docs.nats.io/running-a-nats-service/configuration + # following special rules apply + # 1. strings that start with << and end with >> will be unquoted + # use this for variables and numbers with units + # 2. keys ending in $include will be switched to include directives + # keys are sorted alphabetically, use prefix before $includes to control includes ordering + # paths should be relative to /etc/nats-config/nats.conf + # example: + # + # merge: + # $include: ./my-config.conf + # zzz$include: ./my-config-last.conf + # server_name: nats + # authorization: + # token: << $TOKEN >> + # jetstream: + # max_memory_store: << 1GB >> + # + # will yield the config: + # { + # include ./my-config.conf; + # "authorization": { + # "token": $TOKEN + # }, + # "jetstream": { + # "max_memory_store": 1GB + # }, + # "server_name": "nats", + # include ./my-config-last.conf; + # } + merge: {} + patch: [] + +############################################################ +# stateful set -> pod template -> nats container +############################################################ +container: + image: + repository: nats + tag: 2.10.22-alpine + pullPolicy: + registry: + + # container port options + # must be enabled in the config section also + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#containerport-v1-core + ports: + nats: {} + leafnodes: {} + websocket: {} + mqtt: {} + cluster: {} + gateway: {} + monitor: {} + profiling: {} + + # map with key as env var name, value can be string or map + # example: + # + # env: + # GOMEMLIMIT: 7GiB + # TOKEN: + # valueFrom: + # secretKeyRef: + # name: nats-auth + # key: token + env: {} + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + +############################################################ +# stateful set -> pod template -> reloader container +############################################################ +reloader: + enabled: true + image: + repository: natsio/nats-server-config-reloader + tag: 0.16.0 + pullPolicy: + registry: + + # env var map, see nats.env for an example + env: {} + + # all nats container volume mounts with the following prefixes + # will be mounted into the reloader container + natsVolumeMountPrefixes: + - /etc/ + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + +############################################################ +# stateful set -> pod template -> prom-exporter container +############################################################ +# config.monitor must be enabled +promExporter: + enabled: false + image: + repository: natsio/prometheus-nats-exporter + tag: 0.15.0 + pullPolicy: + registry: + + port: 7777 + # env var map, see nats.env for an example + env: {} + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + + ############################################################ + # prometheus pod monitor + ############################################################ + podMonitor: + enabled: false + + # merge or patch the pod monitor + # https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitor + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + + +############################################################ +# service +############################################################ +service: + enabled: true + + # service port options + # additional boolean field enable to control whether port is exposed in the service + # must be enabled in the config section also + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceport-v1-core + ports: + nats: + enabled: true + leafnodes: + enabled: true + websocket: + enabled: true + mqtt: + enabled: true + cluster: + enabled: false + gateway: + enabled: false + monitor: + enabled: false + profiling: + enabled: false + + # merge or patch the service + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + +############################################################ +# other nats extension points +############################################################ + +# stateful set +statefulSet: + # merge or patch the stateful set + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#statefulset-v1-apps + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + +# stateful set -> pod template +podTemplate: + # adds a hash of the ConfigMap as a pod annotation + # this will cause the StatefulSet to roll when the ConfigMap is updated + configChecksumAnnotation: true + + # map of topologyKey: topologySpreadConstraint + # labelSelector will be added to match StatefulSet pods + # + # topologySpreadConstraints: + # kubernetes.io/hostname: + # maxSkew: 1 + # + topologySpreadConstraints: {} + + # merge or patch the pod template + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core + merge: {} + patch: [] + +# headless service +headlessService: + # merge or patch the headless service + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-headless" + name: + +# config map +configMap: + # merge or patch the config map + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#configmap-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-config" + name: + +# pod disruption budget +podDisruptionBudget: + enabled: true + # merge or patch the pod disruption budget + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#poddisruptionbudget-v1-policy + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + +# service account +serviceAccount: + enabled: false + # merge or patch the service account + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + + +############################################################ +# natsBox +# +# NATS Box Deployment and associated resources +############################################################ +natsBox: + enabled: true + + ############################################################ + # NATS contexts + ############################################################ + contexts: + default: + creds: + # set contents in order to create a secret with the creds file contents + contents: + # set secretName in order to mount an existing secret to dir + secretName: + # defaults to /etc/nats-creds/ + dir: + key: nats.creds + nkey: + # set contents in order to create a secret with the nkey file contents + contents: + # set secretName in order to mount an existing secret to dir + secretName: + # defaults to /etc/nats-nkeys/ + dir: + key: nats.nk + # used to connect with client certificates + tls: + # set secretName in order to mount an existing secret to dir + secretName: + # defaults to /etc/nats-certs/ + dir: + cert: tls.crt + key: tls.key + + # merge or patch the context + # https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts + merge: {} + patch: [] + + # name of context to select by default + defaultContextName: default + + ############################################################ + # deployment -> pod template -> nats-box container + ############################################################ + container: + image: + repository: natsio/nats-box + tag: 0.14.5 + pullPolicy: + registry: + + # env var map, see nats.env for an example + env: {} + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + + ############################################################ + # other nats-box extension points + ############################################################ + + # deployment + deployment: + # merge or patch the deployment + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#deployment-v1-apps + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box" + name: + + # deployment -> pod template + podTemplate: + # merge or patch the pod template + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core + merge: {} + patch: [] + + # contexts secret + contextsSecret: + # merge or patch the context secret + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box-contexts" + name: + + # contents secret + contentsSecret: + # merge or patch the contents secret + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box-contents" + name: + + # service account + serviceAccount: + enabled: false + # merge or patch the service account + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box" + name: + + +################################################################################ +# Extra user-defined resources +################################################################################ +# +# add arbitrary user-generated resources +# example: +# +# config: +# websocket: +# enabled: true +# extraResources: +# - apiVersion: networking.istio.io/v1beta1 +# kind: VirtualService +# metadata: +# name: +# $tplYaml: > +# {{ include "nats.fullname" $ | quote }} +# labels: +# $tplYaml: | +# {{ include "nats.labels" $ }} +# spec: +# hosts: +# - demo.nats.io +# gateways: +# - my-gateway +# http: +# - name: default +# match: +# - name: root +# uri: +# exact: / +# route: +# - destination: +# host: +# $tplYaml: > +# {{ .Values.service.name | quote }} +# port: +# number: +# $tplYaml: > +# {{ .Values.config.websocket.port }} +# +extraResources: [] diff --git a/utils/assets/charts/openldap/.argo-workflow.yaml b/utils/assets/charts/openldap/.argo-workflow.yaml new file mode 100644 index 0000000..aaa61a6 --- /dev/null +++ b/utils/assets/charts/openldap/.argo-workflow.yaml @@ -0,0 +1,133 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: openldap-qualif- +spec: + entrypoint: test-deployment + arguments: + parameters: + - name: namespace + value: openldap-qualif + - name: app + value: openldap-qualif + # This spec contains two templates: hello-hello-hello and whalesay + templates: + - name: test-deployment + parallelism: 1 + # Instead of just running a container + # This template has a sequence of steps + steps: + - - name: wait-upgrade # hello1 is run before the following steps + template: wait-upgrade + arguments: + parameters: + - name: time + value: 10 + - name: type + value: sts + - - name: test-openldap-upgrade # double dash => run after previous step + template: test-openldap-upgrade + arguments: + parameters: + - name: url + value: "{{workflow.parameters.app}}.{{workflow.parameters.namespace}}" + - name: password + value: "Not@SecurePassw0rd" + - name: user + value: "cn=admin,dc=example,dc=org" + - name: occurence + value: "{{item}}" + withSequence: + count: "1" + - - name: apply-chaos-test # double dash => run after previous step + template: apply-chaos-test + - - name: test-openldap # double dash => run after previous step + template: test-openldap-upgrade + arguments: + parameters: + - name: url + value: "{{workflow.parameters.app}}.{{workflow.parameters.namespace}}" + - name: password + value: "Not@SecurePassw0rd" + - name: user + value: "cn=admin,dc=example,dc=org" + - name: occurence + value: "{{item}}" + withSequence: + count: "60" + - - name: cleanup # double dash => run after previous step + template: pause-chaos-test + + # This is the same template as from the previous example + - name: wait-upgrade + serviceAccountName: argo-workflow-invocator + inputs: + parameters: + - name: time + - name: type # type of resources to wait (deployement or sts) + script: + image: bitnami/kubectl:1.18.13 + command: [/bin/bash] + source: | + sleep {{inputs.parameters.time}} + kubectl rollout status -n {{workflow.parameters.namespace}} {{inputs.parameters.type}} {{workflow.parameters.app}} + - name: test-openldap-upgrade + serviceAccountName: argo-workflow-invocator + inputs: + parameters: + - name: url + - name: password + - name: user + - name: occurence + script: + image: alpine + command: [sh] + source: | # Contents of the here-script + apk add openldap-clients + echo "run ldap commands (add, search, modify...)" + LDAPTLS_REQCERT=never ldapsearch -x -D '{{inputs.parameters.user}}' -w {{inputs.parameters.password}} -H ldaps://{{inputs.parameters.url}} -b 'dc=example,dc=org' + sleep 60 + - name: apply-chaos-test + serviceAccountName: argo-workflow-invocator + resource: # indicates that this is a resource template + action: apply # can be any kubectl action (e.g. create, delete, apply, patch) + manifest: | #put your kubernetes spec here + apiVersion: chaos-mesh.org/v1alpha1 + kind: PodChaos + metadata: + name: pod-failure-openldap + namespace: openldap-qualif + annotations: + experiment.chaos-mesh.org/pause: "false" + spec: + action: pod-failure + mode: random-max-percent + value: "100" + duration: "15s" + selector: + labelSelectors: + "app": "openldap-qualif" + scheduler: + cron: "@every 2m" + - name: pause-chaos-test + serviceAccountName: argo-workflow-invocator + resource: # indicates that this is a resource template + action: apply # can be any kubectl action (e.g. create, delete, apply, patch) + manifest: | #put your kubernetes spec here + apiVersion: chaos-mesh.org/v1alpha1 + kind: PodChaos + metadata: + name: pod-failure-openldap + namespace: openldap-qualif + annotations: + experiment.chaos-mesh.org/pause: "true" + spec: + action: pod-failure + mode: random-max-percent + value: "100" + duration: "15s" + selector: + labelSelectors: + "app": "openldap-qualif" + scheduler: + cron: "@every 2m" \ No newline at end of file diff --git a/utils/assets/charts/openldap/.helmignore b/utils/assets/charts/openldap/.helmignore new file mode 100644 index 0000000..cba8aa4 --- /dev/null +++ b/utils/assets/charts/openldap/.helmignore @@ -0,0 +1,5 @@ +.git +.github +.chaos +.argo-workflow + diff --git a/utils/assets/charts/openldap/Chart.yaml b/utils/assets/charts/openldap/Chart.yaml new file mode 100644 index 0000000..bb0d81b --- /dev/null +++ b/utils/assets/charts/openldap/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +appVersion: 2.4.47 +dependencies: +- condition: ltb-passwd.enabled + name: ltb-passwd + repository: "" + version: 0.1.x +- condition: phpldapadmin.enabled + name: phpldapadmin + repository: "" + version: 0.1.x +description: Community developed LDAP software +home: https://www.openldap.org +icon: http://www.openldap.org/images/headers/LDAPworm.gif +keywords: +- ldap +- openldap +maintainers: +- email: jp-gouin@hotmail.fr + name: Jean-Philippe Gouin +name: openldap +sources: +- https://github.com/kubernetes/charts +version: 2.0.4 diff --git a/utils/assets/charts/openldap/README.md b/utils/assets/charts/openldap/README.md new file mode 100644 index 0000000..56c70f2 --- /dev/null +++ b/utils/assets/charts/openldap/README.md @@ -0,0 +1,167 @@ +# OpenLDAP Helm Chart + +## Prerequisites Details +* Kubernetes 1.8+ +* PV support on the underlying infrastructure + +## Chart Details +This chart will do the following: + +* Instantiate 3 instances of OpenLDAP server with multi-master replication +* A phpldapadmin to administrate the OpenLDAP server +* ltb-passwd for self service password + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```bash +$ git clone https://github.com/jp-gouin/helm-openldap.git +$ cd helm-openldap +$ helm install openldap . +``` + +## Configuration + +We use the docker images provided by https://github.com/osixia/docker-openldap. The docker image is highly configurable and well documented. Please consult to documentation for the docker image for more information. + +The following table lists the configurable parameters of the openldap chart and their default values. + +| Parameter | Description | Default | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `replicaCount` | Number of replicas | `3` | +| `strategy` | Deployment strategy | `{}` | +| `image.repository` | Container image repository | `osixia/openldap` | +| `image.tag` | Container image tag | `1.1.10` | +| `image.pullPolicy` | Container pull policy | `IfNotPresent` | +| `extraLabels` | Labels to add to the Resources | `{}` | +| `podAnnotations` | Annotations to add to the pod | `{}` | +| `existingSecret` | Use an existing secret for admin and config user passwords | `""` | +| `service.annotations` | Annotations to add to the service | `{}` | +| `service.externalIPs` | Service external IP addresses | `[]` | +| `service.ldapPort` | External service port for LDAP | `389` | +| `service.ldapPortNodePort` | Nodeport of External service port for LDAP if service.type is NodePort | `nil` | +| `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` | +| `service.loadBalancerSourceRanges` | List of IP CIDRs allowed access to load balancer (if supported) | `[]` | +| `service.sslLdapPort` | External service port for SSL+LDAP | `636` | +| `service.sslLdapPortNodePort` | Nodeport of External service port for SSL if service.type is NodePort | `nil` | +| `service.type` | Service type can be ClusterIP, NodePort, LoadBalancer | `ClusterIP` | +| `env` | List of key value pairs as env variables to be sent to the docker image. See https://github.com/osixia/docker-openldap for available ones | `[see values.yaml]` | +| `logLevel` | Set the container log level. Valid values: `none`, `error`, `warning`, `info`, `debug`, `trace` | `info` | +| `tls.enabled` | Set to enable TLS/LDAPS with custom certificate - should also set `tls.secret` | `false` | +| `tls.secret` | Secret containing TLS cert and key (eg, generated via cert-manager) | `""` | +| `tls.CA.enabled` | Set to enable custom CA crt file - should also set `tls.CA.secret` | `false` | +| `tls.CA.secret` | Secret containing CA certificate (ca.crt) | `""` | +| `adminPassword` | Password for admin user. Unset to auto-generate the password | None | +| `configPassword` | Password for config user. Unset to auto-generate the password | None | +| `customLdifFiles` | Custom ldif files to seed the LDAP server. List of filename -> data pairs | None | +| `persistence.enabled` | Whether to use PersistentVolumes or not | `false` | +| `persistence.storageClass` | Storage class for PersistentVolumes. | `` | +| `persistence.accessMode` | Access mode for PersistentVolumes | `ReadWriteOnce` | +| `persistence.size` | PersistentVolumeClaim storage size | `8Gi` | +| `resources` | Container resource requests and limits in yaml | `{}` | +| `test.enabled` | Conditionally provision test resources | `false` | +| `test.image.repository` | Test container image requires bats framework | `dduportal/bats` | +| `test.image.tag` | Test container tag | `0.4.0` | +| `replication.enabled` | Enable the multi-master replication | `true` | +| `replication.retry` | retry period for replication in sec | `60` | +| `replication.timeout` | timeout for replication in sec| `1` | +| `replication.starttls` | starttls replication | `critical` | +| `replication.tls_reqcert` | tls certificate validation for replication | `never` | +| `replication.interval` | interval for replication | `00:00:00:10` | +| `replication.clusterName` | Set the clustername for replication | "cluster.local" | +| `phpldapadmin.enabled` | Enable the deployment of PhpLdapAdmin | `true`| +| `phpldapadmin.ingress` | Ingress of Phpldapadmin | `{}` | +| `phpldapadmin.env` | Environment variables for PhpldapAdmin| `{}` | +|`ltb-passwd.enabled`| Enable the deployment of Ltb-Passwd| `true` | +|`ltb-passwd.ingress`| Ingress of the Ltb-Passwd service | `{}` | +|`ltb-passwd.ldap`| Ldap configuration for the Ltb-Passwd service | `{}` | +|`ltb-passwd.env`| Environment variables for ltp-passwd | `{}` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```bash +$ helm install --name my-release -f values.yaml stable/openldap +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + + +## PhpLdapAdmin +To enable PhpLdapAdmin set `phpldapadmin.enabled` to `true` + +Ingress can be configure if you want to expose the service. +Setup the env part of the configuration to access the OpenLdap server + +**Note** : The ldap host should match the following `namespace.Appfullname` + +Example : +``` +phpldapadmin: + enabled: true + ingress: + enabled: true + annotations: {} + path: / + ## Ingress Host + hosts: + - phpldapadmin.local + env: + PHPLDAPADMIN_LDAP_HOSTS: openldap.openldap + +``` +## Self-service-password +To enable Self-service-password set `ltb-passwd.enabled` to `true` + +Ingress can be configure if you want to expose the service. + +Setup the `ldap` part with the information of the OpenLdap server. + +Set `bindDN` accordingly to your ldap domain + +**Note** : The ldap server host should match the following `ldap://namespace.Appfullname` + +Example : +``` +ltb-passwd: + enabled : true + ingress: + enabled: true + annotations: {} + host: "ssl-ldap2.local" + ldap: + server: ldap://openldap.openldap + searchBase: dc=example,dc=org + bindDN: cn=admin,dc=example,dc=org + bindPWKey: LDAP_ADMIN_PASSWORD + +``` + +## Cleanup orphaned Persistent Volumes + +Deleting the Deployment will not delete associated Persistent Volumes if persistence is enabled. + +Do the following after deleting the chart release to clean up orphaned Persistent Volumes. + +```bash +$ kubectl delete pvc -l release=${RELEASE-NAME} +``` + +## Custom Secret + +`existingSecret` can be used to override the default secret.yaml provided + +## Testing + +Helm tests are included and they confirm connection to slapd. + +```bash +helm install . --set test.enabled=true +helm test +RUNNING: foolish-mouse-openldap-service-test-akmms +PASSED: foolish-mouse-openldap-service-test-akmms +``` + +It will confirm that we can do an ldapsearch with the default credentials diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/.helmignore b/utils/assets/charts/openldap/charts/ltb-passwd/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/Chart.yaml b/utils/assets/charts/openldap/charts/ltb-passwd/Chart.yaml new file mode 100644 index 0000000..c7ce2dd --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +appVersion: "1.3" +description: LTB Project Password self service +name: ltb-passwd +version: 0.1.0 diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/README.md b/utils/assets/charts/openldap/charts/ltb-passwd/README.md new file mode 100644 index 0000000..7268afe --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/README.md @@ -0,0 +1,63 @@ +# LTB Password Self Service Helm Chart + +This repository contains the helm chart for the LTB password change webapp. +It is based on several other projects, namely: + +- [LTB Self-Service Password](https://ltb-project.org/documentation/self-service-password) +- [LTB Self-Service Password Github Repo](https://github.com/ltb-project/self-service-password) +- [tiredofit Docker Image for the LTB repo](https://github.com/tiredofit/docker-self-service-password) + +## Prerequisites + +- Kubernetes 1.8+ + +## Chart Details + +This chart will do the following: + +- Instantiate an instance of the LTB LDAP Self-Service Password webapp. + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```bash +$ helm install --name my-release $PATH_TO_THIS_REPO +``` + +## Configuration + +We use this image as base image, please refer to the documentation for specific options. + +- [tiredofit Docker Image for the LTB repo](https://github.com/tiredofit/docker-self-service-password) + +Configuration is done within `values.yaml`: + +| Parameter | Description | Default | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| `ldap.server` | LDAP Server URL, should be of the form: `ldap://ldap.svc:389` | ` ` | +| `ldap.searchBase` | LDAP Search Base for the users | ` ` | +| `ldap.binduserSecret` | Name of an **existing** secret to fetch the credentials for the bind user from. Needs keys `BINDDN` and `BINDPW` | ` ` | +| `env` | List of key value pairs as env variables to be sent to the docker image. See https://github.com/tiredofit/docker-self-service-password for available ones | `[see values.yaml]`| +| `replicaCount` | Number of replicas | `1` | +| `image.repository` | Container image repository | ` tiredofit/self-service-password` | +| `image.tag` | Container image tag | `latest` | +| `image.pullPolicy` | Container pull policy | `Default` | +| `service.port` | External port for the WebApp | `80` | +| `service.type` | Service type | `ClusterIP` | +| `ingress.enabled` | Whether to generate ingress resources | `false` | +| `ingress.annotations` | Annotations to add to the ingress | `{}` | +| `ingress.hosts` | Hostnames to redirect to the webapp | `[]` | +| `ingress.tls` | TLS Configuration | `[]` | +| `resources` | Container resource requests and limits in yaml | `{}` | +| `nodeSelector` | NodeSelector to run the image on | `{}` | +| `tolerations` | Tolerations for the service pod | `[]` | +| `affinity` | Attractions for the service pod | `{}` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```bash +$ helm install --name my-release -f values.yaml $PATH_TO_THIS_REPO +``` \ No newline at end of file diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/templates/NOTES.txt b/utils/assets/charts/openldap/charts/ltb-passwd/templates/NOTES.txt new file mode 100644 index 0000000..f34c0df --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/templates/NOTES.txt @@ -0,0 +1 @@ +Happy password changing :) \ No newline at end of file diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/templates/_helpers.tpl b/utils/assets/charts/openldap/charts/ltb-passwd/templates/_helpers.tpl new file mode 100644 index 0000000..8d544b6 --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "ltb-passwd.name" -}} +{{ default .Release.Name .Values.existingSecret }} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ltb-passwd.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ltb-passwd.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "ltb-passwd.labels" -}} +app.kubernetes.io/name: {{ include "ltb-passwd.name" . }} +helm.sh/chart: {{ include "ltb-passwd.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} +{{/* +Generate chart secret name +*/}} +{{- define "ltb-passwd.secretName" -}} +{{ default (include "ltb-passwd.fullname" .) .Values.existingSecret }} +{{- end -}} diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/templates/deployment.yaml b/utils/assets/charts/openldap/charts/ltb-passwd/templates/deployment.yaml new file mode 100644 index 0000000..2214f01 --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ltb-passwd.fullname" . }} + labels: +{{ include "ltb-passwd.labels" . | indent 4 }} +spec: + replicas: {{ default 1 .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "ltb-passwd.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "ltb-passwd.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: LDAP_SERVER + value: {{ .Values.ldap.server | quote }} + - name: LDAP_BINDDN + value: {{ .Values.ldap.bindDN | quote }} + - name: LDAP_BINDPASS + valueFrom: + secretKeyRef: + name: {{ template "ltb-passwd.secretName" . }} + key: {{ .Values.ldap.bindPWKey }} + - name: LDAP_STARTTLS + value: "false" + - name: LDAP_BASE_SEARCH + value: {{ .Values.ldap.searchBase | quote }} + {{- with .Values.env }} + {{- toYaml . | nindent 10 }} + {{- end }} + ports: + - name: http + containerPort: 80 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/templates/ingress.yaml b/utils/assets/charts/openldap/charts/ltb-passwd/templates/ingress.yaml new file mode 100644 index 0000000..e0db442 --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/templates/ingress.yaml @@ -0,0 +1,38 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ltb-passwd.fullname" . -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "ltb-passwd.name" . }} + chart: {{ template "ltb-passwd.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $fullName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/templates/service.yaml b/utils/assets/charts/openldap/charts/ltb-passwd/templates/service.yaml new file mode 100644 index 0000000..2553c15 --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ltb-passwd.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "ltb-passwd.name" . }} + helm.sh/chart: {{ include "ltb-passwd.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "ltb-passwd.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/utils/assets/charts/openldap/charts/ltb-passwd/values.yaml b/utils/assets/charts/openldap/charts/ltb-passwd/values.yaml new file mode 100644 index 0000000..be6064c --- /dev/null +++ b/utils/assets/charts/openldap/charts/ltb-passwd/values.yaml @@ -0,0 +1,51 @@ +# Default values for ltb-passwd. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: tiredofit/self-service-password + tag: latest + pullPolicy: Always + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +service: + type: ClusterIP + port: 80 +ingress: + enabled: true + annotations: {} + host: "ssl-ldap.local" +## Configure Ingress based on the documentation here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +ingress: + enabled: false + annotations: {} + path: / + ## Ingress Host + # hosts: + # - ssl-ldap.local + # + tls: [] + # tls: + # - secretName: ssl-ldap-dedicated-tls + # hosts: + # - ssl-ldap.local +resources: {} +nodeSelector: {} +tolerations: [] +affinity: {} +ldap: + server: ldap://openldap.openldap + searchBase: dc=example,dc=org + # existingSecret: ssp-ldap + bindDN: cn=admin,dc=example,dc=org + bindPWKey: BINDPW +env: +- name: SECRETEKEY + value: "password" +- name: LDAP_LOGIN_ATTRIBUTE + value: "cn" \ No newline at end of file diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/Chart.yaml b/utils/assets/charts/openldap/charts/phpldapadmin/Chart.yaml new file mode 100644 index 0000000..5aa344f --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +appVersion: 0.7.1 +description: Web-based LDAP browser to manage your LDAP server +home: http://phpldapadmin.sourceforge.net +icon: http://phpldapadmin.sourceforge.net/wiki/images/d/d4/Logo.jpg +keywords: +- phpldapadmin +- openldap +- userrights +maintainers: +- name: Jean-Philippe Gouin +name: phpldapadmin +version: 0.1.2 diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/README.md b/utils/assets/charts/openldap/charts/phpldapadmin/README.md new file mode 100644 index 0000000..313fc0c --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/README.md @@ -0,0 +1,107 @@ +# Helm Chart for phpLDAPadmin + +[![CircleCI](https://circleci.com/gh/cetic/helm-phpLDAPadmin.svg?style=svg)](https://circleci.com/gh/cetic/helm-phpLDAPadmin/tree/master) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![version](https://img.shields.io/github/tag/cetic/helm-phpLDAPadmin.svg?label=release) + +## Introduction + +This [Helm](https://github.com/kubernetes/helm) chart installs [phpLDAPadmin](http://phpldapadmin.sourceforge.net/wiki/index.php/Main_Page) in a Kubernetes cluster. + +## Prerequisites + +- Kubernetes cluster 1.10+ +- Helm 2.8.0+ +- PV provisioner support in the underlying infrastructure. + +## Installation + +### Add Helm repository + +```bash +helm repo add cetic https://cetic.github.io/helm-charts +helm repo update +``` + +### Configure the chart + +The following items can be set via `--set` flag during installation or configured by editing the `values.yaml` directly (you need to download the chart first). + +#### Configure the way how to expose phpLDAPadmin service: + +- **Ingress**: The ingress controller must be installed in the Kubernetes cluster. +- **ClusterIP**: Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. +- **NodePort**: Exposes the service on each Node’s IP at a static port (the NodePort). You’ll be able to contact the NodePort service, from outside the cluster, by requesting `NodeIP:NodePort`. +- **LoadBalancer**: Exposes the service externally using a cloud provider’s load balancer. + +#### Configure how to persist data (TODO): + +- **Disable**: The data does not survive the termination of a pod. +- **Persistent Volume Claim(default)**: A default `StorageClass` is needed in the Kubernetes cluster to dynamic provision the volumes. Specify another StorageClass in the `storageClass` or set `existingClaim` if you have already existing persistent volumes to use. + +### Install the chart + +Install the phpLDAPadmin helm chart with a release name `my-release`: + +```bash +helm install --name my-release cetic/phpldapadmin +``` + +## Uninstallation + +To uninstall/delete the `my-release` deployment: + +```bash +helm delete --purge my-release +``` + +## Configuration + +The following table lists the configurable parameters of the phpLDAPadmin chart and the default values. + +| Parameter | Description | Default | +| --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------| ------------------------------- | +| **ReplicaCount** | +| `replicaCount` | number of phpLDAPadmin images | `1` | +| **Env** | +| `env` | See values.yaml | `nil` | +| **Image** | +| `image.repository` | phpldapadmin Image name | `osixia/phpldapadmin` | +| `image.tag` | phpldapadmin Image tag | `0.7.1` | +| `image.pullPolicy` | phpldapadmin Image pull policy | `IfNotPresent` | +| **Service** | +| `service.type` | Type of service for phpldapadmin frontend | `LoadBalancer` | +| `service.port` | Port to expose service | `80` | +| `service.loadBalancerIP` | LoadBalancerIP if service type is `LoadBalancer` | `nil` | +| `service.loadBalancerSourceRanges` | LoadBalancerSourceRanges | `nil` | +| `service.annotations` | Service annotations | `{}` | +| **Ingress** | +| `ingress.enabled` | Enables Ingress | `false` | +| `ingress.annotations` | Ingress annotations | `{}` | +| `ingress.path` | Path to access frontend | `/` | +| `ingress.hosts` | Ingress hosts | `nil` | +| `ingress.tls` | Ingress TLS configuration | `[]` | +| **ReadinessProbe** | +| `readinessProbe` | Rediness Probe settings | `{ "httpGet": { "path": "/", "port": http }}`| +| **LivenessProbe** | +| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/", "port": http }}`| +| **Resources** | +| `resources` | CPU/Memory resource requests/limits | `{}` | +| **nodeSelector** | +| `nodeSelector` | nodeSelector | `{}` | +| **tolerations** | +| `tolerations` | tolerations | `{}` | +| **affinity** | +| `affinity` | affinity | `{}` | + +## Credits + +Initially inspired from https://github.com/gengen1988/helm-phpldapadmin. + +## Contributing + +Feel free to contribute by making a [pull request](https://github.com/cetic/helm-phpLDAPadmin/pull/new/master). + +Please read the official [Contribution Guide](https://github.com/helm/charts/blob/master/CONTRIBUTING.md) from Helm for more information on how you can contribute to this Chart. + +## License + +[Apache License 2.0](/LICENSE) diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/publish.sh b/utils/assets/charts/openldap/charts/phpldapadmin/publish.sh new file mode 100644 index 0000000..2202e25 --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/publish.sh @@ -0,0 +1,84 @@ +#!/bin/sh +set -e +set -o pipefail + +WORKING_DIRECTORY="$PWD" + +[ "$GITHUB_PAGES_REPO" ] || { + echo "ERROR: Environment variable GITHUB_PAGES_REPO is required" + exit 1 +} +[ "$HELM_CHART" ] || { + echo "ERROR: Environment variable HELM_CHART is required" + exit 1 +} +[ -z "$GITHUB_PAGES_BRANCH" ] && GITHUB_PAGES_BRANCH=gh-pages +[ -z "$HELM_CHARTS_SOURCE" ] && HELM_CHARTS_SOURCE="$WORKING_DIRECTORY/$HELM_CHART" +[ -d "$WORKING_DIRECTORY" ] || { + echo "ERROR: Could not find Helm charts in $WORKING_DIRECTORY" + exit 1 +} +[ -z "$HELM_VERSION" ] && HELM_VERSION=2.8.1 +[ "$CIRCLE_BRANCH" ] || { + echo "ERROR: Environment variable CIRCLE_BRANCH is required" + exit 1 +} + +echo "GITHUB_PAGES_REPO=$GITHUB_PAGES_REPO" +echo "GITHUB_PAGES_BRANCH=$GITHUB_PAGES_BRANCH" +echo "HELM_CHARTS_SOURCE=$HELM_CHARTS_SOURCE" +echo "HELM_VERSION=$HELM_VERSION" +echo "CIRCLE_BRANCH=$CIRCLE_BRANCH" + +echo ">>> Create Chart Directory" + +mkdir -p $HELM_CHARTS_SOURCE/ +mkdir -p /tmp/helm-tmp/ + +mv $WORKING_DIRECTORY/* /tmp/helm-tmp/ +mv /tmp/helm-tmp/ $HELM_CHARTS_SOURCE/ + +echo '>> Prepare...' +mkdir -p /tmp/helm/bin +mkdir -p /tmp/helm/publish +apk update +apk add ca-certificates git openssh + +echo '>> Installing Helm...' +cd /tmp/helm/bin +wget "https://storage.googleapis.com/kubernetes-helm/helm-v${HELM_VERSION}-linux-amd64.tar.gz" +tar -zxf "helm-v${HELM_VERSION}-linux-amd64.tar.gz" +chmod +x linux-amd64/helm +alias helm=/tmp/helm/bin/linux-amd64/helm +helm version -c +helm init -c + +echo ">> Checking out $GITHUB_PAGES_BRANCH branch from $GITHUB_PAGES_REPO" +cd /tmp/helm/publish +mkdir -p "$HOME/.ssh" +ssh-keyscan -H github.com >> "$HOME/.ssh/known_hosts" +git clone -b "$GITHUB_PAGES_BRANCH" "git@github.com:$GITHUB_PAGES_REPO.git" . + +echo '>> Building chart...' +echo ">>> helm lint $HELM_CHARTS_SOURCE" +helm lint "$HELM_CHARTS_SOURCE" +echo ">>> helm package -d $HELM_CHART $HELM_CHARTS_SOURCE" +mkdir -p "$HELM_CHART" +helm package -d "$HELM_CHART" "$HELM_CHARTS_SOURCE" + +echo '>>> helm repo index' +helm repo index . + +if [ "$CIRCLE_BRANCH" != "master" ]; then + echo "Current branch is not master and do not publish" + exit 0 +fi + +echo ">> Publishing to $GITHUB_PAGES_BRANCH branch of $GITHUB_PAGES_REPO" +git config user.email "$CIRCLE_USERNAME@users.noreply.github.com" +git config user.name CircleCI +git add . +git status +git commit -m "Published by CircleCI $CIRCLE_BUILD_URL" +git push origin "$GITHUB_PAGES_BRANCH" + diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/templates/NOTES.txt b/utils/assets/charts/openldap/charts/phpldapadmin/templates/NOTES.txt new file mode 100644 index 0000000..3f71475 --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/templates/NOTES.txt @@ -0,0 +1,26 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + You should be able to access your new phpLDAPadmin installation through + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} + + Find out your cluster ip address by running: + $ kubectl cluster-info + +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "phpldapadmin.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "phpldapadmin.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "phpldapadmin.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "phpldapadmin.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl port-forward $POD_NAME 8080:80 +{{- end }} + +** Please be patient while the chart is being deployed ** diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/templates/_helpers.tpl b/utils/assets/charts/openldap/charts/phpldapadmin/templates/_helpers.tpl new file mode 100644 index 0000000..81f00c4 --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/templates/_helpers.tpl @@ -0,0 +1,32 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "phpldapadmin.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "phpldapadmin.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "phpldapadmin.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/templates/configmap.yaml b/utils/assets/charts/openldap/charts/phpldapadmin/templates/configmap.yaml new file mode 100644 index 0000000..9af005d --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/templates/configmap.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "phpldapadmin.fullname" . }} + labels: + app: {{ template "phpldapadmin.name" . }} + chart: {{ template "phpldapadmin.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +data: +{{ toYaml .Values.env | indent 2 }} diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/templates/deployment.yaml b/utils/assets/charts/openldap/charts/phpldapadmin/templates/deployment.yaml new file mode 100644 index 0000000..4c64b8a --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/templates/deployment.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment + +metadata: + name: {{ template "phpldapadmin.fullname" . }} + labels: + app: {{ template "phpldapadmin.name" . }} + chart: {{ template "phpldapadmin.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ template "phpldapadmin.name" . }} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ template "phpldapadmin.name" . }} + release: {{ .Release.Name }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + envFrom: + - configMapRef: + name: {{ template "phpldapadmin.fullname" . }} + livenessProbe: +{{ toYaml .Values.livenessProbe | indent 12 }} + readinessProbe: +{{ toYaml .Values.readinessProbe | indent 12 }} + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/templates/ingress.yaml b/utils/assets/charts/openldap/charts/phpldapadmin/templates/ingress.yaml new file mode 100644 index 0000000..5791b76 --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/templates/ingress.yaml @@ -0,0 +1,38 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "phpldapadmin.fullname" . -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "phpldapadmin.name" . }} + chart: {{ template "phpldapadmin.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $fullName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/templates/service.yaml b/utils/assets/charts/openldap/charts/phpldapadmin/templates/service.yaml new file mode 100644 index 0000000..a86e130 --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/templates/service.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "phpldapadmin.fullname" . }} + labels: + app: {{ template "phpldapadmin.name" . }} + chart: {{ template "phpldapadmin.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.service.annotations }} + annotations: +{{ toYaml .Values.service.annotations | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and .Values.service.loadBalancerIP (eq .Values.service.type "LoadBalancer") }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{ with .Values.service.loadBalancerSourceRanges }} +{{ toYaml . | indent 4 }} +{{- end }} + {{- end }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app: {{ template "phpldapadmin.name" . }} + release: {{ .Release.Name }} diff --git a/utils/assets/charts/openldap/charts/phpldapadmin/values.yaml b/utils/assets/charts/openldap/charts/phpldapadmin/values.yaml new file mode 100644 index 0000000..31e9e84 --- /dev/null +++ b/utils/assets/charts/openldap/charts/phpldapadmin/values.yaml @@ -0,0 +1,94 @@ +--- +# Default values for phpldapadmin. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +## TODO: add this in the deployment.yaml +env: + # PHPLDAPADMIN_LDAP_HOSTS: ... + PHPLDAPADMIN_HTTPS: "false" + PHPLDAPADMIN_TRUST_PROXY_SSL: "true" + +## Number of phpLDAPadmin images +replicaCount: 1 + +## Set default image, imageTag, and imagePullPolicy. mode is used to indicate the +## +image: + repository: osixia/phpldapadmin + tag: 0.9.0 + pullPolicy: IfNotPresent + + +## Enable persistence using Persistent Volume Claims +## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +## + +## TODO persistence + +## Expose the pgAdmin service to be accessed from outside the cluster (LoadBalancer service). +## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. +## ref: http://kubernetes.io/docs/user-guide/services/ +## +service: + type: ClusterIP + ## name: phpldapadmin + port: 80 + annotations: {} + + ## Set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + # loadBalancerIP: + + ## Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + # loadBalancerSourceRanges: + # - 10.10.10.0/24 + +## Configure Ingress based on the documentation here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +## +ingress: + enabled: false + annotations: {} + path: / + ## Ingress Host + # hosts: + # - phpldapadmin.example.org + # + tls: [] + # tls: + # - secretName: phpldapadmin-dedicated-tls + # hosts: + # - phpldapadmin.example.org + +## Configure liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ +## +readinessProbe: + httpGet: + path: / + port: http +livenessProbe: + httpGet: + path: / + port: http + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/utils/assets/charts/openldap/templates/NOTES.txt b/utils/assets/charts/openldap/templates/NOTES.txt new file mode 100644 index 0000000..6f29baf --- /dev/null +++ b/utils/assets/charts/openldap/templates/NOTES.txt @@ -0,0 +1,20 @@ +OpenLDAP has been installed. You can access the server from within the k8s cluster using: + + {{ template "openldap.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.ldapPort }} + + +You can access the LDAP adminPassword and configPassword using: + + kubectl get secret --namespace {{ .Release.Namespace }} {{ template "openldap.secretName" . }} -o jsonpath="{.data.LDAP_ADMIN_PASSWORD}" | base64 --decode; echo + kubectl get secret --namespace {{ .Release.Namespace }} {{ template "openldap.secretName" . }} -o jsonpath="{.data.LDAP_CONFIG_PASSWORD}" | base64 --decode; echo + + +You can access the LDAP service, from within the cluster (or with kubectl port-forward) with a command like (replace password and domain): + ldapsearch -x -H ldap://{{ template "openldap.fullname" . }}-service.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.ldapPort }} -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w $LDAP_ADMIN_PASSWORD + + +Test server health using Helm test: + helm test {{ .Release.Name }} + + +You can also consider installing the helm chart for phpldapadmin to manage this instance of OpenLDAP, or install Apache Directory Studio, and connect using kubectl port-forward. diff --git a/utils/assets/charts/openldap/templates/_helpers.tpl b/utils/assets/charts/openldap/templates/_helpers.tpl new file mode 100644 index 0000000..35b1825 --- /dev/null +++ b/utils/assets/charts/openldap/templates/_helpers.tpl @@ -0,0 +1,74 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "openldap.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "openldap.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "openldap.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{/* +Generate chart secret name +*/}} +{{- define "openldap.secretName" -}} +{{ default (include "openldap.fullname" .) .Values.existingSecret }} +{{- end -}} +{{/* +Generate replication services list +*/}} +{{- define "replicalist" -}} +{{- $name := (include "openldap.fullname" .) }} +{{- $namespace := .Release.Namespace }} +{{- $cluster := .Values.replication.clusterName }} +{{- $nodeCount := .Values.replicaCount | int }} + {{- range $index0 := until $nodeCount -}} + {{- $index1 := $index0 | add1 -}} +'ldap://{{ $name }}-{{ $index0 }}.{{ $name }}-headless.{{ $namespace }}.svc.{{ $cluster }}'{{ if ne $index1 $nodeCount }},{{ end }} + {{- end -}} +{{- end -}} +{{/* +Renders a value that contains template. +Usage: +{{ include "openldap.tplValue" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "openldap.tplValue" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/utils/assets/charts/openldap/templates/configmap-customldif.yaml b/utils/assets/charts/openldap/templates/configmap-customldif.yaml new file mode 100644 index 0000000..f060d1d --- /dev/null +++ b/utils/assets/charts/openldap/templates/configmap-customldif.yaml @@ -0,0 +1,23 @@ +# +# A ConfigMap spec for openldap slapd that map directly to files under +# /container/service/slapd/assets/config/bootstrap/ldif/custom +# +{{- if .Values.customLdifFiles }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "openldap.fullname" . }}-customldif + labels: + app: {{ template "openldap.name" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +data: +{{- range $key, $val := .Values.customLdifFiles }} + {{ $key }}: |- +{{ $val | indent 4}} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/openldap/templates/configmap-env.yaml b/utils/assets/charts/openldap/templates/configmap-env.yaml new file mode 100644 index 0000000..df4783c --- /dev/null +++ b/utils/assets/charts/openldap/templates/configmap-env.yaml @@ -0,0 +1,26 @@ +# +# A ConfigMap spec for openldap slapd that map directly to env variables in the Pod. +# List of environment variables supported is from the docker image: +# https://github.com/osixia/docker-openldap#beginner-guide +# Note that passwords are defined as secrets +# +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "openldap.fullname" . }}-env + labels: + app: {{ template "openldap.name" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +data: +{{ toYaml .Values.env | indent 2 }} +{{- if .Values.replication.enabled }} + LDAP_REPLICATION: "true" + LDAP_REPLICATION_CONFIG_SYNCPROV: "binddn=\"cn=admin,cn=config\" bindmethod=simple credentials=$LDAP_CONFIG_PASSWORD searchbase=\"cn=config\" type=refreshAndPersist retry=\"{{.Values.replication.retry }} +\" timeout={{.Values.replication.timeout }} starttls={{.Values.replication.starttls }} tls_reqcert={{.Values.replication.tls_reqcert }}" + LDAP_REPLICATION_DB_SYNCPROV: "binddn=\"cn=admin,$LDAP_BASE_DN\" bindmethod=simple credentials=$LDAP_ADMIN_PASSWORD searchbase=\"$LDAP_BASE_DN\" type=refreshAndPersist interval={{.Values.replication.interval }} retry=\"{{.Values.replication.retry }} +\" timeout={{.Values.replication.timeout }} starttls={{.Values.replication.starttls }} tls_reqcert={{.Values.replication.tls_reqcert }}" + LDAP_REPLICATION_HOSTS: "#PYTHON2BASH:[{{ template "replicalist" . }}]" +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/openldap/templates/secret-ltb.yaml b/utils/assets/charts/openldap/templates/secret-ltb.yaml new file mode 100644 index 0000000..3c85a5e --- /dev/null +++ b/utils/assets/charts/openldap/templates/secret-ltb.yaml @@ -0,0 +1,17 @@ +{{ if not .Values.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "openldap.fullname" . }}-ltb-passwd + labels: + app: {{ template "openldap.name" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +type: Opaque +data: + LDAP_ADMIN_PASSWORD: {{ .Values.adminPassword | b64enc | quote }} +{{ end }} diff --git a/utils/assets/charts/openldap/templates/secret.yaml b/utils/assets/charts/openldap/templates/secret.yaml new file mode 100644 index 0000000..3963ffd --- /dev/null +++ b/utils/assets/charts/openldap/templates/secret.yaml @@ -0,0 +1,18 @@ +{{ if not .Values.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "openldap.fullname" . }} + labels: + app: {{ template "openldap.name" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +type: Opaque +data: + LDAP_ADMIN_PASSWORD: {{ .Values.adminPassword | b64enc | quote }} + LDAP_CONFIG_PASSWORD: {{ .Values.configPassword | b64enc | quote }} +{{ end }} diff --git a/utils/assets/charts/openldap/templates/service.yaml b/utils/assets/charts/openldap/templates/service.yaml new file mode 100644 index 0000000..70657c5 --- /dev/null +++ b/utils/assets/charts/openldap/templates/service.yaml @@ -0,0 +1,47 @@ +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.service.annotations }} + annotations: +{{ toYaml .Values.service.annotations | indent 4 }} +{{- end }} + name: {{ template "openldap.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "openldap.fullname" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: {{ toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + ports: + - name: ldap-port + protocol: TCP + port: {{ .Values.service.ldapPort }} + targetPort: ldap-port + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort)) }} + nodePort: {{ .Values.service.ldapPortNodePort }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: ssl-ldap-port + protocol: TCP + port: {{ .Values.service.sslLdapPort }} + targetPort: ssl-ldap-port + {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort)) }} + nodePort: {{ .Values.service.sslLdapPortNodePort }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + selector: + app: {{ template "openldap.fullname" . }} + release: {{ .Release.Name }} diff --git a/utils/assets/charts/openldap/templates/statefullset.yaml b/utils/assets/charts/openldap/templates/statefullset.yaml new file mode 100644 index 0000000..2e8afd0 --- /dev/null +++ b/utils/assets/charts/openldap/templates/statefullset.yaml @@ -0,0 +1,153 @@ +apiVersion: {{ template "statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ template "openldap.fullname" . }} + labels: + app: {{ template "openldap.fullname" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.replicaCount }} +{{- if .Values.strategy }} + strategy: +{{ toYaml .Values.strategy | indent 4 }} +{{- end }} + selector: + matchLabels: + app: {{ template "openldap.fullname" . }} + release: {{ .Release.Name }} + serviceName: {{ template "openldap.fullname" . }}-headless + template: + metadata: + annotations: + checksum/configmap-env: {{ include (print $.Template.BasePath "/configmap-env.yaml") . | sha256sum }} +{{- if .Values.customLdifFiles}} + checksum/configmap-customldif: {{ include (print $.Template.BasePath "/configmap-customldif.yaml") . | sha256sum }} +{{- end }} +{{- if .Values.podAnnotations}} +{{ toYaml .Values.podAnnotations | indent 8}} +{{- end }} + labels: + app: {{ template "openldap.fullname" . }} + release: {{ .Release.Name }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - -l + - {{ .Values.logLevel }} +{{- if .Values.customLdifFiles }} + - --copy-service +{{- end }} + ports: + - name: ldap-port + containerPort: 389 + - name: ssl-ldap-port + containerPort: 636 + envFrom: + - configMapRef: + name: {{ template "openldap.fullname" . }}-env + - secretRef: + name: {{ template "openldap.secretName" . }} + volumeMounts: + - name: data + mountPath: /var/lib/ldap + subPath: data + - name: data + mountPath: /etc/ldap/slapd.d + subPath: config-data + - name: data + mountPath: /container/service/slapd/assets/certs +{{- if .Values.customLdifFiles }} + - name: custom-ldif-files + mountPath: /container/service/slapd/assets/config/bootstrap/ldif/custom +{{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + #- name: HOSTNAME + # value: $(POD_NAME).{{ template "openldap.fullname" . }}-headless + {{- if .Values.tls.enabled }} + - name: LDAP_TLS_CRT_FILENAME + value: tls.crt + - name: LDAP_TLS_KEY_FILENAME + value: tls.key + {{- if .Values.tls.CA.enabled }} + - name: LDAP_TLS_CA_CRT_FILENAME + value: ca.crt + {{- end }} + {{- end }} + livenessProbe: + tcpSocket: + port: ldap-port + initialDelaySeconds: 20 + periodSeconds: 10 + failureThreshold: 10 + readinessProbe: + tcpSocket: + port: ldap-port + initialDelaySeconds: 20 + periodSeconds: 10 + failureThreshold: 10 + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + app.kubernetes.io/component: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + imagePullSecrets: + - name: {{ .Values.image.pullSecret }} +{{- if .Values.customLdifFiles }} + volumes: + - name: custom-ldif-files + configMap: + name: {{ template "openldap.fullname" . }}-customldif +{{- end }} +{{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + annotations: + {{- range $key, $value := .Values.persistence.annotations }} + {{ $key }}: {{ $value }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" + {{- end }} +{{- end }} +{{- else }} + - name: data + emptyDir: {} +{{- end }} diff --git a/utils/assets/charts/openldap/templates/svc-headless.yaml b/utils/assets/charts/openldap/templates/svc-headless.yaml new file mode 100644 index 0000000..4d9d836 --- /dev/null +++ b/utils/assets/charts/openldap/templates/svc-headless.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "openldap.fullname" . }}-headless + labels: + app: {{ template "openldap.fullname" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + ports: + - port: {{ .Values.service.ldapPort }} + name: ldap-port + targetPort: ldap-port + clusterIP: None + selector: + app: {{ template "openldap.fullname" . }} + release: {{ .Release.Name }} + type: ClusterIP + sessionAffinity: None \ No newline at end of file diff --git a/utils/assets/charts/openldap/templates/tests/openldap-test-runner.yaml b/utils/assets/charts/openldap/templates/tests/openldap-test-runner.yaml new file mode 100644 index 0000000..cfcaf21 --- /dev/null +++ b/utils/assets/charts/openldap/templates/tests/openldap-test-runner.yaml @@ -0,0 +1,50 @@ +{{- if .Values.test.enabled -}} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ template "openldap.fullname" . }}-test-{{ randAlphaNum 5 | lower }}" + labels: + app: {{ template "openldap.name" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} + annotations: + "helm.sh/hook": test-success +spec: + initContainers: + - name: test-framework + image: {{ .Values.test.image.repository }}:{{ .Values.test.image.tag }} + command: + - "bash" + - "-c" + - | + set -ex + # copy bats to tools dir + cp -R /usr/local/libexec/ /tools/bats/ + volumeMounts: + - mountPath: /tools + name: tools + containers: + - name: {{ .Release.Name }}-test + image: {{ .Values.test.image.repository }}:{{ .Values.test.image.tag }} + envFrom: + - secretRef: + name: {{ template "openldap.secretName" . }} + command: ["/tools/bats/bats", "-t", "/tests/run.sh"] + volumeMounts: + - mountPath: /tests + name: tests + readOnly: true + - mountPath: /tools + name: tools + volumes: + - name: tests + configMap: + name: {{ template "openldap.fullname" . }}-tests + - name: tools + emptyDir: {} + restartPolicy: Never +{{- end -}} diff --git a/utils/assets/charts/openldap/templates/tests/openldap-tests.yaml b/utils/assets/charts/openldap/templates/tests/openldap-tests.yaml new file mode 100644 index 0000000..1cdeb80 --- /dev/null +++ b/utils/assets/charts/openldap/templates/tests/openldap-tests.yaml @@ -0,0 +1,22 @@ +{{- if .Values.test.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "openldap.fullname" . }}-tests + labels: + app: {{ template "openldap.name" . }} + chart: {{ template "openldap.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels | indent 4 }} +{{- end }} +data: + run.sh: |- + @test "Testing connecting to slapd server" { + # Ideally, this should be in the docker image, but there is not a generic image we can use + # with bats and ldap-utils installed. It is not worth for now to push an image for this. + apt-get update && apt-get install -y ldap-utils + ldapsearch -x -H ldap://{{ template "openldap.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.ldapPort }} -b "dc=example,dc=org" -D "cn=admin,dc=example,dc=org" -w $LDAP_ADMIN_PASSWORD + } +{{- end -}} diff --git a/utils/assets/charts/openldap/values.yaml b/utils/assets/charts/openldap/values.yaml new file mode 100644 index 0000000..bc184ae --- /dev/null +++ b/utils/assets/charts/openldap/values.yaml @@ -0,0 +1,179 @@ +# Default values for openldap. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 3 +# Define deployment strategy - IMPORTANT: use rollingUpdate: null when use Recreate strategy. +# It prevents from merging with existing map keys which are forbidden. +strategy: {} + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 0 + # + # or + # + # type: Recreate + # rollingUpdate: null +image: + # From repository https://github.com/osixia/docker-openldap + repository: osixia/openldap + tag: 1.4.0 + pullPolicy: Always + pullSecret: harbor + +# Set the container log level +# Valid log levels: none, error, warning, info (default), debug, trace +logLevel: info + +# Spcifies an existing secret to be used for admin and config user passwords +existingSecret: "" +# settings for enabling TLS with custom certificate +tls: + enabled: true + secret: "" # The name of a kubernetes.io/tls type secret to use for TLS + CA: + enabled: false + secret: "" # The name of a generic secret to use for custom CA certificate (ca.crt) +## Add additional labels to all resources +extraLabels: {} +## Add additional annotations to pods +podAnnotations: {} +service: + annotations: {} + + ldapPort: 389 + sslLdapPort: 636 + + ## If service type NodePort, define the value here + #ldapPortNodePort: + #sslLdapPortNodePort: + ## List of IP addresses at which the service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + #loadBalancerIP: + #loadBalancerSourceRanges: [] + type: ClusterIP + +# Default configuration for openldap as environment variables. These get injected directly in the container. +# Use the env variables from https://github.com/osixia/docker-openldap#beginner-guide +env: + LDAP_LOG_LEVEL: "256" + LDAP_ORGANISATION: "Example Inc." + LDAP_DOMAIN: "example.org" + LDAP_READONLY_USER: "false" + LDAP_READONLY_USER_USERNAME: "readonly" + LDAP_READONLY_USER_PASSWORD: "readonly" + LDAP_RFC2307BIS_SCHEMA: "false" + LDAP_BACKEND: "mdb" + LDAP_TLS: "true" + LDAP_TLS_CRT_FILENAME: "ldap.crt" + LDAP_TLS_KEY_FILENAME: "ldap.key" + LDAP_TLS_DH_PARAM_FILENAME: "dhparam.pem" + LDAP_TLS_CA_CRT_FILENAME: "ca.crt" + LDAP_TLS_ENFORCE: "false" + CONTAINER_LOG_LEVEL: "4" + LDAP_TLS_REQCERT: "never" + KEEP_EXISTING_CONFIG: "false" + LDAP_REMOVE_CONFIG_AFTER_SETUP: "true" + LDAP_SSL_HELPER_PREFIX: "ldap" + LDAP_TLS_VERIFY_CLIENT: "never" + LDAP_TLS_PROTOCOL_MIN: "3.0" + LDAP_TLS_CIPHER_SUITE: "NORMAL" + + + +# Default Passwords to use, stored as a secret. +# You can override these at install time with +# helm install openldap --set openldap.adminPassword=,openldap.configPassword= +adminPassword: Not@SecurePassw0rd +configPassword: Not@SecurePassw0rd + +# Custom openldap configuration files used to override default settings +# customLdifFiles: + # 01-default-users.ldif: |- + # Predefine users here +replication: + enabled: true + # Enter the name of your cluster, defaults to "cluster.local" + clusterName: "cluster.local" + retry: 60 + timeout: 1 + interval: 00:00:00:10 + starttls: "critical" + tls_reqcert: "never" +## Persist data to a persistent volume +persistence: + enabled: true + ## database data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "standard-singlewriter" + accessModes: + - ReadWriteOnce + size: 8Gi + +resources: {} + # requests: + # cpu: "100m" + # memory: "256Mi" + # limits: + # cpu: "500m" + # memory: "512Mi" + +nodeSelector: {} + +tolerations: [] + + +## test container details +test: + enabled: false + image: + repository: dduportal/bats + tag: 0.4.0 +ltb-passwd: + enabled : true + ingress: + enabled: true + annotations: {} + path: / + ## Ingress Host + hosts: + - "ssl-ldap2.example" + ldap: + server: ldap://openldap + searchBase: dc=example,dc=org + # existingSecret: openldaptest + bindDN: cn=admin,dc=example,dc=org + bindPWKey: LDAP_ADMIN_PASSWORD + +phpldapadmin: + enabled: true + ingress: + enabled: true + annotations: {} + path: / + ## Ingress Host + hosts: + - phpldapadmin.example + env: + PHPLDAPADMIN_LDAP_HOSTS: openldap + # TODO make it works + # "#PYTHON2BASH: + # [{'openldap.openldap': + # [{'server': [ + # {'tls': False}, + # {'port':636} + # ]}, + # {'login': + # [{'bind_id': 'cn=admin,dc=example,dc=org'}] + # }] + # }]" + \ No newline at end of file diff --git a/utils/assets/charts/prometheus/.helmignore b/utils/assets/charts/prometheus/.helmignore new file mode 100644 index 0000000..eaeaf7a --- /dev/null +++ b/utils/assets/charts/prometheus/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj + +ci/ +OWNERS diff --git a/utils/assets/charts/prometheus/Chart.lock b/utils/assets/charts/prometheus/Chart.lock new file mode 100644 index 0000000..1bbfc92 --- /dev/null +++ b/utils/assets/charts/prometheus/Chart.lock @@ -0,0 +1,15 @@ +dependencies: +- name: alertmanager + repository: https://prometheus-community.github.io/helm-charts + version: 1.28.0 +- name: kube-state-metrics + repository: https://prometheus-community.github.io/helm-charts + version: 6.4.1 +- name: prometheus-node-exporter + repository: https://prometheus-community.github.io/helm-charts + version: 4.49.1 +- name: prometheus-pushgateway + repository: https://prometheus-community.github.io/helm-charts + version: 3.4.2 +digest: sha256:fedbc59b33be92cc31268269ffcd55336a21d62e3b9ae3874e99f4ca63479991 +generated: "2025-11-04T21:27:16.796331119Z" diff --git a/utils/assets/charts/prometheus/Chart.yaml b/utils/assets/charts/prometheus/Chart.yaml new file mode 100644 index 0000000..deb7a74 --- /dev/null +++ b/utils/assets/charts/prometheus/Chart.yaml @@ -0,0 +1,58 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts + - name: Upstream Project + url: https://github.com/prometheus/prometheus +apiVersion: v2 +appVersion: v3.7.3 +dependencies: +- condition: alertmanager.enabled + name: alertmanager + repository: https://prometheus-community.github.io/helm-charts + version: 1.28.* +- condition: kube-state-metrics.enabled + name: kube-state-metrics + repository: https://prometheus-community.github.io/helm-charts + version: 6.4.* +- condition: prometheus-node-exporter.enabled + name: prometheus-node-exporter + repository: https://prometheus-community.github.io/helm-charts + version: 4.49.* +- condition: prometheus-pushgateway.enabled + name: prometheus-pushgateway + repository: https://prometheus-community.github.io/helm-charts + version: 3.4.* +description: Prometheus is a monitoring system and time series database. +home: https://prometheus.io/ +icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png +keywords: +- monitoring +- prometheus +kubeVersion: '>=1.19.0-0' +maintainers: +- email: gianrubio@gmail.com + name: gianrubio + url: https://github.com/gianrubio +- email: zanhsieh@gmail.com + name: zanhsieh + url: https://github.com/zanhsieh +- email: miroslav.hadzhiev@gmail.com + name: Xtigyro + url: https://github.com/Xtigyro +- email: naseem@transit.app + name: naseemkullah + url: https://github.com/naseemkullah +- email: rootsandtrees@posteo.de + name: zeritti + url: https://github.com/zeritti +name: prometheus +sources: +- https://github.com/prometheus/alertmanager +- https://github.com/prometheus/prometheus +- https://github.com/prometheus/pushgateway +- https://github.com/prometheus/node_exporter +- https://github.com/kubernetes/kube-state-metrics +type: application +version: 27.45.0 diff --git a/utils/assets/charts/prometheus/README.md b/utils/assets/charts/prometheus/README.md new file mode 100644 index 0000000..0191771 --- /dev/null +++ b/utils/assets/charts/prometheus/README.md @@ -0,0 +1,392 @@ +# Prometheus + +[Prometheus](https://prometheus.io/), a [Cloud Native Computing Foundation](https://cncf.io/) project, is a systems and service monitoring system. It collects metrics from configured targets at given intervals, evaluates rule expressions, displays the results, and can trigger alerts if some condition is observed to be true. + +This chart bootstraps a [Prometheus](https://prometheus.io/) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.7+ + +## Usage + +The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/). + +- OCI Artifact: `oci://ghcr.io/prometheus-community/charts/prometheus` +- Helm Repository: `https://prometheus-community.github.io/helm-charts` with chart `prometheus` + +The installation instructions use the OCI registry. Refer to the [`helm repo`]([`helm repo`](https://helm.sh/docs/helm/helm_repo/)) command documentation for information on installing charts via the traditional repository. + +### Install Chart + +Starting with version 16.0, the Prometheus chart requires Helm 3.7+ in order to install successfully. Please check your `helm` release before installation. + +```console +helm install [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/prometheus +``` + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +### Dependencies + +By default this chart installs additional, dependent charts: + +- [alertmanager](https://github.com/prometheus-community/helm-charts/tree/main/charts/alertmanager) +- [kube-state-metrics](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics) +- [prometheus-node-exporter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-node-exporter) +- [prometheus-pushgateway](https://github.com/walker-tom/helm-charts/tree/main/charts/prometheus-pushgateway) + +To disable the dependency during installation, set `alertmanager.enabled`, `kube-state-metrics.enabled`, `prometheus-node-exporter.enabled` and `prometheus-pushgateway.enabled` to `false`. + +_See [helm dependency](https://helm.sh/docs/helm/helm_dependency/) for command documentation._ + +### Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +### Updating values.schema.json + +A [`values.schema.json`](https://helm.sh/docs/topics/charts/#schema-files) file has been added to validate chart values. When `values.yaml` file has a structure change (i.e. add a new field, change value type, etc.), modify `values.schema.json` file manually or run `helm schema-gen values.yaml > values.schema.json` to ensure the schema is aligned with the latest values. Refer to [helm plugin `helm-schema-gen`](https://github.com/karuppiah7890/helm-schema-gen) for plugin installation instructions. + +### Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/prometheus --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +#### To 27.0 + +Prometheus' configuration parameter `insecure_skip_verify` in scrape configs `serverFiles."prometheus.yml".scrape_configs` has been commented out keeping thus the default Prometheus' value. +If certificate verification must be skipped, please, uncomment the line before upgrading. + +#### To 26.0 + +This release changes default version of promethues to v3.0.0, See official [migration guide](https://prometheus.io/docs/prometheus/latest/migration/#prometheus-3-0-migration-guide +) and [release notes](https://github.com/prometheus/prometheus/releases/tag/v3.0.0) for more details. + +#### To 25.0 + +The `server.remoteRead[].url` and `server.remoteWrite[].url` fields now support templating. Allowing for `url` values such as `https://{{ .Release.Name }}.example.com`. + +Any entries in these which previously included `{{` or `}}` must be escaped with `{{ "{{" }}` and `{{ "}}" }}` respectively. Entries which did not previously include the template-like syntax will not be affected. + +#### To 24.0 + +Require Kubernetes 1.19+ + +Release 1.0.0 of the _alertmanager_ replaced [configmap-reload](https://github.com/jimmidyson/configmap-reload) with [prometheus-config-reloader](https://github.com/prometheus-operator/prometheus-operator/tree/main/cmd/prometheus-config-reloader). +Extra command-line arguments specified via `configmapReload.prometheus.extraArgs` are not compatible and will break with the new prometheus-config-reloader. Please, refer to the [sources](https://github.com/prometheus-operator/prometheus-operator/blob/main/cmd/prometheus-config-reloader/main.go) in order to make the appropriate adjustment to the extra command-line arguments. + +#### To 23.0 + +Release 5.0.0 of the _kube-state-metrics_ chart introduced a separation of the `image.repository` value in two distinct values: + +```console + image: + registry: registry.k8s.io + repository: kube-state-metrics/kube-state-metrics +``` + +If a custom values file or CLI flags set `kube-state.metrics.image.repository`, please, set the new values accordingly. + +If you are upgrading _prometheus-pushgateway_ with the chart and _prometheus-pushgateway_ has been deployed as a statefulset with a persistent volume, the statefulset must be deleted before upgrading the chart, e.g.: + +```bash +kubectl delete sts -l app.kubernetes.io/name=prometheus-pushgateway -n monitoring --cascade=orphan +``` + +Users are advised to review changes in the corresponding chart releases before upgrading. + +#### To 22.0 + +The `app.kubernetes.io/version` label has been removed from the pod selector. + +Therefore, you must delete the previous StatefulSet or Deployment before upgrading. Performing this operation will cause **Prometheus to stop functioning** until the upgrade is complete. + +```console +kubectl delete deploy,sts -l app.kubernetes.io/name=prometheus +``` + +#### To 21.0 + +The Kubernetes labels have been updated to follow [Helm 3 label and annotation best practices](https://helm.sh/docs/chart_best_practices/labels/). +Specifically, labels mapping is listed below: + +| OLD | NEW | +|--------------------|------------------------------| +|heritage | app.kubernetes.io/managed-by | +|chart | helm.sh/chart | +|[container version] | app.kubernetes.io/version | +|app | app.kubernetes.io/name | +|release | app.kubernetes.io/instance | + +Therefore, depending on the way you've configured the chart, the previous StatefulSet or Deployment need to be deleted before upgrade. + +If `runAsStatefulSet: false` (this is the default): + +```console +kubectl delete deploy -l app=prometheus +``` + +If `runAsStatefulSet: true`: + +```console +kubectl delete sts -l app=prometheus +``` + +After that do the actual upgrade: + +```console +helm upgrade -i prometheus prometheus-community/prometheus +``` + +#### To 20.0 + +The [configmap-reload](https://github.com/jimmidyson/configmap-reload) container was replaced by the [prometheus-config-reloader](https://github.com/prometheus-operator/prometheus-operator/tree/main/cmd/prometheus-config-reloader). +Extra command-line arguments specified via configmapReload.prometheus.extraArgs are not compatible and will break with the new prometheus-config-reloader, refer to the [sources](https://github.com/prometheus-operator/prometheus-operator/blob/main/cmd/prometheus-config-reloader/main.go) in order to make the appropriate adjustment to the extra command-line arguments. + +#### To 19.0 + +Prometheus has been updated to version v2.40.5. + +Prometheus-pushgateway was updated to version 2.0.0 which adapted [Helm label and annotation best practices](https://helm.sh/docs/chart_best_practices/labels/). +See the [upgrade docs of the prometheus-pushgateway chart](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-pushgateway#to-200) to see whats to do, before you upgrade Prometheus! + +The condition in Chart.yaml to disable kube-state-metrics has been changed from `kubeStateMetrics.enabled` to `kube-state-metrics.enabled` + +The Docker image tag is used from appVersion field in Chart.yaml by default. + +Unused subchart configs has been removed and subchart config is now on the bottom of the config file. + +If Prometheus is used as deployment the updatestrategy has been changed to "Recreate" by default, so Helm updates work out of the box. + +`.Values.server.extraTemplates` & `.Values.server.extraObjects` has been removed in favour of `.Values.extraManifests`, which can do the same. + +`.Values.server.enabled` has been removed as it's useless now that all components are created by subcharts. + +All files in `templates/server` directory has been moved to `templates` directory. + +```bash +helm upgrade [RELEASE_NAME] prometheus-community/prometheus --version 19.0.0 +``` + +#### To 18.0 + +Version 18.0.0 uses alertmanager service from the [alertmanager chart](https://github.com/prometheus-community/helm-charts/tree/main/charts/alertmanager). If you've made some config changes, please check the old `alertmanager` and the new `alertmanager` configuration section in values.yaml for differences. + +Note that the `configmapReload` section for `alertmanager` was moved out of dedicated section (`configmapReload.alertmanager`) to alertmanager embedded (`alertmanager.configmapReload`). + +Before you update, please scale down the `prometheus-server` deployment to `0` then perform upgrade: + +```bash +# In 17.x +kubectl scale deploy prometheus-server --replicas=0 +# Upgrade +helm upgrade [RELEASE_NAME] prometheus-community/prometheus --version 18.0.0 +``` + +#### To 17.0 + +Version 17.0.0 uses pushgateway service from the [prometheus-pushgateway chart](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-pushgateway). If you've made some config changes, please check the old `pushgateway` and the new `prometheus-pushgateway` configuration section in values.yaml for differences. + +Before you update, please scale down the `prometheus-server` deployment to `0` then perform upgrade: + +```bash +# In 16.x +kubectl scale deploy prometheus-server --replicas=0 +# Upgrade +helm upgrade [RELEASE_NAME] prometheus-community/prometheus --version 17.0.0 +``` + +#### To 16.0 + +Starting from version 16.0 embedded services (like alertmanager, node-exporter etc.) are moved out of Prometheus chart and the respecting charts from this repository are used as dependencies. Version 16.0.0 moves node-exporter service to [prometheus-node-exporter chart](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-node-exporter). If you've made some config changes, please check the old `nodeExporter` and the new `prometheus-node-exporter` configuration section in values.yaml for differences. + +Before you update, please scale down the `prometheus-server` deployment to `0` then perform upgrade: + +```bash +# In 15.x +kubectl scale deploy prometheus-server --replicas=0 +# Upgrade +helm upgrade [RELEASE_NAME] prometheus-community/prometheus --version 16.0.0 +``` + +#### To 15.0 + +Version 15.0.0 changes the relabeling config, aligning it with the [Prometheus community conventions](https://github.com/prometheus/prometheus/pull/9832). If you've made manual changes to the relabeling config, you have to adapt your changes. + +Before you update please execute the following command, to be able to update kube-state-metrics: + +```bash +kubectl delete deployments.apps -l app.kubernetes.io/instance=prometheus,app.kubernetes.io/name=kube-state-metrics --cascade=orphan +``` + +#### To 9.0 + +Version 9.0 adds a new option to enable or disable the Prometheus Server. This supports the use case of running a Prometheus server in one k8s cluster and scraping exporters in another cluster while using the same chart for each deployment. To install the server `server.enabled` must be set to `true`. + +#### To 5.0 + +As of version 5.0, this chart uses Prometheus 2.x. This version of prometheus introduces a new data format and is not compatible with prometheus 1.x. It is recommended to install this as a new release, as updating existing releases will not work. See the [prometheus docs](https://prometheus.io/docs/prometheus/latest/migration/#storage) for instructions on retaining your old data. + +Prometheus version 2.x has made changes to alertmanager, storage and recording rules. Check out [the 2.x migration guide](https://prometheus.io/docs/prometheus/2.55/migration/). + +Users of this chart will need to update their alerting rules to the new format before they can upgrade. + +#### Example Migration + +Assuming you have an existing release of the prometheus chart, named `prometheus-old`. In order to update to prometheus 2.x while keeping your old data do the following: + +1. Update the `prometheus-old` release. Disable scraping on every component besides the prometheus server, similar to the configuration below: + + ```yaml + alertmanager: + enabled: false + alertmanagerFiles: + alertmanager.yml: "" + kubeStateMetrics: + enabled: false + nodeExporter: + enabled: false + pushgateway: + enabled: false + server: + extraArgs: + storage.local.retention: 720h + serverFiles: + alerts: "" + prometheus.yml: "" + rules: "" + ``` + +1. Deploy a new release of the chart with version 5.0+ using prometheus 2.x. In the values.yaml set the scrape config as usual, and also add the `prometheus-old` instance as a remote-read target. + + ```yaml + prometheus.yml: + ... + remote_read: + - url: http://prometheus-old/api/v1/read + ... + ``` + + Old data will be available when you query the new prometheus instance. + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values oci://ghcr.io/prometheus-community/charts/prometheus +``` + +You may similarly use the above configuration commands on each chart [dependency](#dependencies) to see its configurations. + +### Scraping Pod Metrics via Annotations + +This chart uses a default configuration that causes prometheus to scrape a variety of kubernetes resource types, provided they have the correct annotations. In this section we describe how to configure pods to be scraped; for information on how other resource types can be scraped you can do a `helm template` to get the kubernetes resource definitions, and then reference the prometheus configuration in the ConfigMap against the prometheus documentation for [relabel_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) and [kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config). + +In order to get prometheus to scrape pods, you must add annotations to the pods as below: + +```yaml +metadata: + annotations: + prometheus.io/scrape: "true" + prometheus.io/path: /metrics + prometheus.io/port: "8080" +``` + +You should adjust `prometheus.io/path` based on the URL that your pod serves metrics from. `prometheus.io/port` should be set to the port that your pod serves metrics from. Note that the values for `prometheus.io/scrape` and `prometheus.io/port` must be enclosed in double quotes. + +### Sharing Alerts Between Services + +Note that when [installing](#install-chart) or [upgrading](#upgrading-chart) you may use multiple values override files. This is particularly useful when you have alerts belonging to multiple services in the cluster. For example, + +```yaml +# values.yaml +# ... + +# service1-alert.yaml +serverFiles: + alerts: + service1: + - alert: anAlert + # ... + +# service2-alert.yaml +serverFiles: + alerts: + service2: + - alert: anAlert + # ... +``` + +```console +helm install [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/prom-label-proxy -f values.yaml -f service1-alert.yaml -f service2-alert.yaml +``` + +### RBAC Configuration + +Roles and RoleBindings resources will be created automatically for `server` service. + +To manually setup RBAC you need to set the parameter `rbac.create=false` and specify the service account to be used for each service by setting the parameters: `serviceAccounts.{{ component }}.create` to `false` and `serviceAccounts.{{ component }}.name` to the name of a pre-existing service account. + +> **Tip**: You can refer to the default `*-clusterrole.yaml` and `*-clusterrolebinding.yaml` files in [templates](templates/) to customize your own. + +### ConfigMap Files + +AlertManager is configured through [alertmanager.yml](https://prometheus.io/docs/alerting/configuration/). This file (and any others listed in `alertmanagerFiles`) will be mounted into the `alertmanager` pod. + +Prometheus is configured through [prometheus.yml](https://prometheus.io/docs/operating/configuration/). This file (and any others listed in `serverFiles`) will be mounted into the `server` pod. + +### Ingress TLS + +If your cluster allows automatic creation/retrieval of TLS certificates (e.g. [cert-manager](https://github.com/jetstack/cert-manager)), please refer to the documentation for that mechanism. + +To manually configure TLS, first create/retrieve a key & certificate pair for the address(es) you wish to protect. Then create a TLS secret in the namespace: + +```console +kubectl create secret tls prometheus-server-tls --cert=path/to/tls.cert --key=path/to/tls.key +``` + +Include the secret's name, along with the desired hostnames, in the alertmanager/server Ingress TLS section of your custom `values.yaml` file: + +```yaml +server: + ingress: + ## If true, Prometheus server Ingress will be created + ## + enabled: true + + ## Prometheus server Ingress hostnames + ## Must be provided if Ingress is enabled + ## + hosts: + - prometheus.domain.com + + ## Prometheus server Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: + - secretName: prometheus-server-tls + hosts: + - prometheus.domain.com +``` + +### NetworkPolicy + +Enabling Network Policy for Prometheus will secure connections to Alert Manager and Kube State Metrics by only accepting connections from Prometheus Server. All inbound connections to Prometheus Server are still allowed. + +To enable network policy for Prometheus, install a networking plugin that implements the Kubernetes NetworkPolicy spec, and set `networkPolicy.enabled` to true. + +If NetworkPolicy is enabled for Prometheus' scrape targets, you may also need to manually create a networkpolicy which allows it. diff --git a/utils/assets/charts/prometheus/charts/alertmanager/.helmignore b/utils/assets/charts/prometheus/charts/alertmanager/.helmignore new file mode 100644 index 0000000..72fc977 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/.helmignore @@ -0,0 +1,26 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +unittests/ +ci/ diff --git a/utils/assets/charts/prometheus/charts/alertmanager/Chart.yaml b/utils/assets/charts/prometheus/charts/alertmanager/Chart.yaml new file mode 100644 index 0000000..da1390d --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/Chart.yaml @@ -0,0 +1,26 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts +apiVersion: v2 +appVersion: v0.29.0 +description: The Alertmanager handles alerts sent by client applications such as the + Prometheus server. +home: https://prometheus.io/ +icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png +keywords: +- monitoring +kubeVersion: '>=1.25.0-0' +maintainers: +- email: monotek23@gmail.com + name: monotek + url: https://github.com/monotek +- email: naseem@transit.app + name: naseemkullah + url: https://github.com/naseemkullah +name: alertmanager +sources: +- https://github.com/prometheus/alertmanager +type: application +version: 1.28.0 diff --git a/utils/assets/charts/prometheus/charts/alertmanager/README.md b/utils/assets/charts/prometheus/charts/alertmanager/README.md new file mode 100644 index 0000000..12f845a --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/README.md @@ -0,0 +1,62 @@ +# Alertmanager + +As per [prometheus.io documentation](https://prometheus.io/docs/alerting/latest/alertmanager/): +> The Alertmanager handles alerts sent by client applications such as the +> Prometheus server. It takes care of deduplicating, grouping, and routing them +> to the correct receiver integration such as email, PagerDuty, or OpsGenie. It +> also takes care of silencing and inhibition of alerts. + +## Prerequisites + +Kubernetes 1.14+ + +## Usage + +The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/). + +- OCI Artifact: `oci://ghcr.io/prometheus-community/charts/alertmanager` +- Helm Repository: `https://prometheus-community.github.io/helm-charts` with chart `alertmanager` + +The installation instructions use the OCI registry. Refer to the [`helm repo`]([`helm repo`](https://helm.sh/docs/helm/helm_repo/)) command documentation for information on installing charts via the traditional repository. + +### Install Chart + +```console +helm install [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/alertmanager +``` + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +### Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +### Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] [CHART] --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### To 1.0 + +The [configmap-reload](https://github.com/jimmidyson/configmap-reload) container was replaced by the [prometheus-config-reloader](https://github.com/prometheus-operator/prometheus-operator/tree/main/cmd/prometheus-config-reloader). +Extra command-line arguments specified via configmapReload.prometheus.extraArgs are not compatible and will break with the new prometheus-config-reloader, refer to the [sources](https://github.com/prometheus-operator/prometheus-operator/blob/main/cmd/prometheus-config-reloader/main.go) in order to make the appropriate adjustment to the extea command-line arguments. +The `networking.k8s.io/v1beta1` is no longer supported. use [`networking.k8s.io/v1`](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingressclass-v122). + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values oci://ghcr.io/prometheus-community/charts/alertmanager +``` diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/NOTES.txt b/utils/assets/charts/prometheus/charts/alertmanager/templates/NOTES.txt new file mode 100644 index 0000000..46ea5be --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/NOTES.txt @@ -0,0 +1,21 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ include "alertmanager.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "alertmanager.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ include "alertmanager.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ include "alertmanager.namespace" . }} svc -w {{ include "alertmanager.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ include "alertmanager.namespace" . }} {{ include "alertmanager.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ include "alertmanager.namespace" . }} -l "app.kubernetes.io/name={{ include "alertmanager.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:{{ .Values.service.port }} to use your application" + kubectl --namespace {{ include "alertmanager.namespace" . }} port-forward $POD_NAME {{ .Values.service.port }}:80 +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/_helpers.tpl b/utils/assets/charts/prometheus/charts/alertmanager/templates/_helpers.tpl new file mode 100644 index 0000000..0c34c73 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/_helpers.tpl @@ -0,0 +1,81 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "alertmanager.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "alertmanager.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "alertmanager.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "alertmanager.labels" -}} +helm.sh/chart: {{ include "alertmanager.chart" . }} +{{ include "alertmanager.selectorLabels" . }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "alertmanager.selectorLabels" -}} +app.kubernetes.io/name: {{ include "alertmanager.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "alertmanager.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "alertmanager.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Define Ingress apiVersion +*/}} +{{- define "alertmanager.ingress.apiVersion" -}} +{{- printf "networking.k8s.io/v1" }} +{{- end }} + +{{/* +Allow overriding alertmanager namespace +*/}} +{{- define "alertmanager.namespace" -}} +{{- if .Values.namespaceOverride -}} +{{- .Values.namespaceOverride -}} +{{- else -}} +{{- .Release.Namespace -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/configmap.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/configmap.yaml new file mode 100644 index 0000000..9e5882d --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/configmap.yaml @@ -0,0 +1,21 @@ +{{- if .Values.config.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "alertmanager.fullname" . }} + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + {{- with .Values.configAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "alertmanager.namespace" . }} +data: + alertmanager.yml: | + {{- $config := omit .Values.config "enabled" }} + {{- toYaml $config | default "{}" | nindent 4 }} + {{- range $key, $value := .Values.templates }} + {{ $key }}: |- + {{- $value | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/ingress.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/ingress.yaml new file mode 100644 index 0000000..4112d64 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/ingress.yaml @@ -0,0 +1,47 @@ +{{- if .Values.ingress.enabled }} +{{- $fullName := include "alertmanager.fullname" . }} +{{- $svcPort := .Values.service.port }} +apiVersion: {{ include "alertmanager.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + {{- if .Values.ingress.labels }} + {{- toYaml .Values.ingress.labels | nindent 4 }} + {{- end }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "alertmanager.namespace" . }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/ingressperreplica.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/ingressperreplica.yaml new file mode 100644 index 0000000..6f5a023 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/ingressperreplica.yaml @@ -0,0 +1,56 @@ +{{- if and .Values.servicePerReplica.enabled .Values.ingressPerReplica.enabled }} +{{- $pathType := .Values.ingressPerReplica.pathType }} +{{- $count := .Values.replicaCount | int -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressValues := .Values.ingressPerReplica -}} +{{- $fullName := include "alertmanager.fullname" . }} +apiVersion: v1 +kind: List +metadata: + name: {{ $fullName }}-ingressperreplica + namespace: {{ include "alertmanager.namespace" . }} +items: +{{- range $i, $e := until $count }} + - kind: Ingress + apiVersion: {{ include "alertmanager.ingress.apiVersion" $ }} + metadata: + name: {{ $fullName }}-{{ $i }} + namespace: {{ include "alertmanager.namespace" $ }} + labels: + {{- include "alertmanager.labels" $ | nindent 8 }} + {{- if $ingressValues.labels }} +{{ toYaml $ingressValues.labels | indent 8 }} + {{- end }} + {{- if $ingressValues.annotations }} + annotations: +{{ toYaml $ingressValues.annotations | indent 8 }} + {{- end }} + spec: + {{- if $ingressValues.className }} + ingressClassName: {{ $ingressValues.className }} + {{- end }} + rules: + - host: {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }} + http: + paths: + {{- range $p := $ingressValues.paths }} + - path: {{ tpl $p $ }} + pathType: {{ $pathType }} + backend: + service: + name: {{ $fullName }}-{{ $i }} + port: + name: http + {{- end -}} + {{- if or $ingressValues.tlsSecretName $ingressValues.tlsSecretPerReplica.enabled }} + tls: + - hosts: + - {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }} + {{- if $ingressValues.tlsSecretPerReplica.enabled }} + secretName: {{ $ingressValues.tlsSecretPerReplica.prefix }}-{{ $i }} + {{- else }} + secretName: {{ $ingressValues.tlsSecretName }} + {{- end }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/pdb.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/pdb.yaml new file mode 100644 index 0000000..920a853 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/pdb.yaml @@ -0,0 +1,14 @@ +{{- if .Values.podDisruptionBudget }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "alertmanager.fullname" . }} + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + namespace: {{ include "alertmanager.namespace" . }} +spec: + selector: + matchLabels: + {{- include "alertmanager.selectorLabels" . | nindent 6 }} + {{- toYaml .Values.podDisruptionBudget | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/serviceaccount.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/serviceaccount.yaml new file mode 100644 index 0000000..bc9ccaa --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "alertmanager.serviceAccountName" . }} + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "alertmanager.namespace" . }} +automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/serviceperreplica.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/serviceperreplica.yaml new file mode 100644 index 0000000..8aa543b --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/serviceperreplica.yaml @@ -0,0 +1,44 @@ +{{- if and .Values.servicePerReplica.enabled }} +{{- $count := .Values.replicaCount | int -}} +{{- $serviceValues := .Values.servicePerReplica -}} +apiVersion: v1 +kind: List +metadata: + name: {{ include "alertmanager.fullname" . }}-serviceperreplica + namespace: {{ include "alertmanager.namespace" . }} +items: +{{- range $i, $e := until $count }} + - apiVersion: v1 + kind: Service + metadata: + name: {{ include "alertmanager.fullname" $ }}-{{ $i }} + namespace: {{ include "alertmanager.namespace" $ }} + labels: + {{- include "alertmanager.labels" $ | nindent 8 }} + {{- if $serviceValues.annotations }} + annotations: +{{ toYaml $serviceValues.annotations | indent 8 }} + {{- end }} + spec: + {{- if $serviceValues.clusterIP }} + clusterIP: {{ $serviceValues.clusterIP }} + {{- end }} + {{- if $serviceValues.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := $serviceValues.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} + {{- end }} + {{- if ne $serviceValues.type "ClusterIP" }} + externalTrafficPolicy: {{ $serviceValues.externalTrafficPolicy }} + {{- end }} + ports: + - name: http + port: {{ $.Values.service.port }} + targetPort: {{ $.Values.containerPortName }} + selector: + {{- include "alertmanager.selectorLabels" $ | nindent 8 }} + statefulset.kubernetes.io/pod-name: {{ include "alertmanager.fullname" $ }}-{{ $i }} + type: "{{ $serviceValues.type }}" +{{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/services.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/services.yaml new file mode 100644 index 0000000..ebc583c --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/services.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "alertmanager.fullname" . }} + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + {{- with .Values.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "alertmanager.namespace" . }} +spec: + {{- if .Values.service.ipDualStack.enabled }} + ipFamilies: {{ toYaml .Values.service.ipDualStack.ipFamilies | nindent 4 }} + ipFamilyPolicy: {{ .Values.service.ipDualStack.ipFamilyPolicy }} + {{- end }} + type: {{ .Values.service.type }} + {{- with .Values.service.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- with .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := . }} + - {{ $cidr }} + {{- end }} + {{- end }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.containerPortName }} + protocol: TCP + name: http + {{- if (and (eq .Values.service.type "NodePort") .Values.service.nodePort) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- with .Values.service.extraPorts }} + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + {{- include "alertmanager.selectorLabels" . | nindent 4 }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "alertmanager.fullname" . }}-headless + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + {{- with .Values.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "alertmanager.namespace" . }} +spec: + clusterIP: None + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.containerPortName }} + protocol: TCP + name: http + {{- if or (gt (int .Values.replicaCount) 1) (.Values.additionalPeers) }} + - port: {{ .Values.service.clusterPort }} + targetPort: clusterpeer-tcp + protocol: TCP + name: cluster-tcp + - port: {{ .Values.service.clusterPort }} + targetPort: clusterpeer-udp + protocol: UDP + name: cluster-udp + {{- end }} + {{- with .Values.service.extraPorts }} + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + {{- include "alertmanager.selectorLabels" . | nindent 4 }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/statefulset.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/statefulset.yaml new file mode 100644 index 0000000..6c9ff82 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/statefulset.yaml @@ -0,0 +1,280 @@ +{{- $svcClusterPort := .Values.service.clusterPort }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "alertmanager.fullname" . }} + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + {{- with .Values.statefulSet.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "alertmanager.namespace" . }} +spec: + replicas: {{ .Values.replicaCount }} + minReadySeconds: {{ .Values.minReadySeconds }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "alertmanager.selectorLabels" . | nindent 6 }} + serviceName: {{ include "alertmanager.fullname" . }}-headless + template: + metadata: + labels: + {{- include "alertmanager.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- if not .Values.configmapReload.enabled }} + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- end }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.hostUsers }} + hostUsers: true + {{- end }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "alertmanager.serviceAccountName" . }} + {{- with .Values.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.hostAliases }} + hostAliases: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.schedulerName }} + schedulerName: {{ . }} + {{- end }} + {{- if or .Values.podAntiAffinity .Values.affinity }} + affinity: + {{- end }} + {{- with .Values.affinity }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if eq .Values.podAntiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [{{ include "alertmanager.name" . }}]} + {{- else if eq .Values.podAntiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: {{ .Values.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [{{ include "alertmanager.name" . }}]} + {{- end }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- with .Values.extraInitContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + {{- if .Values.configmapReload.enabled }} + - name: {{ .Chart.Name }}-{{ .Values.configmapReload.name }} + image: "{{ .Values.configmapReload.image.repository }}:{{ .Values.configmapReload.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.image.pullPolicy }}" + {{- with .Values.configmapReload.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + args: + {{- if and (hasKey .Values.configmapReload.extraArgs "config-file" | not) (hasKey .Values.configmapReload.extraArgs "watched-dir" | not) }} + - --watched-dir=/etc/alertmanager + {{- end }} + {{- if not (hasKey .Values.configmapReload.extraArgs "reload-url") }} + - --reload-url=http://127.0.0.1:9093/-/reload + {{- end }} + {{- range $key, $value := .Values.configmapReload.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + resources: + {{- toYaml .Values.configmapReload.resources | nindent 12 }} + {{- with .Values.configmapReload.containerPort }} + ports: + - containerPort: {{ . }} + {{- end }} + {{- with .Values.configmapReload.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.configmapReload.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.configmapReload.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.config.enabled }} + - name: config + mountPath: /etc/alertmanager + {{- end }} + {{- if .Values.configmapReload.extraVolumeMounts }} + {{- toYaml .Values.configmapReload.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + {{- if .Values.extraEnv }} + {{- toYaml .Values.extraEnv | nindent 12 }} + {{- end }} + {{- with .Values.command }} + command: + {{- toYaml . | nindent 12 }} + {{- end }} + args: + - --storage.path=/alertmanager + {{- if not (hasKey .Values.extraArgs "config.file") }} + - --config.file=/etc/alertmanager/alertmanager.yml + {{- end }} + {{- if or (gt (int .Values.replicaCount) 1) (.Values.additionalPeers) }} + - --cluster.advertise-address=[$(POD_IP)]:{{ $svcClusterPort }} + - --cluster.listen-address=0.0.0.0:{{ $svcClusterPort }} + {{- end }} + {{- if gt (int .Values.replicaCount) 1}} + {{- $fullName := include "alertmanager.fullname" . }} + {{- range $i := until (int .Values.replicaCount) }} + - --cluster.peer={{ $fullName }}-{{ $i }}.{{ $fullName }}-headless:{{ $svcClusterPort }} + {{- end }} + {{- end }} + {{- if .Values.additionalPeers }} + {{- range $item := .Values.additionalPeers }} + - --cluster.peer={{ $item }} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.baseURL }} + - --web.external-url={{ .Values.baseURL }} + {{- end }} + ports: + - name: {{ .Values.containerPortName }} + containerPort: 9093 + protocol: TCP + {{- if or (gt (int .Values.replicaCount) 1) (.Values.additionalPeers) }} + - name: clusterpeer-tcp + containerPort: {{ $svcClusterPort }} + protocol: TCP + - name: clusterpeer-udp + containerPort: {{ $svcClusterPort }} + protocol: UDP + {{- end }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + {{- if .Values.config.enabled }} + - name: config + mountPath: /etc/alertmanager + {{- end }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + - name: storage + mountPath: /alertmanager + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- with .Values.extraContainers }} + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.config.enabled }} + - name: config + configMap: + name: {{ include "alertmanager.fullname" . }} + {{- end }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} + {{- if .Values.extraPodConfigs }} + {{- toYaml .Values.extraPodConfigs | nindent 6 }} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: storage + {{- with .Values.persistence.annotations }} + annotations: + {{ toYaml . | nindent 14 }} + {{- end }} + {{- with .Values.persistence.labels }} + labels: + {{ toYaml . | nindent 14 }} + {{- end }} + spec: + accessModes: + {{- toYaml .Values.persistence.accessModes | nindent 10 }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} + {{- end }} + {{- else }} + - name: storage + {{- with .Values.persistence.emptyDir }} + emptyDir: + {{- toYaml . | nindent 12 }} + {{- else }} + emptyDir: {} + {{- end -}} + {{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/tests/test-connection.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/tests/test-connection.yaml new file mode 100644 index 0000000..410eba5 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/tests/test-connection.yaml @@ -0,0 +1,20 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "alertmanager.fullname" . }}-test-connection" + labels: + {{- include "alertmanager.labels" . | nindent 4 }} + {{- with .Values.testFramework.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "alertmanager.namespace" . }} +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "alertmanager.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/templates/vpa.yaml b/utils/assets/charts/prometheus/charts/alertmanager/templates/vpa.yaml new file mode 100644 index 0000000..53f70a2 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/templates/vpa.yaml @@ -0,0 +1,26 @@ +{{- if .Values.verticalPodAutoscaler.enabled }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ include "alertmanager.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + {{- if .Values.verticalPodAutoscaler.recommenders }} + recommenders: + {{- range .Values.verticalPodAutoscaler.recommenders }} + - name: {{ .name }} + {{- end }} + {{- end }} + targetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: {{ include "alertmanager.fullname" . }} + {{- if .Values.verticalPodAutoscaler.updatePolicy }} + updatePolicy: + {{- toYaml .Values.verticalPodAutoscaler.updatePolicy | nindent 4 }} + {{- end }} + {{- if .Values.verticalPodAutoscaler.resourcePolicy }} + resourcePolicy: + {{- toYaml .Values.verticalPodAutoscaler.resourcePolicy | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/values.schema.json b/utils/assets/charts/prometheus/charts/alertmanager/values.schema.json new file mode 100644 index 0000000..a22ecbb --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/values.schema.json @@ -0,0 +1,972 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "alertmanager", + "description": "The Alertmanager handles alerts sent by client applications such as the Prometheus server.", + "type": "object", + "required": [ + "replicaCount", + "image", + "serviceAccount", + "service", + "persistence", + "config" + ], + "definitions": { + "image": { + "description": "Container image parameters.", + "type": "object", + "required": ["repository"], + "additionalProperties": false, + "properties": { + "repository": { + "description": "Image repository. Path to the image with registry(quay.io) or without(prometheus/alertmanager) for docker.io.", + "type": "string" + }, + "pullPolicy": { + "description": "Image pull policy. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.", + "type": "string", + "enum": [ + "Never", + "IfNotPresent", + "Always" + ], + "default": "IfNotPresent" + }, + "tag": { + "description": "Use chart appVersion by default.", + "type": "string", + "default": "" + } + } + }, + "resources": { + "description": "Resource limits and requests for the Container.", + "type": "object", + "properties": { + "limits": { + "description": "Resource limits for the Container.", + "type": "object", + "properties": { + "cpu": { + "description": "CPU request for the Container.", + "type": "string" + }, + "memory": { + "description": "Memory request for the Container.", + "type": "string" + } + } + }, + "requests": { + "description": "Resource requests for the Container.", + "type": "object", + "properties": { + "cpu": { + "description": "CPU request for the Container.", + "type": "string" + }, + "memory": { + "description": "Memory request for the Container.", + "type": "string" + } + } + } + } + }, + "securityContext": { + "description": "Security context for the container.", + "type": "object", + "properties": { + "capabilities": { + "description": "Specifies the capabilities to be dropped by the container.", + "type": "object", + "properties": { + "drop": { + "description": "List of capabilities to be dropped.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "readOnlyRootFilesystem": { + "description": "Specifies whether the root file system should be mounted as read-only.", + "type": "boolean" + }, + "runAsUser": { + "description": "Specifies the UID (User ID) to run the container as.", + "type": "integer" + }, + "runAsNonRoot": { + "description": "Specifies whether to run the container as a non-root user.", + "type": "boolean" + }, + "runAsGroup": { + "description": "Specifies the GID (Group ID) to run the container as.", + "type": "integer" + } + } + }, + "volumeMounts": { + "description": "List of volume mounts for the Container.", + "type": "array", + "items": { + "description": "Volume mounts for the Container.", + "type": "object", + "required": ["name", "mountPath"], + "properties": { + "name": { + "description": "The name of the volume to mount.", + "type": "string" + }, + "mountPath": { + "description": "The mount path for the volume.", + "type": "string" + }, + "readOnly": { + "description": "Specifies if the volume should be mounted in read-only mode.", + "type": "boolean" + } + } + } + }, + "env": { + "description": "List of environment variables for the Container.", + "type": "array", + "items": { + "description": "Environment variables for the Container.", + "type": "object", + "required": ["name"], + "properties": { + "name": { + "description": "The name of the environment variable.", + "type": "string" + }, + "value": { + "description": "The value of the environment variable.", + "type": "string" + } + } + } + }, + "config": { + "description": "https://prometheus.io/docs/alerting/latest/configuration/", + "duration": { + "type": "string", + "pattern": "^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$" + }, + "labelname": { + "type": "string", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$|^...$" + }, + "route": { + "description": "Alert routing configuration.", + "type": "object", + "properties": { + "receiver": { + "description": "The default receiver to send alerts to.", + "type": "string" + }, + "group_by": { + "description": "The labels by which incoming alerts are grouped together.", + "type": "array", + "items": { + "type": "string", + "$ref": "#/definitions/config/labelname" + } + }, + "continue": { + "description": "Whether an alert should continue matching subsequent sibling nodes.", + "type": "boolean", + "default": false + }, + "matchers": { + "description": "A list of matchers that an alert has to fulfill to match the node.", + "type": "array", + "items": { + "type": "string" + } + }, + "group_wait": { + "description": "How long to initially wait to send a notification for a group of alerts.", + "$ref": "#/definitions/config/duration" + }, + "group_interval": { + "description": "How long to wait before sending a notification about new alerts that are added to a group of alerts for which an initial notification has already been sent.", + "$ref": "#/definitions/config/duration" + }, + "repeat_interval": { + "description": "How long to wait before sending a notification again if it has already been sent successfully for an alert.", + "$ref": "#/definitions/config/duration" + }, + "mute_time_intervals": { + "description": "Times when the route should be muted.", + "type": "array", + "items": { + "type": "string" + } + }, + "active_time_intervals": { + "description": "Times when the route should be active.", + "type": "array", + "items": { + "type": "string" + } + }, + "routes": { + "description": "Zero or more child routes.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/config/route" + } + } + } + } + } + }, + "properties": { + "replicaCount": { + "description": "Number of desired pods.", + "type": "integer", + "default": 1, + "minimum": 0 + }, + "image": { + "description": "Container image parameters.", + "$ref": "#/definitions/image" + }, + "baseURL": { + "description": "External URL where alertmanager is reachable.", + "type": "string", + "default": "", + "examples": [ + "https://alertmanager.example.com" + ] + }, + "extraArgs": { + "description": "Additional alertmanager container arguments. Use args without '--', only 'key: value' syntax.", + "type": "object", + "default": {} + }, + "extraSecretMounts": { + "description": "Additional Alertmanager Secret mounts.", + "type": "array", + "default": [], + "items": { + "type": "object", + "required": ["name", "mountPath", "secretName"], + "properties": { + "name": { + "type": "string" + }, + "mountPath": { + "type": "string" + }, + "subPath": { + "type": "string", + "default": "" + }, + "secretName": { + "type": "string" + }, + "readOnly": { + "type": "boolean", + "default": false + } + } + } + }, + "imagePullSecrets": { + "description": "The property allows you to configure multiple image pull secrets.", + "type": "array", + "default": [], + "items": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "description": "Specifies the Secret name of the image pull secret.", + "type": "string" + } + } + } + }, + "nameOverride": { + "description": "Override value for the name of the Helm chart.", + "type": "string", + "default": "" + }, + "fullnameOverride": { + "description": "Override value for the fully qualified app name.", + "type": "string", + "default": "" + }, + "namespaceOverride": { + "description": "Override deployment namespace.", + "type": "string", + "default": "" + }, + "automountServiceAccountToken": { + "description": "Specifies whether to automatically mount the ServiceAccount token into the Pod's filesystem.", + "type": "boolean", + "default": true + }, + "hostUsers": { + "description": "Running within a user namespace, where the user IDs inside the container are mapped to different, usually unprivileged, user IDs on the host system.", + "type": "boolean", + "default": false + }, + "serviceAccount": { + "description": "Contains properties related to the service account configuration.", + "type": "object", + "required": ["create"], + "properties": { + "create": { + "description": "Specifies whether a service account should be created.", + "type": "boolean", + "default": true + }, + "annotations": { + "description": "Annotations to add to the service account.", + "type": "object", + "default": {} + }, + "name": { + "description": "The name of the service account to use. If not set and create is true, a name is generated using the fullname template.", + "type": "string", + "default": "" + } + } + }, + "schedulerName": { + "description": "Sets the schedulerName in the alertmanager pod.", + "type": "string", + "default": "" + }, + "priorityClassName": { + "description": "Sets the priorityClassName in the alertmanager pod.", + "type": "string", + "default": "" + }, + "podSecurityContext": { + "description": "Pod security context configuration.", + "type": "object", + "properties": { + "fsGroup": { + "description": "The fsGroup value for the pod's security context.", + "type": "integer", + "default": 65534 + }, + "runAsUser": { + "description": "The UID to run the pod's containers as.", + "type": "integer" + }, + "runAsGroup": { + "description": "The GID to run the pod's containers as.", + "type": "integer" + } + } + }, + "dnsConfig": { + "description": "DNS configuration for the pod.", + "type": "object", + "properties": { + "nameservers": { + "description": "List of DNS server IP addresses.", + "type": "array", + "items": { + "type": "string" + } + }, + "searches": { + "description": "List of DNS search domains.", + "type": "array", + "items": { + "type": "string" + } + }, + "options": { + "description": "List of DNS options.", + "type": "array", + "items": { + "description": "DNS options.", + "type": "object", + "required": ["name"], + "properties": { + "name": { + "description": "The name of the DNS option.", + "type": "string" + }, + "value": { + "description": "The value of the DNS option.", + "type": "string" + } + } + } + } + } + }, + "hostAliases": { + "description": "List of host aliases.", + "type": "array", + "items": { + "description": "Host aliases configuration.", + "type": "object", + "required": ["ip", "hostnames"], + "properties": { + "ip": { + "description": "IP address associated with the host alias.", + "type": "string" + }, + "hostnames": { + "description": "List of hostnames associated with the IP address.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "securityContext": { + "description": "Security context for the container.", + "$ref": "#/definitions/securityContext" + }, + "additionalPeers": { + "description": "Additional peers for a alertmanager.", + "type": "array", + "items": { + "type": "string" + } + }, + "extraInitContainers": { + "description": "Additional InitContainers to initialize the pod.", + "type": "array", + "default": [], + "items": { + "required": ["name", "image"], + "properties": { + "name": { + "description": "The name of the InitContainer.", + "type": "string" + }, + "image": { + "description": "The container image to use for the InitContainer.", + "type": "string" + }, + "pullPolicy": { + "description": "Image pull policy. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.", + "type": "string", + "enum": [ + "Never", + "IfNotPresent", + "Always" + ], + "default": "IfNotPresent" + }, + "command": { + "description": "The command to run in the InitContainer.", + "type": "array", + "items": { + "type": "string" + } + }, + "args": { + "description": "Additional command arguments for the InitContainer.", + "type": "array", + "items": { + "type": "string" + } + }, + "ports": { + "description": "List of ports to expose from the container.", + "type": "array", + "items": { + "type": "object" + } + }, + "env": { + "description": "List of environment variables for the InitContainer.", + "$ref": "#/definitions/env" + }, + "envFrom": { + "description": "List of sources to populate environment variables in the container.", + "type": "array", + "items": { + "type": "object" + } + }, + "volumeMounts": { + "description": "List of volume mounts for the InitContainer.", + "$ref": "#/definitions/volumeMounts" + }, + "resources": { + "description": "Resource requirements for the InitContainer.", + "$ref": "#/definitions/resources" + }, + "securityContext": { + "$ref": "#/definitions/securityContext", + "description": "The security context for the InitContainer." + } + } + } + }, + "extraContainers": { + "description": "Additional containers to add to the stateful set.", + "type": "array", + "default": [], + "items": { + "required": ["name", "image"], + "properties": { + "name": { + "description": "The name of the InitContainer.", + "type": "string" + }, + "image": { + "description": "The container image to use for the InitContainer.", + "type": "string" + }, + "pullPolicy": { + "description": "Image pull policy. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.", + "type": "string", + "enum": [ + "Never", + "IfNotPresent", + "Always" + ], + "default": "IfNotPresent" + }, + "command": { + "description": "The command to run in the InitContainer.", + "type": "array", + "items": { + "type": "string" + } + }, + "args": { + "description": "Additional command arguments for the InitContainer.", + "type": "array", + "items": { + "type": "string" + } + }, + "ports": { + "description": "List of ports to expose from the container.", + "type": "array", + "items": { + "type": "object" + } + }, + "env": { + "description": "List of environment variables for the InitContainer.", + "$ref": "#/definitions/env" + }, + "envFrom": { + "description": "List of sources to populate environment variables in the container.", + "type": "array", + "items": { + "type": "object" + } + }, + "volumeMounts": { + "description": "List of volume mounts for the InitContainer.", + "$ref": "#/definitions/volumeMounts" + }, + "resources": { + "description": "Resource requirements for the InitContainer.", + "$ref": "#/definitions/resources" + }, + "securityContext": { + "$ref": "#/definitions/securityContext", + "description": "The security context for the InitContainer." + } + } + } + }, + "resources": { + "description": "Resource limits and requests for the pod.", + "$ref": "#/definitions/resources" + }, + "containerPortName": { + "description": "Name of the port for the main container.", + "type": "string", + "default": "http" + }, + "livenessProbe": { + "description": "Liveness probe configuration.", + "type": "object" + }, + "readinessProbe": { + "description": "Readiness probe configuration.", + "type": "object" + }, + "service": { + "description": "Service configuration.", + "type": "object", + "required": ["type", "port"], + "properties": { + "annotations": { + "description": "Annotations to add to the service.", + "type": "object" + }, + "type": { + "description": "Service type.", + "type": "string" + }, + "port": { + "description": "Port number for the service.", + "type": "integer" + }, + "clusterPort": { + "description": "Port number for the cluster.", + "type": "integer" + }, + "loadBalancerIP": { + "description": "External IP to assign when the service type is LoadBalancer.", + "type": "string" + }, + "loadBalancerSourceRanges": { + "description": "IP ranges to allow access to the loadBalancerIP.", + "type": "array", + "items": { + "type": "string" + } + }, + "nodePort": { + "description": "Specific nodePort to force when service type is NodePort.", + "type": "integer" + } + } + }, + "ingress": { + "description": "Ingress configuration.", + "type": "object", + "properties": { + "enabled": { + "description": "Indicates if Ingress is enabled.", + "type": "boolean" + }, + "className": { + "description": "Ingress class name.", + "type": "string" + }, + "annotations": { + "description": "Annotations to add to the Ingress.", + "type": "object" + }, + "hosts": { + "description": "Host and path configuration for the Ingress.", + "type": "array", + "items": { + "type": "object", + "properties": { + "host": { + "description": "Host name for the Ingress.", + "type": "string" + }, + "paths": { + "description": "Path configuration for the Ingress.", + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "description": "Path for the Ingress.", + "type": "string" + }, + "pathType": { + "description": "Path type for the Ingress.", + "type": "string" + } + } + } + } + } + } + }, + "tls": { + "description": "TLS configuration for the Ingress.", + "type": "array", + "items": { + "type": "object", + "properties": { + "secretName": { + "description": "Name of the secret for TLS.", + "type": "string" + }, + "hosts": { + "description": "Host names for the TLS configuration.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "nodeSelector": { + "description": "Node selector for pod assignment.", + "type": "object" + }, + "tolerations": { + "description": "Tolerations for pod assignment.", + "type": "array" + }, + "affinity": { + "description": "Affinity rules for pod assignment.", + "type": "object" + }, + "podAntiAffinity": { + "description": "Pod anti-affinity configuration.", + "type": "string", + "enum": ["", "soft", "hard"], + "default": "" + }, + "podAntiAffinityTopologyKey": { + "description": "Topology key to use for pod anti-affinity.", + "type": "string" + }, + "topologySpreadConstraints": { + "description": "Topology spread constraints for pod assignment.", + "type": "array", + "items": { + "type": "object", + "required": ["maxSkew", "topologyKey", "whenUnsatisfiable", "labelSelector"], + "properties": { + "maxSkew": { + "type": "integer" + }, + "topologyKey": { + "type": "string" + }, + "whenUnsatisfiable": { + "type": "string", + "enum": ["DoNotSchedule", "ScheduleAnyway"] + }, + "labelSelector": { + "type": "object", + "required": ["matchLabels"], + "properties": { + "matchLabels": { + "type": "object" + } + } + } + } + } + }, + "statefulSet": { + "description": "StatefulSet configuration for managing pods.", + "type": "object", + "properties": { + "annotations": { + "type": "object" + } + } + }, + "podAnnotations": { + "description": "Annotations to add to the pods.", + "type": "object" + }, + "podLabels": { + "description": "Labels to add to the pods.", + "type": "object" + }, + "podDisruptionBudget": { + "description": "Pod disruption budget configuration.", + "type": "object", + "properties": { + "maxUnavailable": { + "type": "integer" + }, + "minAvailable": { + "type": "integer" + } + } + }, + "command": { + "description": "The command to be executed in the container.", + "type": "array", + "items": { + "type": "string" + } + }, + "persistence": { + "description": "Persistence configuration for storing data.", + "type": "object", + "required": ["enabled", "size"], + "properties": { + "enabled": { + "type": "boolean" + }, + "storageClass": { + "type": "string" + }, + "accessModes": { + "type": "array", + "items": { + "type": "string" + } + }, + "size": { + "type": "string" + }, + "annotations": { + "type": "object", + "description": "Custom annotations to apply to the PersistentVolumeClaim created by the Alertmanager StatefulSet.", + "additionalProperties": { + "type": "string" + }, + "default": {} + }, + "labels": { + "type": "object", + "description": "Custom labels to apply to the PersistentVolumeClaim created by the Alertmanager StatefulSet.", + "additionalProperties": { + "type": "string" + }, + "default": {} + } + } + }, + "configAnnotations": { + "description": "Annotations to be added to the Alertmanager configuration.", + "type": "object" + }, + "config": { + "description": "Alertmanager configuration.", + "type": "object", + "properties": { + "enabled": { + "description": "Whether to create alermanager configmap or not.", + "type": "boolean" + }, + "global": { + "description": "Global configuration options.", + "type": "object" + }, + "templates": { + "description": "Alertmanager template files.", + "type": "array", + "items": { + "type": "string" + } + }, + "receivers": { + "description": "Alert receivers configuration.", + "type": "array", + "items": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "description": "The unique name of the receiver.", + "type": "string" + } + } + } + }, + "route": { + "description": "Alert routing configuration.", + "type": "object", + "$ref": "#/definitions/config/route" + } + } + }, + "configmapReload": { + "description": "Monitors ConfigMap changes and POSTs to a URL.", + "type": "object", + "properties": { + "enabled": { + "description": "Specifies whether the configmap-reload container should be deployed.", + "type": "boolean", + "default": false + }, + "name": { + "description": "The name of the configmap-reload container.", + "type": "string" + }, + "image": { + "description": "The container image for the configmap-reload container.", + "$ref": "#/definitions/image" + }, + "containerPort": { + "description": "Port number for the configmap-reload container.", + "type": "integer" + }, + "resources": { + "description": "Resource requests and limits for the configmap-reload container.", + "$ref": "#/definitions/resources" + } + } + }, + "templates": { + "description": "Custom templates used by Alertmanager.", + "type": "object" + }, + "extraVolumeMounts": { + "description": "List of volume mounts for the Container.", + "$ref": "#/definitions/volumeMounts" + }, + "extraVolumes": { + "description": "Additional volumes to be mounted in the Alertmanager pod.", + "type": "array", + "default": [], + "items": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string" + } + } + } + }, + "extraEnv": { + "description": "List of environment variables for the Container.", + "$ref": "#/definitions/env" + }, + "testFramework": { + "description": "Configuration for the test Pod.", + "type": "object", + "properties": { + "enabled": { + "description": "Specifies whether the test Pod is enabled.", + "type": "boolean", + "default": false + }, + "annotations": { + "description": "Annotations to be added to the test Pod.", + "type": "object" + } + } + }, + "verticalPodAutoscaler": { + "description": "Vertical Pod Autoscaling configuration.", + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "default": false + }, + "recommenders": { + "type": "array" + }, + "updatePolicy": { + "type": "object" + }, + "resourcePolicy": { + "type": "object" + } + } + }, + "extraPodConfigs": { + "description": "Object to allow users to add additional Pod configuration like dnsPolicy or hostNetwork", + "type": "object" + } + } +} diff --git a/utils/assets/charts/prometheus/charts/alertmanager/values.yaml b/utils/assets/charts/prometheus/charts/alertmanager/values.yaml new file mode 100644 index 0000000..e4fae62 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/alertmanager/values.yaml @@ -0,0 +1,440 @@ +# yaml-language-server: $schema=values.schema.json +# Default values for alertmanager. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +# Number of old history to retain to allow rollback +# Default Kubernetes value is set to 10 +revisionHistoryLimit: 10 + +image: + repository: quay.io/prometheus/alertmanager + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +# Full external URL where alertmanager is reachable, used for backlinks. +baseURL: "" + +extraArgs: {} + +## Additional Alertmanager Secret mounts +# Defines additional mounts with secrets. Secrets must be manually created in the namespace. +extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # subPath: "" + # secretName: alertmanager-secret-files + # readOnly: true + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" +## namespaceOverride overrides the namespace which the resources will be deployed in +namespaceOverride: "" + +automountServiceAccountToken: true + +## Running within a user namespace. +# Kubernetes server must be at or later than version v1.25. +# Kubernetes v1.25 through to v1.27 recognise UserNamespacesStatelessPodsSupport. +# Kubernetes v1.28 through to v1.32 need to enable the UserNamespacesSupport feature gate. +hostUsers: false + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# Sets priorityClassName in alertmanager pod +priorityClassName: "" + +# Sets schedulerName in alertmanager pod +schedulerName: "" + +podSecurityContext: + fsGroup: 65534 +dnsConfig: {} + # nameservers: + # - 1.2.3.4 + # searches: + # - ns1.svc.cluster-domain.example + # - my.dns.search.suffix + # options: + # - name: ndots + # value: "2" + # - name: edns0 +hostAliases: [] + # - ip: "127.0.0.1" + # hostnames: + # - "foo.local" + # - "bar.local" + # - ip: "10.1.2.3" + # hostnames: + # - "foo.remote" + # - "bar.remote" +securityContext: + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + runAsUser: 65534 + runAsNonRoot: true + runAsGroup: 65534 + +additionalPeers: [] + +## Additional InitContainers to initialize the pod +## +extraInitContainers: [] + +## Additional containers to add to the stateful set. This will allow to setup sidecarContainers like a proxy to integrate +## alertmanager with an external tool like teams that has not direct integration. +## +extraContainers: [] + +containerPortName: &containerPortName http + +livenessProbe: + httpGet: + path: / + port: *containerPortName + +readinessProbe: + httpGet: + path: / + port: *containerPortName + +service: + annotations: {} + labels: {} + type: ClusterIP + port: 9093 + clusterPort: 9094 + loadBalancerIP: "" # Assign ext IP when Service type is LoadBalancer + loadBalancerSourceRanges: [] # Only allow access to loadBalancerIP from these IPs + # if you want to force a specific nodePort. Must be use with service.type=NodePort + # nodePort: + + # Optionally specify extra list of additional ports exposed on both services + extraPorts: [] + + # ip dual stack + ipDualStack: + enabled: false + ipFamilies: ["IPv6", "IPv4"] + ipFamilyPolicy: "PreferDualStack" + +# Configuration for creating a separate Service for each statefulset Alertmanager replica +# +servicePerReplica: + enabled: false + annotations: {} + + # Loadbalancer source IP ranges + # Only used if servicePerReplica.type is "LoadBalancer" + loadBalancerSourceRanges: [] + + # Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints + # + externalTrafficPolicy: Cluster + + # Service type + # + type: ClusterIP + +ingress: + enabled: false + className: "" + labels: {} + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: alertmanager.domain.com + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - alertmanager.domain.com + +# Configuration for creating an Ingress that will map to each Alertmanager replica service +# alertmanager.servicePerReplica must be enabled +# +ingressPerReplica: + enabled: false + + # className for the ingresses + # + className: "" + + annotations: {} + labels: {} + + # Final form of the hostname for each per replica ingress is + # {{ ingressPerReplica.hostPrefix }}-{{ $replicaNumber }}.{{ ingressPerReplica.hostDomain }} + # + # Prefix for the per replica ingress that will have `-$replicaNumber` + # appended to the end + hostPrefix: "alertmanager" + # Domain that will be used for the per replica ingress + hostDomain: "domain.com" + + # Paths to use for ingress rules + # + paths: + - / + + # PathType for ingress rules + # + pathType: ImplementationSpecific + + # Secret name containing the TLS certificate for alertmanager per replica ingress + # Secret must be manually created in the namespace + tlsSecretName: "" + + # Separated secret for each per replica Ingress. Can be used together with cert-manager + # + tlsSecretPerReplica: + enabled: false + # Final form of the secret for each per replica ingress is + # {{ tlsSecretPerReplica.prefix }}-{{ $replicaNumber }} + # + prefix: "alertmanager" + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 10m + # memory: 32Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +## Pod anti-affinity can prevent the scheduler from placing Alertmanager replicas on the same node. +## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. +## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. +## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. +## +podAntiAffinity: "" + +## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. +## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone +## +podAntiAffinityTopologyKey: kubernetes.io/hostname + +## Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. +## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: failure-domain.beta.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: alertmanager + +statefulSet: + annotations: {} + +## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to +## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). +## This is an alpha field from kubernetes 1.22 until 1.24 which requires enabling the StatefulSetMinReadySeconds +## feature gate. +## Ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#minimum-ready-seconds +minReadySeconds: 0 + +podAnnotations: {} +podLabels: {} + +# Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} + # maxUnavailable: 1 + # minAvailable: 1 + +command: [] + +persistence: + ## If true, storage will create or use Persistence Volume + ## If false, storage will use emptyDir + ## + enabled: true + + ## Custom annotations for the PVC created by the alertmanager StatefulSet. + ## Useful for configuring storage provider options such as disk type, KMS encryption keys, or custom volume name prefixes. + annotations: {} + + ## Custom labels for the PVC created by the alertmanager StatefulSet. + ## Useful for selecting, grouping, and organizing so that they can be queried or targeted in deployments, policies, etc. + labels: {} + + ## Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + # storageClass: "-" + accessModes: + - ReadWriteOnce + size: 50Mi + + ## Configure emptyDir volume + ## + emptyDir: {} + +configAnnotations: {} + ## For example if you want to provide private data from a secret vault + ## https://github.com/banzaicloud/bank-vaults/tree/main/charts/vault-secrets-webhook + ## P.s.: Add option `configMapMutation: true` for vault-secrets-webhook + # vault.security.banzaicloud.io/vault-role: "admin" + # vault.security.banzaicloud.io/vault-addr: "https://vault.vault.svc.cluster.local:8200" + # vault.security.banzaicloud.io/vault-skip-verify: "true" + # vault.security.banzaicloud.io/vault-path: "kubernetes" + ## Example for inject secret + # slack_api_url: '${vault:secret/data/slack-hook-alerts#URL}' + +config: + enabled: true + global: {} + # slack_api_url: '' + + templates: + - '/etc/alertmanager/*.tmpl' + + receivers: + - name: default-receiver + # slack_configs: + # - channel: '@you' + # send_resolved: true + + route: + group_wait: 10s + group_interval: 5m + receiver: default-receiver + repeat_interval: 3h + +## Monitors ConfigMap changes and POSTs to a URL +## Ref: https://github.com/prometheus-operator/prometheus-operator/tree/main/cmd/prometheus-config-reloader +## +configmapReload: + ## If false, the configmap-reload container will not be deployed + ## + enabled: false + + ## configmap-reload container name + ## + name: configmap-reload + + ## configmap-reload container image + ## + image: + repository: quay.io/prometheus-operator/prometheus-config-reloader + tag: v0.86.1 + pullPolicy: IfNotPresent + + # containerPort: 9533 + + ## configmap-reload resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + + livenessProbe: {} + # httpGet: + # path: /healthz + # port: 8080 + # scheme: HTTP + readinessProbe: {} + # httpGet: + # path: /healthz + # port: 8080 + # scheme: HTTP + + extraArgs: {} + + ## Optionally specify extra list of additional volumeMounts + extraVolumeMounts: [] + # - name: extras + # mountPath: /usr/share/extras + # readOnly: true + + ## Optionally specify extra environment variables to add to alertmanager container + extraEnv: [] + # - name: FOO + # value: BAR + + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsUser: 65534 + # runAsNonRoot: true + # runAsGroup: 65534 + +templates: {} +# alertmanager.tmpl: |- + +## Optionally specify extra list of additional volumeMounts +extraVolumeMounts: [] + # - name: extras + # mountPath: /usr/share/extras + # readOnly: true + +## Optionally specify extra list of additional volumes +extraVolumes: [] + # - name: extras + # emptyDir: {} + +## Optionally specify extra environment variables to add to alertmanager container +extraEnv: [] + # - name: FOO + # value: BAR + +testFramework: + enabled: false + annotations: + "helm.sh/hook": test-success + # "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + +# --- Vertical Pod Autoscaler +verticalPodAutoscaler: + # -- Use VPA for alertmanager + enabled: false + # recommenders: + # - name: 'alternative' + # updatePolicy: + # updateMode: "Auto" + # minReplicas: 1 + # resourcePolicy: + # containerPolicies: + # - containerName: '*' + # minAllowed: + # cpu: 100m + # memory: 128Mi + # maxAllowed: + # cpu: 1 + # memory: 500Mi + # controlledResources: ["cpu", "memory"] + +# --- Extra Pod Configs +extraPodConfigs: {} + # dnsPolicy: ClusterFirstWithHostNet + # hostNetwork: true diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/.helmignore b/utils/assets/charts/prometheus/charts/kube-state-metrics/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/Chart.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/Chart.yaml new file mode 100644 index 0000000..6f39b66 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/Chart.yaml @@ -0,0 +1,29 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts +apiVersion: v2 +appVersion: 2.17.0 +description: Install kube-state-metrics to generate and expose cluster-level metrics +home: https://github.com/kubernetes/kube-state-metrics/ +keywords: +- metric +- monitoring +- prometheus +- kubernetes +maintainers: +- email: tariq.ibrahim@mulesoft.com + name: tariq1890 + url: https://github.com/tariq1890 +- email: manuel@rueg.eu + name: mrueg + url: https://github.com/mrueg +- email: david@0xdc.me + name: dotdc + url: https://github.com/dotdc +name: kube-state-metrics +sources: +- https://github.com/kubernetes/kube-state-metrics/ +type: application +version: 6.4.1 diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/README.md b/utils/assets/charts/prometheus/charts/kube-state-metrics/README.md new file mode 100644 index 0000000..9348d4c --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/README.md @@ -0,0 +1,87 @@ +# kube-state-metrics Helm Chart + +Installs the [kube-state-metrics agent](https://github.com/kubernetes/kube-state-metrics). + +## Usage + +The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/). + +- OCI Artifact: `oci://ghcr.io/prometheus-community/charts/kube-state-metrics` +- Helm Repository: `https://prometheus-community.github.io/helm-charts` with chart `kube-state-metrics` + +The installation instructions use the OCI registry. Refer to the [`helm repo`]([`helm repo`](https://helm.sh/docs/helm/helm_repo/)) command documentation for information on installing charts via the traditional repository. + +### Install Chart + +```console +helm install [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/kube-state-metrics [flags] +``` + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +### Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +### Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/kube-state-metrics [flags] +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +#### Migrating from stable/kube-state-metrics and kubernetes/kube-state-metrics + +You can upgrade in-place: + +1. [upgrade](#upgrading-chart) your existing release name using the new chart repository + +## Upgrading to v6.0.0 + +This version drops support for deprecated Pod Security Policy resources. + +## Upgrading to v3.0.0 + +v3.0.0 includes kube-state-metrics v2.0, see the [changelog](https://github.com/kubernetes/kube-state-metrics/blob/release-2.0/CHANGELOG.md) for major changes on the application-side. + +The upgraded chart now the following changes: + +- Dropped support for helm v2 (helm v3 or later is required) +- collectors key was renamed to resources +- namespace key was renamed to namespaces + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments: + +```console +helm show values oci://ghcr.io/prometheus-community/charts/kube-state-metrics +``` + +### kube-rbac-proxy + +You can enable `kube-state-metrics` endpoint protection using `kube-rbac-proxy`. By setting `kubeRBACProxy.enabled: true`, this chart will deploy one RBAC proxy container per endpoint (metrics & telemetry). +To authorize access, authenticate your requests (via a `ServiceAccount` for example) with a `ClusterRole` attached such as: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kube-state-metrics-read +rules: + - apiGroups: [ "" ] + resources: ["services/kube-state-metrics"] + verbs: + - get +``` + +See [kube-rbac-proxy examples](https://github.com/brancz/kube-rbac-proxy/tree/master/examples/resource-attributes) for more details. diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt new file mode 100644 index 0000000..3589c24 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt @@ -0,0 +1,23 @@ +kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. +The exposed metrics can be found here: +https://github.com/kubernetes/kube-state-metrics/blob/master/docs/README.md#exposed-metrics + +The metrics are exported on the HTTP endpoint /metrics on the listening port. +In your case, {{ template "kube-state-metrics.fullname" . }}.{{ template "kube-state-metrics.namespace" . }}.svc.cluster.local:{{ .Values.service.port }}/metrics + +They are served either as plaintext or protobuf depending on the Accept header. +They are designed to be consumed either by Prometheus itself or by a scraper that is compatible with scraping a Prometheus client endpoint. + +{{- if .Values.kubeRBACProxy.enabled}} + +kube-rbac-proxy endpoint protections is enabled: +- Metrics endpoints are now HTTPS +- Ensure that the client authenticates the requests (e.g. via service account) with the following role permissions: +``` +rules: + - apiGroups: [ "" ] + resources: ["services/{{ template "kube-state-metrics.fullname" . }}"] + verbs: + - get +``` +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl new file mode 100644 index 0000000..c8cfa56 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl @@ -0,0 +1,186 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "kube-state-metrics.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "kube-state-metrics.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "kube-state-metrics.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "kube-state-metrics.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "kube-state-metrics.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kube-state-metrics.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Generate basic labels +*/}} +{{- define "kube-state-metrics.labels" }} +helm.sh/chart: {{ template "kube-state-metrics.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: metrics +app.kubernetes.io/part-of: {{ template "kube-state-metrics.name" . }} +{{- include "kube-state-metrics.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if .Values.customLabels }} +{{ tpl (toYaml .Values.customLabels) . }} +{{- end }} +{{- if .Values.releaseLabel }} +release: {{ .Release.Name }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kube-state-metrics.selectorLabels" }} +{{- if .Values.selectorOverride }} +{{ toYaml .Values.selectorOverride }} +{{- else }} +app.kubernetes.io/name: {{ include "kube-state-metrics.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- end }} + +{{/* Sets default scrape limits for servicemonitor */}} +{{- define "servicemonitor.scrapeLimits" -}} +{{- with .sampleLimit }} +sampleLimit: {{ . }} +{{- end }} +{{- with .targetLimit }} +targetLimit: {{ . }} +{{- end }} +{{- with .labelLimit }} +labelLimit: {{ . }} +{{- end }} +{{- with .labelNameLengthLimit }} +labelNameLengthLimit: {{ . }} +{{- end }} +{{- with .labelValueLengthLimit }} +labelValueLengthLimit: {{ . }} +{{- end }} +{{- end -}} + +{{/* Sets default scrape limits for scrapeconfig */}} +{{- define "scrapeconfig.scrapeLimits" -}} +{{- with .sampleLimit }} +sampleLimit: {{ . }} +{{- end }} +{{- with .targetLimit }} +targetLimit: {{ . }} +{{- end }} +{{- with .labelLimit }} +labelLimit: {{ . }} +{{- end }} +{{- with .labelNameLengthLimit }} +labelNameLengthLimit: {{ . }} +{{- end }} +{{- with .labelValueLengthLimit }} +labelValueLengthLimit: {{ . }} +{{- end }} +{{- end -}} + +{{/* +Formats imagePullSecrets. Input is (dict "Values" .Values "imagePullSecrets" .{specific imagePullSecrets}) +*/}} +{{- define "kube-state-metrics.imagePullSecrets" -}} +{{- range (concat .Values.global.imagePullSecrets .imagePullSecrets) }} + {{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml . | trim }} + {{- else }} +- name: {{ . }} + {{- end }} +{{- end }} +{{- end -}} + +{{/* +The image to use for kube-state-metrics +*/}} +{{- define "kube-state-metrics.image" -}} +{{- if .Values.image.sha }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s@%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.sha }} +{{- else }} +{{- printf "%s/%s:%s@%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.sha }} +{{- end }} +{{- else }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- else }} +{{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +The image to use for kubeRBACProxy +*/}} +{{- define "kubeRBACProxy.image" -}} +{{- if .Values.kubeRBACProxy.image.sha }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s@%s" .Values.global.imageRegistry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) .Values.kubeRBACProxy.image.sha }} +{{- else }} +{{- printf "%s/%s:%s@%s" .Values.kubeRBACProxy.image.registry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) .Values.kubeRBACProxy.image.sha }} +{{- end }} +{{- else }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s" .Values.global.imageRegistry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) }} +{{- else }} +{{- printf "%s/%s:%s" .Values.kubeRBACProxy.image.registry .Values.kubeRBACProxy.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.kubeRBACProxy.image.tag) }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +The name of the ConfigMap for the customResourceState config. +*/}} +{{- define "kube-state-metrics.crsConfigMapName" -}} + {{- if ne .Values.customResourceState.name "" }} + {{- .Values.customResourceState.name }} + {{- else }} + {{- template "kube-state-metrics.fullname" . }}-customresourcestate-config + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/ciliumnetworkpolicy.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/ciliumnetworkpolicy.yaml new file mode 100644 index 0000000..025cd47 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/ciliumnetworkpolicy.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.networkPolicy.enabled (eq .Values.networkPolicy.flavor "cilium") }} +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +spec: + endpointSelector: + matchLabels: + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + egress: + {{- if and .Values.networkPolicy.cilium .Values.networkPolicy.cilium.kubeApiServerSelector }} + {{ toYaml .Values.networkPolicy.cilium.kubeApiServerSelector | nindent 6 }} + {{- else }} + - toEntities: + - kube-apiserver + {{- end }} + ingress: + - toPorts: + - ports: + - port: {{ .Values.service.port | quote }} + protocol: TCP + {{- if .Values.selfMonitor.enabled }} + - port: {{ .Values.selfMonitor.telemetryPort | default 8081 | quote }} + protocol: TCP + {{ end }} +{{ end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..cf9f628 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.rbac.create .Values.rbac.useClusterRole -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole +{{- if .Values.rbac.useExistingRole }} + name: {{ .Values.rbac.useExistingRole }} +{{- else }} + name: {{ template "kube-state-metrics.fullname" . }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/crs-configmap.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/crs-configmap.yaml new file mode 100644 index 0000000..e64c4a7 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/crs-configmap.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.customResourceState.enabled .Values.customResourceState.create }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "kube-state-metrics.crsConfigMapName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} +data: + {{ .Values.customResourceState.key }}: | + {{- toYaml .Values.customResourceState.config | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml new file mode 100644 index 0000000..9425092 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml @@ -0,0 +1,379 @@ +apiVersion: apps/v1 +{{- if .Values.autosharding.enabled }} +kind: StatefulSet +{{- else }} +kind: Deployment +{{- end }} +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + replicas: {{ .Values.replicas }} + {{- if not .Values.autosharding.enabled }} + strategy: + type: {{ .Values.updateStrategy | default "RollingUpdate" }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- if .Values.autosharding.enabled }} + serviceName: {{ template "kube-state-metrics.fullname" . }} + volumeClaimTemplates: [] + {{- end }} + template: + metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.podAnnotations }} + annotations: + {{ toYaml .Values.podAnnotations | nindent 8 }} + {{- end }} + spec: + automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} + hostNetwork: {{ .Values.hostNetwork }} + serviceAccountName: {{ template "kube-state-metrics.serviceAccountName" . }} + {{- if .Values.securityContext.enabled }} + securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- with .Values.initContainers }} + initContainers: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .Values.dnsConfig }} + dnsConfig: {{ toYaml .Values.dnsConfig | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.dnsPolicy }} + containers: + {{- $servicePort := ternary .Values.kubeRBACProxy.port (.Values.service.port | default 8080) .Values.kubeRBACProxy.enabled}} + {{- $telemetryPort := ternary 9091 (.Values.selfMonitor.telemetryPort | default 8081) .Values.kubeRBACProxy.enabled}} + - name: {{ template "kube-state-metrics.name" . }} + {{- if .Values.autosharding.enabled }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.env }} + {{- toYaml .Values.env | nindent 8 }} + {{- end }} + {{ else }} + {{- if .Values.env }} + env: + {{- toYaml .Values.env | nindent 8 }} + {{- end }} + {{- end }} + args: + {{- if .Values.extraArgs }} + {{- .Values.extraArgs | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - --host=127.0.0.1 + {{- end }} + - --port={{ $servicePort }} + {{- if .Values.collectors }} + - --resources={{ .Values.collectors | join "," }} + {{- end }} + {{- if .Values.metricLabelsAllowlist }} + - --metric-labels-allowlist={{ .Values.metricLabelsAllowlist | join "," }} + {{- end }} + {{- if .Values.metricAnnotationsAllowList }} + - --metric-annotations-allowlist={{ .Values.metricAnnotationsAllowList | join "," }} + {{- end }} + {{- if .Values.metricAllowlist }} + - --metric-allowlist={{ .Values.metricAllowlist | join "," }} + {{- end }} + {{- if .Values.metricDenylist }} + - --metric-denylist={{ .Values.metricDenylist | join "," }} + {{- end }} + {{- $namespaces := list }} + {{- if .Values.namespaces }} + {{- range $ns := join "," .Values.namespaces | split "," }} + {{- $namespaces = append $namespaces (tpl $ns $) }} + {{- end }} + {{- end }} + {{- if .Values.releaseNamespace }} + {{- $namespaces = append $namespaces ( include "kube-state-metrics.namespace" . ) }} + {{- end }} + {{- if $namespaces }} + - --namespaces={{ $namespaces | mustUniq | join "," }} + {{- end }} + {{- if .Values.namespacesDenylist }} + - --namespaces-denylist={{ tpl (.Values.namespacesDenylist | join ",") $ }} + {{- end }} + {{- if .Values.autosharding.enabled }} + - --pod=$(POD_NAME) + - --pod-namespace=$(POD_NAMESPACE) + {{- end }} + {{- if .Values.kubeconfig.enabled }} + - --kubeconfig=/opt/k8s/.kube/config + {{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - --telemetry-host=127.0.0.1 + - --telemetry-port={{ $telemetryPort }} + {{- else }} + {{- if .Values.selfMonitor.telemetryHost }} + - --telemetry-host={{ .Values.selfMonitor.telemetryHost }} + {{- end }} + {{- if .Values.selfMonitor.telemetryPort }} + - --telemetry-port={{ $telemetryPort }} + {{- end }} + {{- end }} + {{- if .Values.customResourceState.enabled }} + - --custom-resource-state-config-file=/etc/customresourcestate/{{ .Values.customResourceState.key }} + {{- end }} + {{- if or (.Values.kubeconfig.enabled) (.Values.customResourceState.enabled) (.Values.volumeMounts) }} + volumeMounts: + {{- if .Values.kubeconfig.enabled }} + - name: kubeconfig + mountPath: /opt/k8s/.kube/ + readOnly: true + {{- end }} + {{- if .Values.customResourceState.enabled }} + - name: customresourcestate-config + mountPath: /etc/customresourcestate + readOnly: true + {{- end }} + {{- if .Values.volumeMounts }} +{{ toYaml .Values.volumeMounts | indent 8 }} + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + image: {{ include "kube-state-metrics.image" . }} + {{- if eq .Values.kubeRBACProxy.enabled false }} + ports: + - containerPort: {{ .Values.service.port | default 8080}} + name: http + {{- if .Values.selfMonitor.enabled }} + - containerPort: {{ $telemetryPort }} + name: metrics + {{- end }} + {{- end }} + {{- if .Values.startupProbe.enabled }} + startupProbe: + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + httpGet: + {{- if .Values.hostNetwork }} + host: 127.0.0.1 + {{- end }} + httpHeaders: + {{- range $_, $header := .Values.startupProbe.httpGet.httpHeaders }} + - name: {{ $header.name }} + value: {{ $header.value }} + {{- end }} + path: /healthz + {{- if .Values.kubeRBACProxy.enabled }} + port: http + scheme: HTTPS + {{- else }} + port: {{ $servicePort }} + scheme: {{ upper .Values.startupProbe.httpGet.scheme }} + {{- end }} + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + {{- end }} + livenessProbe: + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + httpGet: + {{- if .Values.hostNetwork }} + host: 127.0.0.1 + {{- end }} + httpHeaders: + {{- range $_, $header := .Values.livenessProbe.httpGet.httpHeaders }} + - name: {{ $header.name }} + value: {{ $header.value }} + {{- end }} + path: /livez + {{- if .Values.kubeRBACProxy.enabled }} + port: http + scheme: HTTPS + {{- else }} + port: {{ $servicePort }} + scheme: {{ upper .Values.livenessProbe.httpGet.scheme }} + {{- end }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + readinessProbe: + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + httpGet: + {{- if .Values.hostNetwork }} + host: 127.0.0.1 + {{- end }} + httpHeaders: + {{- range $_, $header := .Values.readinessProbe.httpGet.httpHeaders }} + - name: {{ $header.name }} + value: {{ $header.value }} + {{- end }} + path: /readyz + {{- if .Values.kubeRBACProxy.enabled }} + port: metrics + scheme: HTTPS + {{- else }} + port: {{ $telemetryPort }} + scheme: {{ upper .Values.readinessProbe.httpGet.scheme }} + {{- end }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + resources: +{{ toYaml .Values.resources | indent 10 }} +{{- if .Values.containerSecurityContext }} + securityContext: +{{ toYaml .Values.containerSecurityContext | indent 10 }} +{{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - name: kube-rbac-proxy-http + args: + {{- if .Values.kubeRBACProxy.extraArgs }} + {{- .Values.kubeRBACProxy.extraArgs | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.kubeRBACProxy.ignoreProbePaths }} + - --ignore-paths=/livez,/readyz + {{- end }} + - --secure-listen-address=:{{ .Values.service.port | default 8080}} + - --upstream=http://127.0.0.1:{{ $servicePort }}/ + - --proxy-endpoints-port={{ .Values.kubeRBACProxy.proxyEndpointsPort | default 8888 }} + - --config-file=/etc/kube-rbac-proxy-config/config-file.yaml + volumeMounts: + - name: kube-rbac-proxy-config + mountPath: /etc/kube-rbac-proxy-config + {{- with .Values.kubeRBACProxy.volumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + imagePullPolicy: {{ .Values.kubeRBACProxy.image.pullPolicy }} + image: {{ include "kubeRBACProxy.image" . }} + ports: + - containerPort: {{ .Values.service.port | default 8080}} + name: http + - containerPort: {{ .Values.kubeRBACProxy.proxyEndpointsPort | default 8888 }} + name: http-healthz + readinessProbe: + httpGet: + scheme: HTTPS + port: http-healthz + path: /healthz + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.kubeRBACProxy.resources }} + resources: +{{ toYaml .Values.kubeRBACProxy.resources | indent 10 }} +{{- end }} +{{- if .Values.kubeRBACProxy.containerSecurityContext }} + securityContext: +{{ toYaml .Values.kubeRBACProxy.containerSecurityContext | indent 10 }} +{{- end }} + {{- if .Values.selfMonitor.enabled }} + - name: kube-rbac-proxy-telemetry + args: + {{- if .Values.kubeRBACProxy.extraArgs }} + {{- .Values.kubeRBACProxy.extraArgs | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.kubeRBACProxy.ignoreProbePaths }} + - --ignore-paths=/livez,/readyz + {{- end }} + - --secure-listen-address=:{{ .Values.selfMonitor.telemetryPort | default 8081 }} + - --upstream=http://127.0.0.1:{{ $telemetryPort }}/ + - --proxy-endpoints-port=8889 + - --config-file=/etc/kube-rbac-proxy-config/config-file.yaml + volumeMounts: + - name: kube-rbac-proxy-config + mountPath: /etc/kube-rbac-proxy-config + {{- with .Values.kubeRBACProxy.volumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + imagePullPolicy: {{ .Values.kubeRBACProxy.image.pullPolicy }} + image: {{ include "kubeRBACProxy.image" . }} + ports: + - containerPort: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + name: metrics + - containerPort: 8889 + name: metrics-healthz + readinessProbe: + httpGet: + scheme: HTTPS + port: 8889 + path: healthz + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.kubeRBACProxy.resources }} + resources: +{{ toYaml .Values.kubeRBACProxy.resources | indent 10 }} +{{- end }} +{{- if .Values.kubeRBACProxy.containerSecurityContext }} + securityContext: +{{ toYaml .Values.kubeRBACProxy.containerSecurityContext | indent 10 }} +{{- end }} + {{- end }} + {{- end }} + {{- with .Values.containers }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- if or .Values.imagePullSecrets .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- include "kube-state-metrics.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.imagePullSecrets) | indent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: + {{- if kindIs "map" .Values.affinity }} + {{- toYaml .Values.affinity | nindent 8 }} + {{- else }} + {{- tpl .Values.affinity $ | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ tpl (toYaml .) $ | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ tpl (toYaml .) $ | indent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.topologySpreadConstraints | indent 8 }} + {{- end }} + {{- if or (.Values.kubeconfig.enabled) (.Values.customResourceState.enabled) (.Values.volumes) (.Values.kubeRBACProxy.enabled) }} + volumes: + {{- if .Values.kubeconfig.enabled}} + - name: kubeconfig + secret: + secretName: {{ template "kube-state-metrics.fullname" . }}-kubeconfig + {{- end }} + {{- if .Values.kubeRBACProxy.enabled}} + - name: kube-rbac-proxy-config + configMap: + name: {{ template "kube-state-metrics.fullname" . }}-rbac-config + {{- end }} + {{- if .Values.customResourceState.enabled}} + - name: customresourcestate-config + configMap: + name: {{ template "kube-state-metrics.crsConfigMapName" . }} + {{- end }} + {{- if .Values.volumes }} +{{ toYaml .Values.volumes | indent 8 }} + {{- end }} + {{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/extra-manifests.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/extra-manifests.yaml new file mode 100644 index 0000000..567f7bf --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraManifests }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/kubeconfig-secret.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/kubeconfig-secret.yaml new file mode 100644 index 0000000..6af0084 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/kubeconfig-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.kubeconfig.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "kube-state-metrics.fullname" . }}-kubeconfig + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +type: Opaque +data: + config: '{{ .Values.kubeconfig.secret }}' +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/networkpolicy.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/networkpolicy.yaml new file mode 100644 index 0000000..abe292a --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/networkpolicy.yaml @@ -0,0 +1,43 @@ +{{- if and .Values.networkPolicy.enabled (eq .Values.networkPolicy.flavor "kubernetes") }} +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +spec: + {{- if .Values.networkPolicy.egress }} + ## Deny all egress by default + egress: + {{- toYaml .Values.networkPolicy.egress | nindent 4 }} + {{- end }} + ingress: + {{- if .Values.networkPolicy.ingress }} + {{- toYaml .Values.networkPolicy.ingress | nindent 4 }} + {{- else }} + ## Allow ingress on default ports by default + - ports: + - port: http + protocol: TCP + {{- if .Values.selfMonitor.enabled }} + {{- $telemetryPort := ternary 9091 (.Values.selfMonitor.telemetryPort | default 8081) .Values.kubeRBACProxy.enabled}} + - port: {{ $telemetryPort }} + protocol: TCP + {{- end }} + {{- end }} + podSelector: + {{- if .Values.networkPolicy.podSelector }} + {{- toYaml .Values.networkPolicy.podSelector | nindent 4 }} + {{- else }} + matchLabels: + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + {{- end }} + policyTypes: + - Ingress + - Egress +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/pdb.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/pdb.yaml new file mode 100644 index 0000000..2d1e64b --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/pdb.yaml @@ -0,0 +1,14 @@ +{{- if .Values.podDisruptionBudget -}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} +{{ toYaml .Values.podDisruptionBudget | indent 2 }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/rbac-configmap.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/rbac-configmap.yaml new file mode 100644 index 0000000..671dc9d --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/rbac-configmap.yaml @@ -0,0 +1,22 @@ +{{- if .Values.kubeRBACProxy.enabled}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "kube-state-metrics.fullname" . }}-rbac-config + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- if .Values.annotations }} + annotations: + {{ toYaml .Values.annotations | nindent 4 }} + {{- end }} +data: + config-file.yaml: |+ + authorization: + resourceAttributes: + namespace: {{ template "kube-state-metrics.namespace" . }} + apiVersion: v1 + resource: services + subresource: {{ template "kube-state-metrics.fullname" . }} + name: {{ template "kube-state-metrics.fullname" . }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/role.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/role.yaml new file mode 100644 index 0000000..4b6537b --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/role.yaml @@ -0,0 +1,236 @@ +{{- if and (eq .Values.rbac.create true) (not .Values.rbac.useExistingRole) -}} +{{- range (ternary (join "," .Values.namespaces | split "," ) (list "") (eq $.Values.rbac.useClusterRole false)) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if eq $.Values.rbac.useClusterRole false }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + labels: + {{- include "kube-state-metrics.labels" $ | indent 4 }} + name: {{ template "kube-state-metrics.fullname" $ }} +{{- if eq $.Values.rbac.useClusterRole false }} + namespace: {{ . }} +{{- end }} +rules: +{{ if has "certificatesigningrequests" $.Values.collectors }} +- apiGroups: ["certificates.k8s.io"] + resources: + - certificatesigningrequests + verbs: ["list", "watch"] +{{ end -}} +{{ if has "configmaps" $.Values.collectors }} +- apiGroups: [""] + resources: + - configmaps + verbs: ["list", "watch"] +{{ end -}} +{{ if has "cronjobs" $.Values.collectors }} +- apiGroups: ["batch"] + resources: + - cronjobs + verbs: ["list", "watch"] +{{ end -}} +{{ if has "daemonsets" $.Values.collectors }} +- apiGroups: ["apps"] + resources: + - daemonsets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "deployments" $.Values.collectors }} +- apiGroups: ["apps"] + resources: + - deployments + verbs: ["list", "watch"] +{{ end -}} +{{ if has "endpoints" $.Values.collectors }} +- apiGroups: [""] + resources: + - endpoints + verbs: ["list", "watch"] +{{ end -}} +{{ if has "endpointslices" $.Values.collectors }} +- apiGroups: ["discovery.k8s.io"] + resources: + - endpointslices + verbs: ["list", "watch"] +{{ end -}} +{{ if has "horizontalpodautoscalers" $.Values.collectors }} +- apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: ["list", "watch"] +{{ end -}} +{{ if has "ingresses" $.Values.collectors }} +- apiGroups: ["networking.k8s.io"] + resources: + - ingresses + verbs: ["list", "watch"] +{{ end -}} +{{ if has "jobs" $.Values.collectors }} +- apiGroups: ["batch"] + resources: + - jobs + verbs: ["list", "watch"] +{{ end -}} +{{ if has "leases" $.Values.collectors }} +- apiGroups: ["coordination.k8s.io"] + resources: + - leases + verbs: ["list", "watch"] +{{ end -}} +{{ if has "limitranges" $.Values.collectors }} +- apiGroups: [""] + resources: + - limitranges + verbs: ["list", "watch"] +{{ end -}} +{{ if has "mutatingwebhookconfigurations" $.Values.collectors }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - mutatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if has "namespaces" $.Values.collectors }} +- apiGroups: [""] + resources: + - namespaces + verbs: ["list", "watch"] +{{ end -}} +{{ if has "networkpolicies" $.Values.collectors }} +- apiGroups: ["networking.k8s.io"] + resources: + - networkpolicies + verbs: ["list", "watch"] +{{ end -}} +{{ if has "ingressclasses" $.Values.collectors }} +- apiGroups: ["networking.k8s.io"] + resources: + - ingressclasses + verbs: ["list", "watch"] +{{ end -}} +{{ if has "clusterrolebindings" $.Values.collectors }} +- apiGroups: ["rbac.authorization.k8s.io"] + resources: + - clusterrolebindings + verbs: ["list", "watch"] +{{ end -}} +{{ if has "clusterroles" $.Values.collectors }} +- apiGroups: ["rbac.authorization.k8s.io"] + resources: + - clusterroles + verbs: ["list", "watch"] +{{ end -}} +{{ if has "roles" $.Values.collectors }} +- apiGroups: ["rbac.authorization.k8s.io"] + resources: + - roles + verbs: ["list", "watch"] +{{ end -}} +{{ if has "nodes" $.Values.collectors }} +- apiGroups: [""] + resources: + - nodes + verbs: ["list", "watch"] +{{ end -}} +{{ if has "persistentvolumeclaims" $.Values.collectors }} +- apiGroups: [""] + resources: + - persistentvolumeclaims + verbs: ["list", "watch"] +{{ end -}} +{{ if has "persistentvolumes" $.Values.collectors }} +- apiGroups: [""] + resources: + - persistentvolumes + verbs: ["list", "watch"] +{{ end -}} +{{ if has "poddisruptionbudgets" $.Values.collectors }} +- apiGroups: ["policy"] + resources: + - poddisruptionbudgets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "pods" $.Values.collectors }} +- apiGroups: [""] + resources: + - pods + verbs: ["list", "watch"] +{{ end -}} +{{ if has "replicasets" $.Values.collectors }} +- apiGroups: ["apps"] + resources: + - replicasets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "replicationcontrollers" $.Values.collectors }} +- apiGroups: [""] + resources: + - replicationcontrollers + verbs: ["list", "watch"] +{{ end -}} +{{ if has "resourcequotas" $.Values.collectors }} +- apiGroups: [""] + resources: + - resourcequotas + verbs: ["list", "watch"] +{{ end -}} +{{ if has "secrets" $.Values.collectors }} +- apiGroups: [""] + resources: + - secrets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "services" $.Values.collectors }} +- apiGroups: [""] + resources: + - services + verbs: ["list", "watch"] +{{ end -}} +{{ if has "statefulsets" $.Values.collectors }} +- apiGroups: ["apps"] + resources: + - statefulsets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "storageclasses" $.Values.collectors }} +- apiGroups: ["storage.k8s.io"] + resources: + - storageclasses + verbs: ["list", "watch"] +{{ end -}} +{{ if has "validatingwebhookconfigurations" $.Values.collectors }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - validatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if has "volumeattachments" $.Values.collectors }} +- apiGroups: ["storage.k8s.io"] + resources: + - volumeattachments + verbs: ["list", "watch"] +{{ end -}} +{{- if $.Values.kubeRBACProxy.enabled }} +- apiGroups: ["authentication.k8s.io"] + resources: + - tokenreviews + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: + - subjectaccessreviews + verbs: ["create"] +{{- end }} +{{- if $.Values.customResourceState.enabled }} +- apiGroups: ["apiextensions.k8s.io"] + resources: + - customresourcedefinitions + verbs: ["list", "watch"] +{{- end }} +{{ if $.Values.rbac.extraRules }} +{{ toYaml $.Values.rbac.extraRules }} +{{ end }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/rolebinding.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/rolebinding.yaml new file mode 100644 index 0000000..330651b --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and (eq .Values.rbac.create true) (eq .Values.rbac.useClusterRole false) -}} +{{- range (join "," $.Values.namespaces) | split "," }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" $ | indent 4 }} + name: {{ template "kube-state-metrics.fullname" $ }} + namespace: {{ . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role +{{- if (not $.Values.rbac.useExistingRole) }} + name: {{ template "kube-state-metrics.fullname" $ }} +{{- else }} + name: {{ $.Values.rbac.useExistingRole }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" $ }} + namespace: {{ template "kube-state-metrics.namespace" $ }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/scrapeconfig.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/scrapeconfig.yaml new file mode 100644 index 0000000..028f3d1 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/scrapeconfig.yaml @@ -0,0 +1,60 @@ +{{- if .Values.prometheus.scrapeconfig.enabled }} +apiVersion: monitoring.coreos.com/v1alpha1 +kind: ScrapeConfig +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- with .Values.prometheus.scrapeconfig.additionalLabels }} + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} + {{- with .Values.prometheus.scrapeconfig.annotations }} + annotations: + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} +spec: + {{- include "scrapeconfig.scrapeLimits" .Values.prometheus.scrapeconfig | indent 2 }} + staticConfigs: + - targets: + - {{ template "kube-state-metrics.fullname" . }}.{{ template "kube-state-metrics.namespace" . }}.svc:{{ .Values.service.port }} + {{- if .Values.prometheus.scrapeconfig.staticConfigLabels}} + labels: + {{- with .Values.prometheus.scrapeconfig.staticConfigLabels }} + {{- tpl (toYaml . | nindent 8) $ }} + {{- end }} + {{- end }} +{{- if .Values.prometheus.scrapeconfig.jobName }} + jobName: {{ .Values.prometheus.scrapeconfig.jobName }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.honorLabels }} + honorLabels: true +{{- end }} +{{- if .Values.prometheus.scrapeconfig.scrapeInterval }} + scrapeInterval: {{ .Values.prometheus.scrapeconfig.scrapeInterval }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.scrapeconfig.scrapeTimeout }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.proxyUrl }} + proxyUrl: {{ .Values.prometheus.scrapeconfig.proxyUrl }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.enableHttp2 }} + enableHttp2: {{ .Values.prometheus.scrapeconfig.enableHttp2 }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.scrapeconfig.metricRelabelings | nindent 4 }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.scrapeconfig.relabelings | nindent 4 }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.scheme }} + scheme: {{ .Values.prometheus.scrapeconfig.scheme }} +{{- end }} +{{- if .Values.prometheus.scrapeconfig.tlsConfig }} + tlsConfig: + {{- toYaml (.Values.prometheus.scrapeconfig.tlsConfig ) | nindent 4 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/service.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/service.yaml new file mode 100644 index 0000000..4bfa7df --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/service.yaml @@ -0,0 +1,53 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + annotations: + {{- if .Values.prometheusScrape }} + prometheus.io/scrape: '{{ .Values.prometheusScrape }}' + {{- end }} + {{- if .Values.service.annotations }} + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + type: "{{ .Values.service.type }}" + {{- if .Values.service.ipDualStack.enabled }} + ipFamilies: {{ toYaml .Values.service.ipDualStack.ipFamilies | nindent 4 }} + ipFamilyPolicy: {{ .Values.service.ipDualStack.ipFamilyPolicy }} + {{- end }} + ports: + - name: http + protocol: TCP + port: {{ .Values.service.port | default 8080}} + {{- if ( and (eq .Values.service.type "NodePort" ) (not (empty .Values.service.nodePort)) ) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + targetPort: http + {{ if .Values.selfMonitor.enabled }} + - name: metrics + protocol: TCP + port: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + targetPort: metrics + {{- if ( and (eq .Values.service.type "NodePort" ) (not (empty .Values.service.nodePort)) ) }} + nodePort: {{ .Values.selfMonitor.telemetryNodePort }} + {{- end }} + {{ end }} +{{- if .Values.service.loadBalancerIP }} + loadBalancerIP: "{{ .Values.service.loadBalancerIP }}" +{{- end }} +{{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} +{{- if .Values.autosharding.enabled }} + clusterIP: None +{{- else if .Values.service.clusterIP }} + clusterIP: "{{ .Values.service.clusterIP }}" +{{- end }} + selector: + {{- include "kube-state-metrics.selectorLabels" . | indent 4 }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml new file mode 100644 index 0000000..c302bc7 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- if .Values.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.serviceAccount.annotations | indent 4 }} +{{- end }} +{{- if or .Values.serviceAccount.imagePullSecrets .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- include "kube-state-metrics.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.serviceAccount.imagePullSecrets) | indent 2 }} +{{- end }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml new file mode 100644 index 0000000..99d7fa9 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml @@ -0,0 +1,120 @@ +{{- if .Values.prometheus.monitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- with .Values.prometheus.monitor.additionalLabels }} + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} + {{- with .Values.prometheus.monitor.annotations }} + annotations: + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} +spec: + jobLabel: {{ default "app.kubernetes.io/name" .Values.prometheus.monitor.jobLabel }} + {{- with .Values.prometheus.monitor.targetLabels }} + targetLabels: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + {{- with .Values.prometheus.monitor.podTargetLabels }} + podTargetLabels: + {{- toYaml . | trim | nindent 4 }} + {{- end }} + {{- include "servicemonitor.scrapeLimits" .Values.prometheus.monitor | indent 2 }} + {{- if .Values.prometheus.monitor.namespaceSelector }} + namespaceSelector: + matchNames: + {{- with .Values.prometheus.monitor.namespaceSelector }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + selector: + matchLabels: + {{- with .Values.prometheus.monitor.selectorOverride }} + {{- toYaml . | nindent 6 }} + {{- else }} + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + {{- end }} + endpoints: + - port: http + {{- if or .Values.prometheus.monitor.http.interval .Values.prometheus.monitor.interval }} + interval: {{ .Values.prometheus.monitor.http.interval | default .Values.prometheus.monitor.interval }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.scrapeTimeout .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.monitor.http.scrapeTimeout | default .Values.prometheus.monitor.scrapeTimeout }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.proxyUrl .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ .Values.prometheus.monitor.http.proxyUrl | default .Values.prometheus.monitor.proxyUrl }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.enableHttp2 .Values.prometheus.monitor.enableHttp2 }} + enableHttp2: {{ .Values.prometheus.monitor.http.enableHttp2 | default .Values.prometheus.monitor.enableHttp2 }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.honorLabels .Values.prometheus.monitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if or .Values.prometheus.monitor.http.metricRelabelings .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml (.Values.prometheus.monitor.http.metricRelabelings | default .Values.prometheus.monitor.metricRelabelings) | nindent 8 }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.relabelings .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml (.Values.prometheus.monitor.http.relabelings | default .Values.prometheus.monitor.relabelings) | nindent 8 }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.scheme .Values.prometheus.monitor.scheme }} + scheme: {{ .Values.prometheus.monitor.http.scheme | default .Values.prometheus.monitor.scheme }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.tlsConfig .Values.prometheus.monitor.tlsConfig }} + tlsConfig: + {{- toYaml (.Values.prometheus.monitor.http.tlsConfig | default .Values.prometheus.monitor.tlsConfig) | nindent 8 }} + {{- end }} + {{- if or .Values.prometheus.monitor.http.bearerTokenFile .Values.prometheus.monitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.prometheus.monitor.http.bearerTokenFile | default .Values.prometheus.monitor.bearerTokenFile }} + {{- end }} + {{- with (.Values.prometheus.monitor.http.bearerTokenSecret | default .Values.prometheus.monitor.bearerTokenSecret) }} + bearerTokenSecret: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.selfMonitor.enabled }} + - port: metrics + {{- if or .Values.prometheus.monitor.metrics.interval .Values.prometheus.monitor.interval }} + interval: {{ .Values.prometheus.monitor.metrics.interval | default .Values.prometheus.monitor.interval }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.scrapeTimeout .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.monitor.metrics.scrapeTimeout | default .Values.prometheus.monitor.scrapeTimeout }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.proxyUrl .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ .Values.prometheus.monitor.metrics.proxyUrl | default .Values.prometheus.monitor.proxyUrl }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.enableHttp2 .Values.prometheus.monitor.enableHttp2 }} + enableHttp2: {{ .Values.prometheus.monitor.metrics.enableHttp2 | default .Values.prometheus.monitor.enableHttp2 }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.honorLabels .Values.prometheus.monitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.metricRelabelings .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml (.Values.prometheus.monitor.metrics.metricRelabelings | default .Values.prometheus.monitor.metricRelabelings) | nindent 8 }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.relabelings .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml (.Values.prometheus.monitor.metrics.relabelings | default .Values.prometheus.monitor.relabelings) | nindent 8 }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.scheme .Values.prometheus.monitor.scheme }} + scheme: {{ .Values.prometheus.monitor.metrics.scheme | default .Values.prometheus.monitor.scheme }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.tlsConfig .Values.prometheus.monitor.tlsConfig }} + tlsConfig: + {{- toYaml (.Values.prometheus.monitor.metrics.tlsConfig | default .Values.prometheus.monitor.tlsConfig) | nindent 8 }} + {{- end }} + {{- if or .Values.prometheus.monitor.metrics.bearerTokenFile .Values.prometheus.monitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.prometheus.monitor.metrics.bearerTokenFile | default .Values.prometheus.monitor.bearerTokenFile }} + {{- end }} + {{- with (.Values.prometheus.monitor.metrics.bearerTokenSecret | default .Values.prometheus.monitor.bearerTokenSecret) }} + bearerTokenSecret: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml new file mode 100644 index 0000000..489de14 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - apps + resourceNames: + - {{ template "kube-state-metrics.fullname" . }} + resources: + - statefulsets + verbs: + - get + - list + - watch +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml new file mode 100644 index 0000000..73b37a4 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/verticalpodautoscaler.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/verticalpodautoscaler.yaml new file mode 100644 index 0000000..f46305b --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/templates/verticalpodautoscaler.yaml @@ -0,0 +1,44 @@ +{{- if and (.Capabilities.APIVersions.Has "autoscaling.k8s.io/v1") (.Values.verticalPodAutoscaler.enabled) }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +spec: + {{- with .Values.verticalPodAutoscaler.recommenders }} + recommenders: + {{- toYaml . | nindent 4 }} + {{- end }} + resourcePolicy: + containerPolicies: + - containerName: {{ template "kube-state-metrics.name" . }} + {{- with .Values.verticalPodAutoscaler.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.verticalPodAutoscaler.controlledValues }} + controlledValues: {{ .Values.verticalPodAutoscaler.controlledValues }} + {{- end }} + {{- if .Values.verticalPodAutoscaler.maxAllowed }} + maxAllowed: + {{ toYaml .Values.verticalPodAutoscaler.maxAllowed | nindent 8 }} + {{- end }} + {{- if .Values.verticalPodAutoscaler.minAllowed }} + minAllowed: + {{ toYaml .Values.verticalPodAutoscaler.minAllowed | nindent 8 }} + {{- end }} + targetRef: + apiVersion: apps/v1 + {{- if .Values.autosharding.enabled }} + kind: StatefulSet + {{- else }} + kind: Deployment + {{- end }} + name: {{ template "kube-state-metrics.fullname" . }} + {{- with .Values.verticalPodAutoscaler.updatePolicy }} + updatePolicy: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/kube-state-metrics/values.yaml b/utils/assets/charts/prometheus/charts/kube-state-metrics/values.yaml new file mode 100644 index 0000000..188d206 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/kube-state-metrics/values.yaml @@ -0,0 +1,611 @@ +# Default values for kube-state-metrics. +prometheusScrape: true +image: + registry: registry.k8s.io + repository: kube-state-metrics/kube-state-metrics + # If unset use v + .Charts.appVersion + tag: "" + sha: "" + pullPolicy: IfNotPresent + +imagePullSecrets: [] +# - name: "image-pull-secret" + +global: + # To help compatibility with other charts which use global.imagePullSecrets. + # Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). + # global: + # imagePullSecrets: + # - name: pullSecret1 + # - name: pullSecret2 + # or + # global: + # imagePullSecrets: + # - pullSecret1 + # - pullSecret2 + imagePullSecrets: [] + # + # Allow parent charts to override registry hostname + imageRegistry: "" + +# If set to true, this will deploy kube-state-metrics as a StatefulSet and the data +# will be automatically sharded across <.Values.replicas> pods using the built-in +# autodiscovery feature: https://github.com/kubernetes/kube-state-metrics#automated-sharding +# This is an experimental feature and there are no stability guarantees. +autosharding: + enabled: false + +replicas: 1 + +# Change the deployment strategy when autosharding is disabled. +# ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +# The default is "RollingUpdate" as per Kubernetes defaults. +# During a release, 'RollingUpdate' can lead to two running instances for a short period of time while 'Recreate' can create a small gap in data. +# updateStrategy: Recreate + +# Number of old history to retain to allow rollback +# Default Kubernetes value is set to 10 +revisionHistoryLimit: 10 + +# List of additional cli arguments to configure kube-state-metrics +# for example: --enable-gzip-encoding, --log-file, etc. +# all the possible args can be found here: https://github.com/kubernetes/kube-state-metrics/blob/main/docs/developer/cli-arguments.md +extraArgs: [] + +# If false then the user will opt out of automounting API credentials. +automountServiceAccountToken: true + +service: + port: 8080 + # Default to clusterIP for backward compatibility + type: ClusterIP + ipDualStack: + enabled: false + ipFamilies: ["IPv6", "IPv4"] + ipFamilyPolicy: "PreferDualStack" + nodePort: 0 + loadBalancerIP: "" + # Only allow access to the loadBalancerIP from these IPs + loadBalancerSourceRanges: [] + clusterIP: "" + annotations: {} + +## Additional labels to add to all resources +customLabels: {} + # app: kube-state-metrics + +## Override selector labels +selectorOverride: {} + +## set to true to add the release label so scraping of the servicemonitor with kube-prometheus-stack works out of the box +releaseLabel: false + +hostNetwork: false + +rbac: + # If true, create & use RBAC resources + create: true + + # Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to it, rolename set here. + # useExistingRole: your-existing-role + + # If set to false - Run without Cluteradmin privs needed - ONLY works if namespace is also set (if useExistingRole is set this name is used as ClusterRole or Role to bind to) + useClusterRole: true + + # Add permissions for CustomResources' apiGroups in Role/ClusterRole. Should be used in conjunction with Custom Resource State Metrics configuration + # Example: + # - apiGroups: ["monitoring.coreos.com"] + # resources: ["prometheuses"] + # verbs: ["list", "watch"] + extraRules: [] + +# Configure kube-rbac-proxy. When enabled, creates one kube-rbac-proxy container per exposed HTTP endpoint (metrics and telemetry if enabled). +# The requests are served through the same service but requests are then HTTPS. +kubeRBACProxy: + enabled: false + image: + registry: quay.io + repository: brancz/kube-rbac-proxy + tag: v0.20.0 + sha: "" + pullPolicy: IfNotPresent + + # This set --ignore-paths=/livez,/readyz to kubeRBACProxy container args + # to allow the pod probes working properly with kubeRBACProxy enabled. + ignoreProbePaths: true + + # List of additional cli arguments to configure kube-rbac-prxy + # for example: --tls-cipher-suites, --log-file, etc. + # all the possible args can be found here: https://github.com/brancz/kube-rbac-proxy#usage + extraArgs: [] + + ## Specify security settings for a Container + ## Allows overrides and additional options compared to (Pod) securityContext + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + containerSecurityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + + # Configure specific upstream port for kube-state-metrics container + port: 9090 + # Configure specific proxy endpoints port + # This port is for healthz on readinessProbe kube-rbac-proxy-http container + proxyEndpointsPort: 8888 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 64Mi + # requests: + # cpu: 10m + # memory: 32Mi + + ## volumeMounts enables mounting custom volumes in rbac-proxy containers + ## Useful for TLS certificates and keys + volumeMounts: [] + # - mountPath: /etc/tls + # name: kube-rbac-proxy-tls + # readOnly: true + +serviceAccount: + # Specifies whether a ServiceAccount should be created, require rbac true + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + # Reference to one or more secrets to be used when pulling images + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + imagePullSecrets: [] + # ServiceAccount annotations. + # Use case: AWS EKS IAM roles for service accounts + # ref: https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html + annotations: {} + # If false then the user will opt out of automounting API credentials. + automountServiceAccountToken: true + +# Additional Environment variables +env: [] + # - name: GOMAXPROCS + # valueFrom: + # resourceFieldRef: + # resource: limits.cpu + +prometheus: + monitor: + enabled: false + annotations: {} + additionalLabels: {} + namespace: "" + namespaceSelector: [] + jobLabel: "" + targetLabels: [] + podTargetLabels: [] + ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. + ## + sampleLimit: 0 + + ## TargetLimit defines a limit on the number of scraped targets that will be accepted. + ## + targetLimit: 0 + + ## Per-scrape limit on number of labels that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelLimit: 0 + + ## Per-scrape limit on length of labels name that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelNameLengthLimit: 0 + + ## Per-scrape limit on length of labels value that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelValueLengthLimit: 0 + selectorOverride: {} + + ## kube-state-metrics endpoint + http: + interval: "" + scrapeTimeout: "" + proxyUrl: "" + ## Whether to enable HTTP2 for servicemonitor + enableHttp2: false + honorLabels: false + metricRelabelings: [] + relabelings: [] + scheme: "" + ## File to read bearer token for scraping targets + bearerTokenFile: "" + ## Secret to mount to read bearer token for scraping targets. The secret needs + ## to be in the same namespace as the service monitor and accessible by the + ## Prometheus Operator + bearerTokenSecret: {} + # name: secret-name + # key: key-name + tlsConfig: {} + + ## selfMonitor endpoint + metrics: + interval: "" + scrapeTimeout: "" + proxyUrl: "" + ## Whether to enable HTTP2 for servicemonitor + enableHttp2: false + honorLabels: false + metricRelabelings: [] + relabelings: [] + scheme: "" + ## File to read bearer token for scraping targets + bearerTokenFile: "" + ## Secret to mount to read bearer token for scraping targets. The secret needs + ## to be in the same namespace as the service monitor and accessible by the + ## Prometheus Operator + bearerTokenSecret: {} + # name: secret-name + # key: key-name + tlsConfig: {} + ## Create a scrapeConfig resource for scraping the kube-state-metrics service. Use this instead of serviceMonitor + ## to have more instances of kube-state-metrics safety. + scrapeconfig: + ## To avoid duplicate metrics, first disable the serviceMonitor creation via prometheus.monitor.enabled=false + enabled: false + annotations: {} + additionalLabels: {} + jobName: kube-state-metrics + ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. + ## + sampleLimit: 0 + + ## TargetLimit defines a limit on the number of scraped targets that will be accepted. + ## + targetLimit: 0 + + ## Per-scrape limit on number of labels that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelLimit: 0 + + ## Per-scrape limit on length of labels name that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelNameLengthLimit: 0 + + ## Per-scrape limit on length of labels value that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelValueLengthLimit: 0 + + ## StaticConfigLabels defines the labels to be used in the Prometheus static configuration for scraping. + staticConfigLabels: {} + scrapeInterval: "" + scrapeTimeout: "" + proxyUrl: "" + ## Whether to enable HTTP2 for scrapeconfig + enableHttp2: false + honorLabels: true + metricRelabelings: [] + relabelings: [] + scheme: "" + tlsConfig: {} + +## Configure network policy for kube-state-metrics +networkPolicy: + enabled: false + # networkPolicy.flavor -- Flavor of the network policy to use. + # Can be: + # * kubernetes for networking.k8s.io/v1/NetworkPolicy + # * cilium for cilium.io/v2/CiliumNetworkPolicy + flavor: kubernetes + + ## Configure the cilium network policy kube-apiserver selector + # cilium: + # kubeApiServerSelector: + # - toEntities: + # - kube-apiserver + + # egress: + # - {} + # ingress: + # - {} + # podSelector: + # matchLabels: + # app.kubernetes.io/name: kube-state-metrics + +securityContext: + enabled: true + runAsGroup: 65534 + runAsUser: 65534 + fsGroup: 65534 + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + +## Specify security settings for a Container +## Allows overrides and additional options compared to (Pod) securityContext +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +containerSecurityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + +## Node labels for pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +## Affinity settings for pod assignment +## Can be defined as either a dict or string. String is useful for `tpl` templating. +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ +affinity: {} +# affinity: | +# podAntiAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# - labelSelector: +# matchLabels: +# {{- include "kube-state-metrics.selectorLabels" . | indent 10 }} +# topologyKey: kubernetes.io/hostname + +## Tolerations for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +## Topology spread constraints for pod assignment +## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +topologySpreadConstraints: [] + +# Annotations to be added to the deployment/statefulset +annotations: {} + +# Labels to be added to the deployment/statefulset +labels: {} + +# Annotations to be added to the pod +podAnnotations: {} + +# Labels to be added to the pod +podLabels: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: "" + +# Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} + +# Comma-separated list of metrics to be exposed. +# This list comprises of exact metric names and/or regex patterns. +# The allowlist and denylist are mutually exclusive. +metricAllowlist: [] + +# Comma-separated list of metrics not to be enabled. +# This list comprises of exact metric names and/or regex patterns. +# The allowlist and denylist are mutually exclusive. +metricDenylist: [] + +# Comma-separated list of additional Kubernetes label keys that will be used in the resource's +# labels metric. By default the metric contains only name and namespace labels. +# To include additional labels, provide a list of resource names in their plural form and Kubernetes +# label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. +# A single '*' can be provided per resource instead to allow any labels, but that has +# severe performance implications (Example: '=pods=[*]'). +metricLabelsAllowlist: [] + # - namespaces=[k8s-label-1,k8s-label-n] + +# Comma-separated list of Kubernetes annotations keys that will be used in the resource' +# labels metric. By default the metric contains only name and namespace labels. +# To include additional annotations provide a list of resource names in their plural form and Kubernetes +# annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. +# A single '*' can be provided per resource instead to allow any annotations, but that has +# severe performance implications (Example: '=pods=[*]'). +metricAnnotationsAllowList: [] + # - pods=[k8s-annotation-1,k8s-annotation-n] + +# Available collectors for kube-state-metrics. +# By default, all available resources are enabled, comment out to disable. +collectors: + - certificatesigningrequests + - configmaps + - cronjobs + - daemonsets + - deployments + - endpoints + - horizontalpodautoscalers + - ingresses + - jobs + - leases + - limitranges + - mutatingwebhookconfigurations + - namespaces + - networkpolicies + - nodes + - persistentvolumeclaims + - persistentvolumes + - poddisruptionbudgets + - pods + - replicasets + - replicationcontrollers + - resourcequotas + - secrets + - services + - statefulsets + - storageclasses + - validatingwebhookconfigurations + - volumeattachments + # - ingressclasses + # - clusterrolebindings + # - clusterroles + # - roles + +# Enabling kubeconfig will pass the --kubeconfig argument to the container +kubeconfig: + enabled: false + # base64 encoded kube-config file + secret: + +# Enabling support for customResourceState, will create a configMap including your config that will be read from kube-state-metrics +customResourceState: + # Whether to enable support for CustomResourceStateMetrics. + enabled: false + + # Whether to create the ConfigMap that holds the config. + create: true + + # Name of the ConfigMap that holds the config. If empty, name will be generated based on the release name. + name: "" + + # ConfigMap key that holds the config. + key: config.yaml + + # Definition of the CustomResourceStateMetrics. Add (Cluster)Role permissions to list/watch the resources defined in the config to rbac.extraRules. + config: {} + +# Enable only the release namespace for collecting resources. By default all namespaces are collected. +# If releaseNamespace and namespaces are both set a merged list will be collected. +releaseNamespace: false + +# Comma-separated list(string) or yaml list of namespaces to be enabled for collecting resources. By default all namespaces are collected. +namespaces: "" + +# Comma-separated list of namespaces not to be enabled. If namespaces and namespaces-denylist are both set, +# only namespaces that are excluded in namespaces-denylist will be used. +namespacesDenylist: "" + +## Override the deployment namespace +## +namespaceOverride: "" + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 64Mi + # requests: + # cpu: 10m + # memory: 32Mi + +# Enable self metrics configuration for service and Service Monitor +# Default values for telemetry configuration can be overridden +# If you set telemetryNodePort, you must also set service.type to NodePort +selfMonitor: + enabled: false + # telemetryHost: 0.0.0.0 + # telemetryPort: 8081 + # telemetryNodePort: 0 + +# Enable vertical pod autoscaler support for kube-state-metrics +verticalPodAutoscaler: + enabled: false + + # Recommender responsible for generating recommendation for the object. + # List should be empty (then the default recommender will generate the recommendation) + # or contain exactly one recommender. + # recommenders: [] + # - name: custom-recommender-performance + + # List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + controlledResources: [] + # Specifies which resource values should be controlled: RequestsOnly or RequestsAndLimits. + # controlledValues: RequestsAndLimits + + # Define the max allowed resources for the pod + maxAllowed: {} + # cpu: 200m + # memory: 100Mi + # Define the min allowed resources for the pod + minAllowed: {} + # cpu: 200m + # memory: 100Mi + + # updatePolicy: + # Specifies minimal number of replicas which need to be alive for VPA Updater to attempt pod eviction + # minReplicas: 1 + # Specifies whether recommended updates are applied when a Pod is started and whether recommended updates + # are applied during the life of a Pod. Possible values are "Off", "Initial", "Recreate", and "Auto". + # updateMode: Auto + +# volumeMounts are used to add custom volume mounts to deployment. +# See example below +volumeMounts: [] +# - mountPath: /etc/config +# name: config-volume + +# volumes are used to add custom volumes to deployment +# See example below +volumes: [] +# - configMap: +# name: cm-for-volume +# name: config-volume + +# Extra manifests to deploy as an array +extraManifests: [] + # - apiVersion: v1 + # kind: ConfigMap + # metadata: + # labels: + # name: prometheus-extra + # data: + # extra-data: "value" + +## Containers allows injecting additional containers. +containers: [] + # - name: crd-init + # image: kiwigrid/k8s-sidecar:latest + +## InitContainers allows injecting additional initContainers. +initContainers: [] + # - name: crd-sidecar + # image: kiwigrid/k8s-sidecar:latest + +## dnsPolicy allows to change the default DNS configuration for the pod +## Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy +dnsPolicy: ClusterFirst + +## dnsConfig allows setting up specific DNS configuration for the pod +## Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config +dnsConfig: {} + +## Settings for startup, liveness and readiness probes +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +## + +## Startup probe can optionally be enabled. +## +startupProbe: + enabled: false + failureThreshold: 3 + httpGet: + httpHeaders: [] + scheme: http + initialDelaySeconds: 0 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + +## Liveness probe +## +livenessProbe: + failureThreshold: 3 + httpGet: + httpHeaders: [] + scheme: http + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + +## Readiness probe +## +readinessProbe: + failureThreshold: 3 + httpGet: + httpHeaders: [] + scheme: http + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/.helmignore b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/.helmignore new file mode 100644 index 0000000..2846d36 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj + +ci/ diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/Chart.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/Chart.yaml new file mode 100644 index 0000000..cf54941 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/Chart.yaml @@ -0,0 +1,28 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts +apiVersion: v2 +appVersion: 1.10.2 +description: A Helm chart for prometheus node-exporter +home: https://github.com/prometheus/node_exporter/ +keywords: +- node-exporter +- prometheus +- exporter +maintainers: +- email: gianrubio@gmail.com + name: gianrubio + url: https://github.com/gianrubio +- email: zanhsieh@gmail.com + name: zanhsieh + url: https://github.com/zanhsieh +- email: rootsandtrees@posteo.de + name: zeritti + url: https://github.com/zeritti +name: prometheus-node-exporter +sources: +- https://github.com/prometheus/node_exporter/ +type: application +version: 4.49.1 diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/README.md b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/README.md new file mode 100644 index 0000000..a540467 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/README.md @@ -0,0 +1,96 @@ +# Prometheus Node Exporter + +Prometheus exporter for hardware and OS metrics exposed by *NIX kernels, written in Go with pluggable metric collectors. + +This chart bootstraps a Prometheus [Node Exporter](http://github.com/prometheus/node_exporter) daemonset on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Usage + +The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/). + +- OCI Artifact: `oci://ghcr.io/prometheus-community/charts/prometheus-node-exporter` +- Helm Repository: `https://prometheus-community.github.io/helm-charts` with chart `prometheus-node-exporter` + +The installation instructions use the OCI registry. Refer to the [`helm repo`]([`helm repo`](https://helm.sh/docs/helm/helm_repo/)) command documentation for information on installing charts via the traditional repository. + +### Install Chart + +```console +helm install [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/prometheus-node-exporter +``` + +_See [configuration](#configuring) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +### Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +### Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/prometheus-node-exporter --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +#### 3.x to 4.x + +Starting from version 4.0.0, the `node exporter` chart is using the [Kubernetes recommended labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/). Therefore you have to delete the daemonset before you upgrade. + +```console +kubectl delete daemonset -l app=prometheus-node-exporter +helm upgrade -i prometheus-node-exporter prometheus-community/prometheus-node-exporter +``` + +If you use your own custom [ServiceMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md#servicemonitor) or [PodMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md#podmonitor), please ensure to upgrade their `selector` fields accordingly to the new labels. + +#### From 2.x to 3.x + +Change the following: + +```yaml +hostRootFsMount: true +``` + +to: + +```yaml +hostRootFsMount: + enabled: true + mountPropagation: HostToContainer +``` + +## Configuring + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values oci://ghcr.io/prometheus-community/charts/prometheus-node-exporter +``` + +### kube-rbac-proxy + +You can enable `prometheus-node-exporter` endpoint protection using `kube-rbac-proxy`. By setting `kubeRBACProxy.enabled: true`, this chart will deploy a RBAC proxy container protecting the node-exporter endpoint. +To authorize access, authenticate your requests (via a `ServiceAccount` for example) with a `ClusterRole` attached such as: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: prometheus-node-exporter-read +rules: + - apiGroups: [ "" ] + resources: ["services/node-exporter-prometheus-node-exporter"] + verbs: + - get +``` + +See [kube-rbac-proxy examples](https://github.com/brancz/kube-rbac-proxy/tree/master/examples/resource-attributes) for more details. diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/NOTES.txt b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/NOTES.txt new file mode 100644 index 0000000..db8584d --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/NOTES.txt @@ -0,0 +1,29 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ template "prometheus-node-exporter.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus-node-exporter.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ template "prometheus-node-exporter.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "prometheus-node-exporter.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ template "prometheus-node-exporter.namespace" . }} {{ template "prometheus-node-exporter.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ template "prometheus-node-exporter.namespace" . }} -l "app.kubernetes.io/name={{ template "prometheus-node-exporter.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:9100 to use your application" + kubectl port-forward --namespace {{ template "prometheus-node-exporter.namespace" . }} $POD_NAME 9100 +{{- end }} + +{{- if .Values.kubeRBACProxy.enabled}} + +kube-rbac-proxy endpoint protections is enabled: +- Metrics endpoints is now HTTPS +- Ensure that the client authenticates the requests (e.g. via service account) with the following role permissions: +``` +rules: + - apiGroups: [ "" ] + resources: ["services/{{ template "prometheus-node-exporter.fullname" . }}"] + verbs: + - get +``` +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/_helpers.tpl b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/_helpers.tpl new file mode 100644 index 0000000..890c487 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/_helpers.tpl @@ -0,0 +1,237 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus-node-exporter.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "prometheus-node-exporter.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus-node-exporter.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "prometheus-node-exporter.labels" -}} +helm.sh/chart: {{ include "prometheus-node-exporter.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: metrics +app.kubernetes.io/part-of: {{ include "prometheus-node-exporter.name" . }} +{{ include "prometheus-node-exporter.selectorLabels" . }} +{{- with .Chart.AppVersion }} +app.kubernetes.io/version: {{ . | quote }} +{{- end }} +{{- with .Values.commonLabels }} +{{ tpl (toYaml .) $ }} +{{- end }} +{{- if .Values.releaseLabel }} +release: {{ .Release.Name }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "prometheus-node-exporter.selectorLabels" -}} +app.kubernetes.io/name: {{ include "prometheus-node-exporter.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + + +{{/* +Create the name of the service account to use +*/}} +{{- define "prometheus-node-exporter.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "prometheus-node-exporter.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +The image to use +*/}} +{{- define "prometheus-node-exporter.image" -}} +{{- if .Values.image.sha }} +{{- fail "image.sha forbidden. Use image.digest instead" }} +{{- else if .Values.image.digest }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s@%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.digest }} +{{- else }} +{{- printf "%s/%s:%s@%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) .Values.image.digest }} +{{- end }} +{{- else }} +{{- if .Values.global.imageRegistry }} +{{- printf "%s/%s:%s" .Values.global.imageRegistry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- else }} +{{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "prometheus-node-exporter.namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{/* +Create the namespace name of the service monitor +*/}} +{{- define "prometheus-node-exporter.monitor-namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- if .Values.prometheus.monitor.namespace }} +{{- .Values.prometheus.monitor.namespace }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Sets default scrape limits for servicemonitor */}} +{{- define "servicemonitor.scrapeLimits" -}} +{{- with .sampleLimit }} +sampleLimit: {{ . }} +{{- end }} +{{- with .targetLimit }} +targetLimit: {{ . }} +{{- end }} +{{- with .labelLimit }} +labelLimit: {{ . }} +{{- end }} +{{- with .labelNameLengthLimit }} +labelNameLengthLimit: {{ . }} +{{- end }} +{{- with .labelValueLengthLimit }} +labelValueLengthLimit: {{ . }} +{{- end }} +{{- end }} + +{{/* +Formats imagePullSecrets. Input is (dict "Values" .Values "imagePullSecrets" .{specific imagePullSecrets}) +*/}} +{{- define "prometheus-node-exporter.imagePullSecrets" -}} +{{- range (concat .Values.global.imagePullSecrets .imagePullSecrets) }} + {{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml . | trim }} + {{- else }} +- name: {{ . }} + {{- end }} +{{- end }} +{{- end -}} + +{{/* +Create the namespace name of the pod monitor +*/}} +{{- define "prometheus-node-exporter.podmonitor-namespace" -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- if .Values.prometheus.podMonitor.namespace }} +{{- .Values.prometheus.podMonitor.namespace }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Sets default scrape limits for podmonitor */}} +{{- define "podmonitor.scrapeLimits" -}} +{{- with .sampleLimit }} +sampleLimit: {{ . }} +{{- end }} +{{- with .targetLimit }} +targetLimit: {{ . }} +{{- end }} +{{- with .labelLimit }} +labelLimit: {{ . }} +{{- end }} +{{- with .labelNameLengthLimit }} +labelNameLengthLimit: {{ . }} +{{- end }} +{{- with .labelValueLengthLimit }} +labelValueLengthLimit: {{ . }} +{{- end }} +{{- end }} + +{{/* Sets sidecar volumeMounts */}} +{{- define "prometheus-node-exporter.sidecarVolumeMounts" -}} +{{- range $_, $mount := $.Values.sidecarVolumeMount }} +- name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: {{ $mount.readOnly }} +{{- end }} +{{- range $_, $mount := $.Values.sidecarHostVolumeMounts }} +- name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: {{ $mount.readOnly }} +{{- if $mount.mountPropagation }} + mountPropagation: {{ $mount.mountPropagation }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +The default node affinity to exclude +- AWS Fargate +- Azure virtual nodes +*/}} +{{- define "prometheus-node-exporter.defaultAffinity" -}} +nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: eks.amazonaws.com/compute-type + operator: NotIn + values: + - fargate + - key: type + operator: NotIn + values: + - virtual-kubelet +{{- end -}} +{{- define "prometheus-node-exporter.mergedAffinities" -}} +{{- $defaultAffinity := include "prometheus-node-exporter.defaultAffinity" . | fromYaml -}} +{{- with .Values.affinity -}} + {{- if .nodeAffinity -}} + {{- $_ := set $defaultAffinity "nodeAffinity" (mergeOverwrite $defaultAffinity.nodeAffinity .nodeAffinity) -}} + {{- end -}} + {{- if .podAffinity -}} + {{- $_ := set $defaultAffinity "podAffinity" .podAffinity -}} + {{- end -}} + {{- if .podAntiAffinity -}} + {{- $_ := set $defaultAffinity "podAntiAffinity" .podAntiAffinity -}} + {{- end -}} +{{- end -}} +{{- toYaml $defaultAffinity -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/clusterrole.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/clusterrole.yaml new file mode 100644 index 0000000..c256dba --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if and (eq .Values.rbac.create true) (eq .Values.kubeRBACProxy.enabled true) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +rules: + {{- if $.Values.kubeRBACProxy.enabled }} + - apiGroups: [ "authentication.k8s.io" ] + resources: + - tokenreviews + verbs: [ "create" ] + - apiGroups: [ "authorization.k8s.io" ] + resources: + - subjectaccessreviews + verbs: [ "create" ] + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/clusterrolebinding.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..653305a --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and (eq .Values.rbac.create true) (eq .Values.kubeRBACProxy.enabled true) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + name: {{ template "prometheus-node-exporter.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole +{{- if .Values.rbac.useExistingRole }} + name: {{ .Values.rbac.useExistingRole }} +{{- else }} + name: {{ template "prometheus-node-exporter.fullname" . }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "prometheus-node-exporter.serviceAccountName" . }} + namespace: {{ template "prometheus-node-exporter.namespace" . }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/daemonset.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/daemonset.yaml new file mode 100644 index 0000000..3d8293d --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/daemonset.yaml @@ -0,0 +1,349 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- with .Values.updateStrategy }} + updateStrategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + spec: + automountServiceAccountToken: {{ ternary true false (or .Values.serviceAccount.automountServiceAccountToken .Values.kubeRBACProxy.enabled) }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.extraInitContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "prometheus-node-exporter.serviceAccountName" . }} + {{- with .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ . }} + {{- end }} + containers: + {{- $servicePort := ternary .Values.kubeRBACProxy.port .Values.service.port .Values.kubeRBACProxy.enabled }} + {{- $servicePortReference := ternary .Values.kubeRBACProxy.port .Values.service.portName .Values.kubeRBACProxy.enabled }} + - name: node-exporter + image: {{ include "prometheus-node-exporter.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --path.procfs=/host/proc + - --path.sysfs=/host/sys + {{- if .Values.hostRootFsMount.enabled }} + - --path.rootfs=/host/root + {{- if semverCompare ">=1.4.0-0" (coalesce .Values.version .Values.image.tag .Chart.AppVersion) }} + - --path.udev.data=/host/root/run/udev/data + {{- end }} + {{- end }} + - --web.listen-address=[$(HOST_IP)]:{{ $servicePort }} + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: HOST_IP + {{- if .Values.kubeRBACProxy.enabled }} + value: 127.0.0.1 + {{- else if .Values.service.listenOnAllInterfaces }} + value: 0.0.0.0 + {{- else }} + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + {{- end }} + {{- range $key, $value := .Values.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- if eq .Values.kubeRBACProxy.enabled false }} + ports: + - name: {{ .Values.service.portName }} + containerPort: {{ .Values.service.port }} + protocol: TCP + {{- end }} + livenessProbe: + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + httpGet: + {{- if .Values.kubeRBACProxy.enabled }} + host: 127.0.0.1 + {{- end }} + httpHeaders: + {{- range $_, $header := .Values.livenessProbe.httpGet.httpHeaders }} + - name: {{ $header.name }} + value: {{ $header.value }} + {{- end }} + path: / + port: {{ $servicePortReference }} + scheme: {{ upper .Values.livenessProbe.httpGet.scheme }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + readinessProbe: + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + httpGet: + {{- if .Values.kubeRBACProxy.enabled }} + host: 127.0.0.1 + {{- end }} + httpHeaders: + {{- range $_, $header := .Values.readinessProbe.httpGet.httpHeaders }} + - name: {{ $header.name }} + value: {{ $header.value }} + {{- end }} + path: / + port: {{ $servicePortReference }} + scheme: {{ upper .Values.readinessProbe.httpGet.scheme }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.terminationMessageParams.enabled }} + {{- with .Values.terminationMessageParams }} + terminationMessagePath: {{ .terminationMessagePath }} + terminationMessagePolicy: {{ .terminationMessagePolicy }} + {{- end }} + {{- end }} + volumeMounts: + - name: proc + mountPath: /host/proc + {{- with .Values.hostProcFsMount.mountPropagation }} + mountPropagation: {{ . }} + {{- end }} + readOnly: true + - name: sys + mountPath: /host/sys + {{- with .Values.hostSysFsMount.mountPropagation }} + mountPropagation: {{ . }} + {{- end }} + readOnly: true + {{- if .Values.hostRootFsMount.enabled }} + - name: root + mountPath: /host/root + {{- with .Values.hostRootFsMount.mountPropagation }} + mountPropagation: {{ . }} + {{- end }} + readOnly: true + {{- end }} + {{- range $_, $mount := .Values.extraHostVolumeMounts }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: {{ $mount.readOnly }} + {{- with $mount.mountPropagation }} + mountPropagation: {{ . }} + {{- end }} + {{- end }} + {{- range $_, $mount := .Values.sidecarVolumeMount }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + readOnly: true + {{- end }} + {{- range $_, $mount := .Values.configmaps }} + - name: {{ $mount.name }} + mountPath: {{ $mount.mountPath }} + {{- end }} + {{- range $_, $mount := .Values.secrets }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- range .Values.sidecars }} + {{- $overwrites := dict "volumeMounts" (concat (include "prometheus-node-exporter.sidecarVolumeMounts" $ | fromYamlArray) (.volumeMounts | default list) | default list) }} + {{- $defaults := dict "image" (include "prometheus-node-exporter.image" $) "securityContext" $.Values.containerSecurityContext "imagePullPolicy" $.Values.image.pullPolicy }} + - {{- toYaml (merge $overwrites . $defaults) | nindent 10 }} + {{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - name: kube-rbac-proxy + args: + {{- if .Values.kubeRBACProxy.extraArgs }} + {{- .Values.kubeRBACProxy.extraArgs | toYaml | nindent 12 }} + {{- end }} + - --secure-listen-address=:{{ .Values.service.port}} + - --upstream=http://127.0.0.1:{{ $servicePort }}/ + - --proxy-endpoints-port={{ .Values.kubeRBACProxy.proxyEndpointsPort }} + - --config-file=/etc/kube-rbac-proxy-config/config-file.yaml + {{- if and .Values.kubeRBACProxy.tls.enabled .Values.tlsSecret.enabled }} + - --tls-cert-file=/tls/private/{{ .Values.tlsSecret.certItem }} + - --tls-private-key-file=/tls/private/{{ .Values.tlsSecret.keyItem }} + {{- if and .Values.kubeRBACProxy.tls.tlsClientAuth .Values.tlsSecret.caItem }} + - --client-ca-file=/tls/private/{{ .Values.tlsSecret.caItem }} + {{- end }} + {{- end }} + volumeMounts: + - name: kube-rbac-proxy-config + mountPath: /etc/kube-rbac-proxy-config + {{- if and .Values.kubeRBACProxy.tls.enabled .Values.tlsSecret.enabled }} + - name: {{ tpl .Values.tlsSecret.volumeName . | quote }} + mountPath: /tls/private + readOnly: true + {{- end }} + {{- with .Values.kubeRBACProxy.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + imagePullPolicy: {{ .Values.kubeRBACProxy.image.pullPolicy }} + {{- if .Values.kubeRBACProxy.image.sha }} + image: "{{ .Values.global.imageRegistry | default .Values.kubeRBACProxy.image.registry}}/{{ .Values.kubeRBACProxy.image.repository }}:{{ .Values.kubeRBACProxy.image.tag }}@sha256:{{ .Values.kubeRBACProxy.image.sha }}" + {{- else }} + image: "{{ .Values.global.imageRegistry | default .Values.kubeRBACProxy.image.registry}}/{{ .Values.kubeRBACProxy.image.repository }}:{{ .Values.kubeRBACProxy.image.tag }}" + {{- end }} + ports: + - containerPort: {{ .Values.service.port}} + name: {{ .Values.kubeRBACProxy.portName }} + {{- if .Values.kubeRBACProxy.enableHostPort }} + hostPort: {{ .Values.service.port }} + {{- end }} + - containerPort: {{ .Values.kubeRBACProxy.proxyEndpointsPort }} + {{- if .Values.kubeRBACProxy.enableProxyEndpointsHostPort }} + hostPort: {{ .Values.kubeRBACProxy.proxyEndpointsPort }} + {{- end }} + name: "http-healthz" + readinessProbe: + httpGet: + scheme: HTTPS + port: {{ .Values.kubeRBACProxy.proxyEndpointsPort }} + path: healthz + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.kubeRBACProxy.resources }} + resources: + {{- toYaml .Values.kubeRBACProxy.resources | nindent 12 }} + {{- end }} + {{- if .Values.terminationMessageParams.enabled }} + {{- with .Values.terminationMessageParams }} + terminationMessagePath: {{ .terminationMessagePath }} + terminationMessagePolicy: {{ .terminationMessagePolicy }} + {{- end }} + {{- end }} + {{- with .Values.kubeRBACProxy.env }} + env: + {{- range $key, $value := $.Values.kubeRBACProxy.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + {{- if .Values.kubeRBACProxy.containerSecurityContext }} + securityContext: + {{ toYaml .Values.kubeRBACProxy.containerSecurityContext | nindent 12 }} + {{- end }} + {{- end }} + {{- if or .Values.imagePullSecrets .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- include "prometheus-node-exporter.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.imagePullSecrets) | indent 8 }} + {{- end }} + hostNetwork: {{ .Values.hostNetwork }} + hostPID: {{ .Values.hostPID }} + hostIPC: {{ .Values.hostIPC }} + affinity: + {{- include "prometheus-node-exporter.mergedAffinities" . | nindent 8 }} + {{- with .Values.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.restartPolicy }} + restartPolicy: {{ . }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: proc + hostPath: + path: /proc + - name: sys + hostPath: + path: /sys + {{- if .Values.hostRootFsMount.enabled }} + - name: root + hostPath: + path: / + {{- end }} + {{- range $_, $mount := .Values.extraHostVolumeMounts }} + - name: {{ $mount.name }} + hostPath: + path: {{ $mount.hostPath }} + {{- with $mount.type }} + type: {{ . }} + {{- end }} + {{- end }} + {{- range $_, $mount := .Values.sidecarVolumeMount }} + - name: {{ $mount.name }} + emptyDir: + medium: Memory + {{- end }} + {{- range $_, $mount := .Values.sidecarHostVolumeMounts }} + - name: {{ $mount.name }} + hostPath: + path: {{ $mount.hostPath }} + {{- end }} + {{- range $_, $mount := .Values.configmaps }} + - name: {{ $mount.name }} + configMap: + name: {{ $mount.name }} + {{- end }} + {{- range $_, $mount := .Values.secrets }} + - name: {{ $mount.name }} + secret: + secretName: {{ $mount.name }} + {{- end }} + {{- if .Values.kubeRBACProxy.enabled }} + - name: kube-rbac-proxy-config + configMap: + name: {{ template "prometheus-node-exporter.fullname" . }}-rbac-config + {{- end }} + {{- if .Values.tlsSecret.enabled }} + - name: {{ tpl .Values.tlsSecret.volumeName . | quote }} + secret: + secretName: {{ tpl .Values.tlsSecret.secretName . | quote }} + items: + - key: {{ required "Value tlsSecret.certItem must be set." .Values.tlsSecret.certItem | quote }} + path: {{ .Values.tlsSecret.certItem | quote }} + - key: {{ required "Value tlsSecret.keyItem must be set." .Values.tlsSecret.keyItem | quote }} + path: {{ .Values.tlsSecret.keyItem | quote }} + {{- if .Values.tlsSecret.caItem }} + - key: {{ .Values.tlsSecret.caItem | quote }} + path: {{ .Values.tlsSecret.caItem | quote }} + {{- end }} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/endpoints.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/endpoints.yaml new file mode 100644 index 0000000..45eeb8d --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/endpoints.yaml @@ -0,0 +1,18 @@ +{{- if .Values.endpoints }} +apiVersion: v1 +kind: Endpoints +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +subsets: + - addresses: + {{- range .Values.endpoints }} + - ip: {{ . }} + {{- end }} + ports: + - name: {{ .Values.service.portName }} + port: 9100 + protocol: TCP +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/extra-manifests.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/extra-manifests.yaml new file mode 100644 index 0000000..2b21b71 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraManifests }} +--- +{{ tpl . $ }} +{{ end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/networkpolicy.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/networkpolicy.yaml new file mode 100644 index 0000000..ee40902 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/networkpolicy.yaml @@ -0,0 +1,27 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" $ | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingress: + {{- if .Values.networkPolicy.ingress }} + {{- toYaml .Values.networkPolicy.ingress | nindent 4 }} + {{- else }} + - ports: + - port: {{ .Values.service.port }} + {{- end }} + policyTypes: + - Egress + - Ingress + podSelector: + matchLabels: + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/podmonitor.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/podmonitor.yaml new file mode 100644 index 0000000..f88da6a --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/podmonitor.yaml @@ -0,0 +1,91 @@ +{{- if .Values.prometheus.podMonitor.enabled }} +apiVersion: {{ .Values.prometheus.podMonitor.apiVersion | default "monitoring.coreos.com/v1" }} +kind: PodMonitor +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.podmonitor-namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.prometheus.podMonitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ default "app.kubernetes.io/name" .Values.prometheus.podMonitor.jobLabel }} + {{- include "podmonitor.scrapeLimits" .Values.prometheus.podMonitor | nindent 2 }} + selector: + matchLabels: + {{- with .Values.prometheus.podMonitor.selectorOverride }} + {{- toYaml . | nindent 6 }} + {{- else }} + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ include "prometheus-node-exporter.namespace" . }} + {{- with .Values.prometheus.podMonitor.attachMetadata }} + attachMetadata: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.podTargetLabels }} + podTargetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} + podMetricsEndpoints: + - port: {{ .Values.service.portName }} + {{- with .Values.prometheus.podMonitor.scheme }} + scheme: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.path }} + path: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.basicAuth }} + basicAuth: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.bearerTokenSecret }} + bearerTokenSecret: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.authorization }} + authorization: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.oauth2 }} + oauth2: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.proxyUrl }} + proxyUrl: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.honorTimestamps }} + honorTimestamps: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.honorLabels }} + honorLabels: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.prometheus.podMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.podMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + enableHttp2: {{ default false .Values.prometheus.podMonitor.enableHttp2 }} + filterRunning: {{ default true .Values.prometheus.podMonitor.filterRunning }} + followRedirects: {{ default false .Values.prometheus.podMonitor.followRedirects }} + {{- with .Values.prometheus.podMonitor.params }} + params: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/rbac-configmap.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/rbac-configmap.yaml new file mode 100644 index 0000000..814e110 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/rbac-configmap.yaml @@ -0,0 +1,16 @@ +{{- if .Values.kubeRBACProxy.enabled}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "prometheus-node-exporter.fullname" . }}-rbac-config + namespace: {{ include "prometheus-node-exporter.namespace" . }} +data: + config-file.yaml: |+ + authorization: + resourceAttributes: + namespace: {{ template "prometheus-node-exporter.namespace" . }} + apiVersion: v1 + resource: services + subresource: {{ template "prometheus-node-exporter.fullname" . }} + name: {{ template "prometheus-node-exporter.fullname" . }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/service.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/service.yaml new file mode 100644 index 0000000..9807c66 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/service.yaml @@ -0,0 +1,41 @@ +{{- if .Values.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" $ | nindent 4 }} + {{- with .Values.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.service.ipDualStack.enabled }} + ipFamilies: {{ toYaml .Values.service.ipDualStack.ipFamilies | nindent 4 }} + ipFamilyPolicy: {{ .Values.service.ipDualStack.ipFamilyPolicy }} +{{- end }} +{{- if .Values.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} +{{- end }} +{{- if .Values.service.internalTrafficPolicy }} + internalTrafficPolicy: {{ .Values.service.internalTrafficPolicy }} +{{- end }} + type: {{ .Values.service.type }} +{{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: "{{ .Values.service.clusterIP }}" +{{- end }} + ports: + - port: {{ .Values.service.servicePort | default .Values.service.port }} + {{- if ( and (eq .Values.service.type "NodePort" ) (not (empty .Values.service.nodePort)) ) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + targetPort: {{ .Values.service.targetPort }} + protocol: TCP + name: {{ .Values.service.portName }} + selector: + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/serviceaccount.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/serviceaccount.yaml new file mode 100644 index 0000000..462b0cd --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/serviceaccount.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.rbac.create .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "prometheus-node-exporter.serviceAccountName" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- if or .Values.serviceAccount.imagePullSecrets .Values.global.imagePullSecrets }} +imagePullSecrets: + {{- include "prometheus-node-exporter.imagePullSecrets" (dict "Values" .Values "imagePullSecrets" .Values.serviceAccount.imagePullSecrets) | indent 2 }} +{{- end }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/servicemonitor.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/servicemonitor.yaml new file mode 100644 index 0000000..96ec1af --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/servicemonitor.yaml @@ -0,0 +1,65 @@ +{{- if .Values.prometheus.monitor.enabled }} +apiVersion: {{ .Values.prometheus.monitor.apiVersion | default "monitoring.coreos.com/v1" }} +kind: ServiceMonitor +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.monitor-namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} + {{- with .Values.prometheus.monitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ default "app.kubernetes.io/name" .Values.prometheus.monitor.jobLabel }} + {{- include "servicemonitor.scrapeLimits" .Values.prometheus.monitor | nindent 2 }} + {{- with .Values.prometheus.monitor.podTargetLabels }} + podTargetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.prometheus.monitor.targetLabels }} + targetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- with .Values.prometheus.monitor.selectorOverride }} + {{- toYaml . | nindent 6 }} + {{- else }} + {{- include "prometheus-node-exporter.selectorLabels" . | nindent 6 }} + {{- end }} + {{- with .Values.prometheus.monitor.attachMetadata }} + attachMetadata: + {{- toYaml . | nindent 4 }} + {{- end }} + endpoints: + - port: {{ .Values.service.portName }} + scheme: {{ .Values.prometheus.monitor.scheme }} + {{- with .Values.prometheus.monitor.basicAuth }} + basicAuth: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.monitor.bearerTokenFile }} + bearerTokenFile: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/verticalpodautoscaler.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/verticalpodautoscaler.yaml new file mode 100644 index 0000000..2c2705f --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/templates/verticalpodautoscaler.yaml @@ -0,0 +1,40 @@ +{{- if and (.Capabilities.APIVersions.Has "autoscaling.k8s.io/v1") (.Values.verticalPodAutoscaler.enabled) }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ include "prometheus-node-exporter.fullname" . }} + namespace: {{ include "prometheus-node-exporter.namespace" . }} + labels: + {{- include "prometheus-node-exporter.labels" . | nindent 4 }} +spec: + {{- with .Values.verticalPodAutoscaler.recommenders }} + recommenders: + {{- toYaml . | nindent 4 }} + {{- end }} + resourcePolicy: + containerPolicies: + - containerName: node-exporter + {{- with .Values.verticalPodAutoscaler.controlledResources }} + controlledResources: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.verticalPodAutoscaler.controlledValues }} + controlledValues: {{ . }} + {{- end }} + {{- with .Values.verticalPodAutoscaler.maxAllowed }} + maxAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.verticalPodAutoscaler.minAllowed }} + minAllowed: + {{- toYaml . | nindent 8 }} + {{- end }} + targetRef: + apiVersion: apps/v1 + kind: DaemonSet + name: {{ include "prometheus-node-exporter.fullname" . }} + {{- with .Values.verticalPodAutoscaler.updatePolicy }} + updatePolicy: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-node-exporter/values.yaml b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/values.yaml new file mode 100644 index 0000000..c056625 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-node-exporter/values.yaml @@ -0,0 +1,616 @@ +# Default values for prometheus-node-exporter. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +image: + registry: quay.io + repository: prometheus/node-exporter + # Overrides the image tag whose default is {{ printf "v%s" .Chart.AppVersion }} + tag: "" + pullPolicy: IfNotPresent + digest: "" + +imagePullSecrets: [] +# - name: "image-pull-secret" +nameOverride: "" +fullnameOverride: "" + +# Number of old history to retain to allow rollback +# Default Kubernetes value is set to 10 +revisionHistoryLimit: 10 + +global: + # To help compatibility with other charts which use global.imagePullSecrets. + # Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). + # global: + # imagePullSecrets: + # - name: pullSecret1 + # - name: pullSecret2 + # or + # global: + # imagePullSecrets: + # - pullSecret1 + # - pullSecret2 + imagePullSecrets: [] + # + # Allow parent charts to override registry hostname + imageRegistry: "" + +# Configure kube-rbac-proxy. When enabled, creates a kube-rbac-proxy to protect the node-exporter http endpoint. +# The requests are served through the same service but requests are HTTPS. +kubeRBACProxy: + enabled: false + ## Set environment variables as name/value pairs + env: {} + # VARIABLE: value + image: + registry: quay.io + repository: brancz/kube-rbac-proxy + tag: v0.20.0 + sha: "" + pullPolicy: IfNotPresent + + # List of additional cli arguments to configure kube-rbac-proxy + # for example: --tls-cipher-suites, --log-file, etc. + # all the possible args can be found here: https://github.com/brancz/kube-rbac-proxy#usage + extraArgs: [] + + ## Specify security settings for a Container + ## Allows overrides and additional options compared to (Pod) securityContext + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + containerSecurityContext: {} + + # Specify the port used for the Node exporter container (upstream port) + port: 8100 + # Specify the name of the container port + portName: http + # Configure a hostPort. If true, hostPort will be enabled in the container and set to service.port. + enableHostPort: false + + # Configure Proxy Endpoints Port + # This is the port being probed for readiness + proxyEndpointsPort: 8888 + # Configure a hostPort. If true, hostPort will be enabled in the container and set to proxyEndpointsPort. + enableProxyEndpointsHostPort: false + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 64Mi + # requests: + # cpu: 10m + # memory: 32Mi + + ## Additional volume mounts in the kube-rbac-proxy container + ## See extraVolumes below + extraVolumeMounts: [] + # - name: extra-volume + # mountPath: /extra + # readOnly: true + + ## tls enables using TLS resources from a volume on secret referred to in tlsSecret below. + ## When enabling tlsClientAuth, client CA certificate must be set in tlsSecret.caItem. + ## Ref. https://github.com/brancz/kube-rbac-proxy/issues/187 + tls: + enabled: false + tlsClientAuth: false + +## tlsSecret refers to an existing secret holding TLS items: client CA certificate, private key and certificate. +## secretName and volumeName can be templated. +## If enabled, volume volumeName gets created on secret secretName. +## The volume's resources will be used by kube-rbac-proxy if kubeRBACProxy.tls.enabled is set. +tlsSecret: + enabled: false + ## Key with client CA certificate (optional) + caItem: "" + ## Key with certificate + certItem: tls.crt + ## Key with private key + keyItem: tls.key + ## Name of an existing secret + secretName: prometheus-node-exporter-tls + ## Name of the volume to be created + volumeName: prometheus-node-exporter-tls + +## Service configuration +service: + ## Creating a service is enabled by default + enabled: true + + ## Service type + type: ClusterIP + ## IP address for type ClusterIP + clusterIP: "" + ## Default service port. Sets the port of the exposed container as well (NE or kubeRBACProxy). + ## Use "servicePort" below if changing the service port only is desired. + port: 9100 + ## Service port. Use this field if you wish to set a different service port + ## without changing the container port ("port" above). + servicePort: "" + ## Targeted port in the pod. Must refer to an open container port ("port" or "portName"). + ## (IntOrString) + targetPort: 9100 + ## Name of the service port. Sets the port name of the main container (NE) as well. + portName: metrics + ## Port number for service type NodePort + nodePort: null + + ## If true, node exporter will listen on all interfaces + listenOnAllInterfaces: true + + ## Additional annotations and labels for the service + annotations: + prometheus.io/scrape: "true" + labels: {} + + ## Dual stack settings for the service + ## https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ipDualStack: + enabled: false + ipFamilies: ["IPv6", "IPv4"] + ipFamilyPolicy: "PreferDualStack" + + ## External/Internal traffic policy setting (Cluster, Local) + ## https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-policies + externalTrafficPolicy: "" + internalTrafficPolicy: "" + +# Set a NetworkPolicy with: +# ingress only on service.port or custom policy +# no egress permitted +networkPolicy: + enabled: false + + # ingress: + # - {} + +# Additional environment variables that will be passed to the daemonset +env: {} +## env: +## VARIABLE: value + +prometheus: + monitor: + enabled: false + additionalLabels: {} + namespace: "" + + jobLabel: "" + + # List of pod labels to add to node exporter metrics + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md#servicemonitor + podTargetLabels: [] + + # List of target labels to add to node exporter metrics + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md#servicemonitor + targetLabels: [] + + scheme: http + basicAuth: {} + bearerTokenFile: + tlsConfig: {} + + ## proxyUrl: URL of a proxy that should be used for scraping. + ## + proxyUrl: "" + + ## Override serviceMonitor selector + ## + selectorOverride: {} + + ## Attach node metadata to discovered targets. Requires Prometheus v2.35.0 and above. + ## + attachMetadata: + node: false + + relabelings: [] + metricRelabelings: [] + interval: "" + scrapeTimeout: 10s + ## prometheus.monitor.apiVersion ApiVersion for the serviceMonitor Resource(defaults to "monitoring.coreos.com/v1") + apiVersion: "" + + ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. + ## + sampleLimit: 0 + + ## TargetLimit defines a limit on the number of scraped targets that will be accepted. + ## + targetLimit: 0 + + ## Per-scrape limit on number of labels that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelLimit: 0 + + ## Per-scrape limit on length of labels name that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelNameLengthLimit: 0 + + ## Per-scrape limit on length of labels value that will be accepted for a sample. Only valid in Prometheus versions 2.27.0 and newer. + ## + labelValueLengthLimit: 0 + + # PodMonitor defines monitoring for a set of pods. + # ref. https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md#podmonitor + # Using a PodMonitor may be preferred in some environments where there is very large number + # of Node Exporter endpoints (1000+) behind a single service. + # The PodMonitor is disabled by default. When switching from ServiceMonitor to PodMonitor, + # the time series resulting from the configuration through PodMonitor may have different labels. + # For instance, there will not be the service label any longer which might + # affect PromQL queries selecting that label. + podMonitor: + enabled: false + # Namespace in which to deploy the pod monitor. Defaults to the release namespace. + namespace: "" + # Additional labels, e.g. setting a label for pod monitor selector as set in prometheus + additionalLabels: {} + # release: kube-prometheus-stack + # PodTargetLabels transfers labels of the Kubernetes Pod onto the target. + podTargetLabels: [] + # apiVersion defaults to monitoring.coreos.com/v1. + apiVersion: "" + # Override pod selector to select pod objects. + selectorOverride: {} + # Attach node metadata to discovered targets. Requires Prometheus v2.35.0 and above. + attachMetadata: + node: false + # The label to use to retrieve the job name from. Defaults to label app.kubernetes.io/name. + jobLabel: "" + + # Scheme/protocol to use for scraping. + scheme: "http" + # Path to scrape metrics at. + path: "/metrics" + + # BasicAuth allow an endpoint to authenticate over basic authentication. + # More info: https://prometheus.io/docs/operating/configuration/#endpoint + basicAuth: {} + # Secret to mount to read bearer token for scraping targets. + # The secret needs to be in the same namespace as the pod monitor and accessible by the Prometheus Operator. + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secretkeyselector-v1-core + bearerTokenSecret: {} + # TLS configuration to use when scraping the endpoint. + tlsConfig: {} + # Authorization section for this endpoint. + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md#safeauthorization + authorization: {} + # OAuth2 for the URL. Only valid in Prometheus versions 2.27.0 and newer. + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md#oauth2 + oauth2: {} + + # ProxyURL eg http://proxyserver:2195. Directs scrapes through proxy to this endpoint. + proxyUrl: "" + # Interval at which endpoints should be scraped. If not specified Prometheus' global scrape interval is used. + interval: "" + # Timeout after which the scrape is ended. If not specified, the Prometheus global scrape interval is used. + scrapeTimeout: "" + # HonorTimestamps controls whether Prometheus respects the timestamps present in scraped data. + honorTimestamps: true + # HonorLabels chooses the metric's labels on collisions with target labels. + honorLabels: true + # Whether to enable HTTP2. Default false. + enableHttp2: "" + # Drop pods that are not running. (Failed, Succeeded). + # Enabled by default. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase + filterRunning: "" + # FollowRedirects configures whether scrape requests follow HTTP 3xx redirects. Default false. + followRedirects: "" + # Optional HTTP URL parameters + params: {} + + # RelabelConfigs to apply to samples before scraping. Prometheus Operator automatically adds + # relabelings for a few standard Kubernetes fields. The original scrape job's name + # is available via the __tmp_prometheus_job_name label. + # More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + relabelings: [] + # MetricRelabelConfigs to apply to samples before ingestion. + metricRelabelings: [] + + # SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. + sampleLimit: 0 + # TargetLimit defines a limit on the number of scraped targets that will be accepted. + targetLimit: 0 + # Per-scrape limit on number of labels that will be accepted for a sample. + # Only valid in Prometheus versions 2.27.0 and newer. + labelLimit: 0 + # Per-scrape limit on length of labels name that will be accepted for a sample. + # Only valid in Prometheus versions 2.27.0 and newer. + labelNameLengthLimit: 0 + # Per-scrape limit on length of labels value that will be accepted for a sample. + # Only valid in Prometheus versions 2.27.0 and newer. + labelValueLengthLimit: 0 + +## Customize the updateStrategy if set +updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 200m + # memory: 50Mi + # requests: + # cpu: 100m + # memory: 30Mi + +# Specify the container restart policy passed to the Node Export container +# Possible Values: Always (default)|OnFailure|Never +restartPolicy: null + +serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + annotations: {} + imagePullSecrets: [] + automountServiceAccountToken: false + +securityContext: + fsGroup: 65534 + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + +containerSecurityContext: + readOnlyRootFilesystem: true + # capabilities: + # add: + # - SYS_TIME + +rbac: + ## If true, create & use RBAC resources + ## + create: true + +# for deployments that have node_exporter deployed outside of the cluster, list +# their addresses here +endpoints: [] + +# Expose the service to the host network +hostNetwork: true + +# Share the host process ID namespace +hostPID: true + +# Share the host ipc namespace +hostIPC: false + +# Mount the node's root file system (/) at /host/root in the container +hostRootFsMount: + enabled: true + # Defines how new mounts in existing mounts on the node or in the container + # are propagated to the container or node, respectively. Possible values are + # None, HostToContainer, and Bidirectional. If this field is omitted, then + # None is used. More information on: + # https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation + mountPropagation: HostToContainer + +# Mount the node's proc file system (/proc) at /host/proc in the container +hostProcFsMount: + # Possible values are None, HostToContainer, and Bidirectional + mountPropagation: "" + +# Mount the node's sys file system (/sys) at /host/sys in the container +hostSysFsMount: + # Possible values are None, HostToContainer, and Bidirectional + mountPropagation: "" + +## Assign a group of affinity scheduling rules +## The default nodeAffinity excludes Fargate nodes and virtual kubelets from scheduling +## unless overriden by hard node affinity set in the field. +affinity: {} +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchFields: +# - key: metadata.name +# operator: In +# values: +# - target-host-name + +# Annotations to be added to node exporter pods +podAnnotations: + # Fix for very slow GKE cluster upgrades + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + +# Extra labels to add to node exporter pods (can be templated) +podLabels: {} + +## Extra labels to attach to all resources (can be templated) +commonLabels: {} + +# Annotations to be added to node exporter daemonset +daemonsetAnnotations: {} + +## set to true to add the release label so scraping of the servicemonitor with kube-prometheus-stack works out of the box +releaseLabel: false + +# Custom DNS configuration to be added to prometheus-node-exporter pods +dnsConfig: {} +# nameservers: +# - 1.2.3.4 +# searches: +# - ns1.svc.cluster-domain.example +# - my.dns.search.suffix +# options: +# - name: ndots +# value: "2" +# - name: edns0 + +## Assign a nodeSelector if operating a hybrid cluster +## +nodeSelector: + kubernetes.io/os: linux + # kubernetes.io/arch: amd64 + +# Specify grace period for graceful termination of pods. Defaults to 30 if null or not specified +terminationGracePeriodSeconds: null + +tolerations: + - effect: NoSchedule + operator: Exists + +# Enable or disable container termination message settings +# https://kubernetes.io/docs/tasks/debug/debug-application/determine-reason-pod-failure/ +terminationMessageParams: + enabled: false + # If enabled, specify the path for termination messages + terminationMessagePath: /dev/termination-log + # If enabled, specify the policy for termination messages + terminationMessagePolicy: File + + +## Assign a PriorityClassName to pods if set +# priorityClassName: "" + +## Additional container arguments +## +extraArgs: [] +# - --collector.diskstats.ignored-devices=^(ram|loop|fd|(h|s|v)d[a-z]|nvme\\d+n\\d+p)\\d+$ +# - --collector.textfile.directory=/run/prometheus + +## Additional mounts from the host to node-exporter container +## +extraHostVolumeMounts: [] +# - name: +# hostPath: +# https://kubernetes.io/docs/concepts/storage/volumes/#hostpath-volume-types +# type: "" (Default)|DirectoryOrCreate|Directory|FileOrCreate|File|Socket|CharDevice|BlockDevice +# mountPath: +# readOnly: true|false +# mountPropagation: None|HostToContainer|Bidirectional + +## Additional configmaps to be mounted. +## +configmaps: [] +# - name: +# mountPath: + +secrets: [] +# - name: +# mountPath: + +## Override the deployment namespace +## +namespaceOverride: "" + +## Additional containers for export metrics to text file; fields image,imagePullPolicy,securityContext take default value from main container +## +sidecars: [] +# - name: nvidia-dcgm-exporter +# image: nvidia/dcgm-exporter:1.4.3 +# volumeMounts: +# - name: tmp +# mountPath: /tmp + +## Volume for sidecar containers +## +sidecarVolumeMount: [] +# - name: collector-textfiles +# mountPath: /run/prometheus +# readOnly: false + +## Additional mounts from the host to sidecar containers +## +sidecarHostVolumeMounts: [] +# - name: +# hostPath: +# mountPath: +# readOnly: true|false +# mountPropagation: None|HostToContainer|Bidirectional + +## Additional InitContainers to initialize the pod +## +extraInitContainers: [] + +## Liveness probe +## +livenessProbe: + failureThreshold: 3 + httpGet: + httpHeaders: [] + scheme: http + initialDelaySeconds: 0 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +## Readiness probe +## +readinessProbe: + failureThreshold: 3 + httpGet: + httpHeaders: [] + scheme: http + initialDelaySeconds: 0 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +# Enable vertical pod autoscaler support for prometheus-node-exporter +verticalPodAutoscaler: + enabled: false + + # Recommender responsible for generating recommendation for the object. + # List should be empty (then the default recommender will generate the recommendation) + # or contain exactly one recommender. + # recommenders: + # - name: custom-recommender-performance + + # List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + controlledResources: [] + # Specifies which resource values should be controlled: RequestsOnly or RequestsAndLimits. + # controlledValues: RequestsAndLimits + + # Define the max allowed resources for the pod + maxAllowed: {} + # cpu: 200m + # memory: 100Mi + # Define the min allowed resources for the pod + minAllowed: {} + # cpu: 200m + # memory: 100Mi + + # updatePolicy: + # Specifies minimal number of replicas which need to be alive for VPA Updater to attempt pod eviction + # minReplicas: 1 + # Specifies whether recommended updates are applied when a Pod is started and whether recommended updates + # are applied during the life of a Pod. Possible values are "Off", "Initial", "Recreate", and "Auto". + # updateMode: Auto + +# Extra manifests to deploy as an array +extraManifests: [] + # - | + # apiVersion: v1 + # kind: ConfigMap + # metadata: + # name: prometheus-extra + # data: + # extra-data: "value" + +## Extra volumes to become available in the pod +extraVolumes: [] + # - name: extra-volume + # secret: + # defaultMode: 420 + # optional: false + # secretName: node-exporter-secret + +## Extra volume mounts in the node-exporter container +extraVolumeMounts: [] + # - name: extra-volume + # mountPath: /extra + # readOnly: true + +# Override version of app, required if image.tag is defined and does not follow semver +version: "" diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/.helmignore b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/.helmignore new file mode 100644 index 0000000..4bcfe5f --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/.helmignore @@ -0,0 +1,26 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj + +# OWNERS file for Kubernetes +OWNERS + +ci/ diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/Chart.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/Chart.yaml new file mode 100644 index 0000000..7b608f3 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/Chart.yaml @@ -0,0 +1,27 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/prometheus-community/helm-charts +apiVersion: v2 +appVersion: v1.11.2 +description: A Helm chart for prometheus pushgateway +home: https://github.com/prometheus/pushgateway +keywords: +- pushgateway +- prometheus +maintainers: +- email: gianrubio@gmail.com + name: gianrubio + url: https://github.com/gianrubio +- email: christian.staude@staffbase.com + name: cstaud + url: https://github.com/cstaud +- email: rootsandtrees@posteo.de + name: zeritti + url: https://github.com/zeritti +name: prometheus-pushgateway +sources: +- https://github.com/prometheus/pushgateway +type: application +version: 3.4.2 diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/README.md b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/README.md new file mode 100644 index 0000000..8cf8fda --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/README.md @@ -0,0 +1,101 @@ +# Prometheus Pushgateway + +This chart bootstraps a Prometheus [Pushgateway](http://github.com/prometheus/pushgateway) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +An optional prometheus `ServiceMonitor` can be enabled, should you wish to use this gateway with [Prometheus Operator](https://github.com/coreos/prometheus-operator). + +## Usage + +The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/). + +- OCI Artifact: `oci://ghcr.io/prometheus-community/charts/prometheus-pushgateway` +- Helm Repository: `https://prometheus-community.github.io/helm-charts` with chart `prometheus-pushgateway` + +The installation instructions use the OCI registry. Refer to the [`helm repo`]([`helm repo`](https://helm.sh/docs/helm/helm_repo/)) command documentation for information on installing charts via the traditional repository. + +### Install Chart + +```console +helm install [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/prometheus-pushgateway +``` + +_See [configuration](#configuration) below._ + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +### Uninstall Chart + +```console +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +### Upgrading Chart + +```console +helm upgrade [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/prometheus-pushgateway --install +``` + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +#### To 3.0.0 + +Previously, as dynamic labels were also set on the statefulset's volume claim template, it was not possible +to upgrade a chart release in a usual manner whilst using a statefulset and persistence due to the volume claim template's fields being immutable. + +This release removes the dynamic labels from the statefulset's volume claim template. +If you have configured a statefulset with persistent storage, +please, delete the statefulset before upgrading: + +```console +kubectl delete sts -l app.kubernetes.io/name=prometheus-pushgateway --cascade=orphan +``` + +#### To 2.0.0 + +Chart API version has been upgraded to v2 so Helm 3 is needed from now on. + +Docker image tag is used from Chart.yaml appVersion field by default now. + +Version 2.0.0 also adapted [Helm label and annotation best practices](https://helm.sh/docs/chart_best_practices/labels/). Specifically, labels mapping is listed below: + +```console +OLD => NEW +---------------------------------------- +heritage => app.kubernetes.io/managed-by +chart => helm.sh/chart +[container version] => app.kubernetes.io/version +app => app.kubernetes.io/name +release => app.kubernetes.io/instance +``` + +Therefore, depending on the way you've configured the chart, the previous StatefulSet or Deployment need to be deleted before upgrade. + +If `runAsStatefulSet: false` (this is the default): + +```console +kubectl delete deploy -l app=prometheus-pushgateway +``` + +If `runAsStatefulSet: true`: + +```console +kubectl delete sts -l app=prometheus-pushgateway +``` + +After that do the actual upgrade: + +```console +helm upgrade -i prometheus-pushgateway prometheus-community/prometheus-pushgateway +``` + +## Configuration + +See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: + +```console +helm show values oci://ghcr.io/prometheus-community/charts/prometheus-pushgateway +``` diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/NOTES.txt b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/NOTES.txt new file mode 100644 index 0000000..263b1d8 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/NOTES.txt @@ -0,0 +1,19 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ template "prometheus-pushgateway.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus-pushgateway.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ template "prometheus-pushgateway.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "prometheus-pushgateway.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ template "prometheus-pushgateway.namespace" . }} {{ template "prometheus-pushgateway.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ template "prometheus-pushgateway.namespace" . }} -l "app.kubernetes.io/name={{ template "prometheus-pushgateway.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl port-forward $POD_NAME 9091 + echo "Visit http://127.0.0.1:9091 to use your application" +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/_helpers.tpl b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/_helpers.tpl new file mode 100644 index 0000000..ba379b2 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/_helpers.tpl @@ -0,0 +1,297 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus-pushgateway.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Namespace to set on the resources +*/}} +{{- define "prometheus-pushgateway.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "prometheus-pushgateway.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus-pushgateway.chart" -}} +{{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "prometheus-pushgateway.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "prometheus-pushgateway.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create default labels +*/}} +{{- define "prometheus-pushgateway.defaultLabels" -}} +helm.sh/chart: {{ include "prometheus-pushgateway.chart" . }} +{{ include "prometheus-pushgateway.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.podLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "prometheus-pushgateway.selectorLabels" -}} +app.kubernetes.io/name: {{ include "prometheus-pushgateway.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Define webConfiguration +*/}} +{{- define "prometheus-pushgateway.webConfiguration" -}} +basic_auth_users: +{{- range $k, $v := .Values.webConfiguration.basicAuthUsers }} + {{ $k }}: {{ htpasswd "" $v | trimPrefix ":"}} +{{- end }} +{{- end }} + +{{/* +Define Authorization +*/}} +{{- define "prometheus-pushgateway.Authorization" -}} +{{- $users := keys .Values.webConfiguration.basicAuthUsers }} +{{- $user := first $users }} +{{- $password := index .Values.webConfiguration.basicAuthUsers $user }} +{{- $user }}:{{ $password }} +{{- end }} + +{{/* +Define basicAuth +*/}} +{{- define "prometheus-pushgateway.basicAuth" -}} +{{- $users := keys .Values.webConfiguration.basicAuthUsers }} +{{- $user := first $users }} +{{- $password := index .Values.webConfiguration.basicAuthUsers $user -}} +user: {{ $user | b64enc | quote }} +password: {{ $password | b64enc | quote }} +{{- end }} + +{{/* +Set the image with or without the registry +*/}} +{{- define "prometheus-pushgateway.image" -}} +{{- $registry := default .Values.image.registry (.Values.global).imageRegistry }} +{{- $repository := .Values.image.repository }} +{{- $tag := default .Chart.AppVersion .Values.image.tag }} +{{- if $registry }} + {{- printf "%s/%s:%s" $registry $repository $tag -}} +{{- else -}} + {{- printf "%s:%s" $repository $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Returns pod spec +*/}} +{{- define "prometheus-pushgateway.podSpec" -}} +serviceAccountName: {{ include "prometheus-pushgateway.serviceAccountName" . }} +automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} +{{- with .Values.priorityClassName }} +priorityClassName: {{ . | quote }} +{{- end }} +{{- with .Values.hostAliases }} +hostAliases: +{{- toYaml . | nindent 2 }} +{{- end }} +{{- with (.Values.global).imagePullSecrets | default .Values.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.extraInitContainers }} +initContainers: + {{- toYaml . | nindent 2 }} +{{- end }} +containers: + {{- with .Values.extraContainers }} + {{- toYaml . | nindent 2 }} + {{- end }} + - name: pushgateway + image: {{ include "prometheus-pushgateway.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.extraVars }} + env: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- if or .Values.extraArgs .Values.webConfiguration }} + args: + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .Values.webConfiguration }} + - --web.config.file=/etc/config/web-config.yaml + {{- end }} + {{- end }} + ports: + - name: metrics + containerPort: 9091 + protocol: TCP + {{- if .Values.liveness.enabled }} + {{- $livenessCommon := omit .Values.liveness.probe "httpGet" }} + livenessProbe: + {{- with .Values.liveness.probe }} + httpGet: + path: {{ .httpGet.path }} + port: {{ .httpGet.port }} + {{- if or .httpGet.httpHeaders $.Values.webConfiguration.basicAuthUsers }} + httpHeaders: + {{- if $.Values.webConfiguration.basicAuthUsers }} + - name: Authorization + value: Basic {{ include "prometheus-pushgateway.Authorization" $ | b64enc }} + {{- end }} + {{- with .httpGet.httpHeaders }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- toYaml $livenessCommon | nindent 6 }} + {{- end }} + {{- end }} + {{- if .Values.readiness.enabled }} + {{- $readinessCommon := omit .Values.readiness.probe "httpGet" }} + readinessProbe: + {{- with .Values.readiness.probe }} + httpGet: + path: {{ .httpGet.path }} + port: {{ .httpGet.port }} + {{- if or .httpGet.httpHeaders $.Values.webConfiguration.basicAuthUsers }} + httpHeaders: + {{- if $.Values.webConfiguration.basicAuthUsers }} + - name: Authorization + value: Basic {{ include "prometheus-pushgateway.Authorization" $ | b64enc }} + {{- end }} + {{- with .httpGet.httpHeaders }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- toYaml $readinessCommon | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.lifecycle }} + lifecycle: {{ toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: storage-volume + mountPath: "{{ .Values.persistentVolume.mountPath }}" + subPath: "{{ .Values.persistentVolume.subPath }}" + {{- if .Values.webConfiguration }} + - name: web-config + mountPath: "/etc/config" + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 6 }} + {{- end }} +{{- with .Values.nodeSelector }} +nodeSelector: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.tolerations }} +tolerations: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- if or .Values.podAntiAffinity .Values.affinity }} +affinity: +{{- end }} + {{- with .Values.affinity }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- if eq .Values.podAntiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [{{ include "prometheus-pushgateway.name" . }}]} + {{- else if eq .Values.podAntiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: {{ .Values.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [{{ include "prometheus-pushgateway.name" . }}]} + {{- end }} +{{- with .Values.topologySpreadConstraints }} +topologySpreadConstraints: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +volumes: + {{- $storageVolumeAsPVCTemplate := and .Values.runAsStatefulSet .Values.persistentVolume.enabled -}} + {{- if not $storageVolumeAsPVCTemplate }} + - name: storage-volume + {{- if .Values.persistentVolume.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.persistentVolume.existingClaim }}{{ .Values.persistentVolume.existingClaim }}{{- else }}{{ include "prometheus-pushgateway.fullname" . }}{{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.webConfiguration }} + - name: web-config + secret: + secretName: {{ include "prometheus-pushgateway.fullname" . }} + {{- end }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 2 }} + {{- else if $storageVolumeAsPVCTemplate }} + {{- if .Values.webConfiguration }} + - name: web-config + secret: + secretName: {{ include "prometheus-pushgateway.fullname" . }} + {{- else }} + [] + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/deployment.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/deployment.yaml new file mode 100644 index 0000000..a655380 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/deployment.yaml @@ -0,0 +1,32 @@ +{{- if not .Values.runAsStatefulSet }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +spec: + replicas: {{ .Values.replicaCount }} + {{- with .Values.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "prometheus-pushgateway.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 8 }} + spec: + {{- include "prometheus-pushgateway.podSpec" . | nindent 6 }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/extra-manifests.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/extra-manifests.yaml new file mode 100644 index 0000000..bafee95 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/extra-manifests.yaml @@ -0,0 +1,8 @@ +{{- range .Values.extraManifests }} +--- + {{- if typeIs "string" . }} + {{- tpl . $ }} + {{- else }} + {{- tpl (. | toYaml | nindent 0) $ }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/ingress.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/ingress.yaml new file mode 100644 index 0000000..c449406 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/ingress.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ingress.enabled }} +{{- $serviceName := include "prometheus-pushgateway.fullname" . }} +{{- $servicePort := .Values.service.port }} +{{- $ingressPath := .Values.ingress.path }} +{{- $ingressClassName := .Values.ingress.className }} +{{- $ingressPathType := .Values.ingress.pathType }} +{{- $extraPaths := .Values.ingress.extraPaths }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +spec: + ingressClassName: {{ $ingressClassName }} + rules: + {{- range $host := .Values.ingress.hosts }} + - host: {{ $host }} + http: + paths: + {{- with $extraPaths }} + {{- toYaml . | nindent 10 }} + {{- end }} + - path: {{ $ingressPath }} + pathType: {{ $ingressPathType }} + backend: + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- end -}} + {{- with .Values.ingress.tls }} + tls: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/networkpolicy.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/networkpolicy.yaml new file mode 100644 index 0000000..529b255 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/networkpolicy.yaml @@ -0,0 +1,26 @@ +{{- if .Values.networkPolicy }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + {{- if .Values.networkPolicy.customSelectors }} + name: ingress-allow-customselector-{{ template "prometheus-pushgateway.name" . }} + {{- else if .Values.networkPolicy.allowAll }} + name: ingress-allow-all-{{ template "prometheus-pushgateway.name" . }} + {{- else -}} + {{- fail "One of `allowAll` or `customSelectors` must be specified." }} + {{- end }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +spec: + podSelector: + matchLabels: + {{- include "prometheus-pushgateway.selectorLabels" . | nindent 6 }} + ingress: + - ports: + - port: {{ .Values.service.targetPort }} + {{- with .Values.networkPolicy.customSelectors }} + from: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/pdb.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/pdb.yaml new file mode 100644 index 0000000..1ee77e1 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/pdb.yaml @@ -0,0 +1,14 @@ +{{- if .Values.podDisruptionBudget }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +spec: + selector: + matchLabels: + {{- include "prometheus-pushgateway.selectorLabels" . | nindent 6 }} + {{- toYaml .Values.podDisruptionBudget | nindent 2 }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/pushgateway-pvc.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/pushgateway-pvc.yaml new file mode 100644 index 0000000..d2a85f4 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/pushgateway-pvc.yaml @@ -0,0 +1,29 @@ +{{- if and (not .Values.runAsStatefulSet) .Values.persistentVolume.enabled (not .Values.persistentVolume.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- with .Values.persistentVolume.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + {{- with .Values.persistentVolumeLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +spec: + accessModes: + {{- toYaml .Values.persistentVolume.accessModes | nindent 4 }} + {{- if .Values.persistentVolume.storageClass }} + {{- if (eq "-" .Values.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistentVolume.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: "{{ .Values.persistentVolume.size }}" +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/secret.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/secret.yaml new file mode 100644 index 0000000..a6d6c04 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/secret.yaml @@ -0,0 +1,24 @@ +{{- if .Values.webConfiguration }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ include "prometheus-pushgateway.namespace" . }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} +data: + web-config.yaml: {{ include "prometheus-pushgateway.webConfiguration" . | b64enc}} +{{- end }} +--- +{{- if and .Values.webConfiguration .Values.serviceMonitor.enabled (empty .Values.serviceMonitor.basicAuth) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "prometheus-pushgateway.fullname" . }}-basic-auth + namespace: {{ default (include "prometheus-pushgateway.namespace" .) .Values.serviceMonitor.namespace }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} +data: + {{- include "prometheus-pushgateway.basicAuth" . | nindent 2 }} +type: Opaque +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/service.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/service.yaml new file mode 100644 index 0000000..15029f7 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/service.yaml @@ -0,0 +1,45 @@ +{{- $stsNoHeadlessSvcTypes := list "LoadBalancer" "NodePort" -}} +apiVersion: v1 +kind: Service +metadata: + {{- with .Values.serviceAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + {{- with .Values.serviceLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +spec: + {{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{ else if and .Values.runAsStatefulSet (not (has .Values.service.type $stsNoHeadlessSvcTypes)) }} + clusterIP: None # Headless service + {{- end }} + {{- if .Values.service.ipDualStack.enabled }} + ipFamilies: {{ toYaml .Values.service.ipDualStack.ipFamilies | nindent 4 }} + ipFamilyPolicy: {{ .Values.service.ipDualStack.ipFamilyPolicy }} + {{- end }} + type: {{ .Values.service.type }} + {{- with .Values.service.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} + {{- end }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} + {{- if and (eq .Values.service.type "NodePort") .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + protocol: TCP + name: {{ .Values.service.portName }} + selector: + {{- include "prometheus-pushgateway.selectorLabels" . | nindent 4 }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/serviceaccount.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/serviceaccount.yaml new file mode 100644 index 0000000..88f1470 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + {{- with .Values.serviceAccountLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus-pushgateway.serviceAccountName" . }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/servicemonitor.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/servicemonitor.yaml new file mode 100644 index 0000000..78a2081 --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/servicemonitor.yaml @@ -0,0 +1,58 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + {{- if .Values.serviceMonitor.additionalLabels }} + {{- toYaml .Values.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ default (include "prometheus-pushgateway.namespace" .) .Values.serviceMonitor.namespace }} +spec: + endpoints: + - port: {{ .Values.service.portName }} + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scheme }} + scheme: {{ . }} + {{- end }} + {{- if and .Values.webConfiguration (empty .Values.serviceMonitor.basicAuth) }} + basicAuth: + password: + name: {{ include "prometheus-pushgateway.fullname" . }}-basic-auth + key: password + username: + name: {{ include "prometheus-pushgateway.fullname" . }}-basic-auth + key: user + {{- else if not (empty .Values.serviceMonitor.basicAuth) }} + basicAuth: {{ toYaml .Values.serviceMonitor.basicAuth | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml .| nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + path: {{ .Values.serviceMonitor.telemetryPath }} + honorLabels: {{ .Values.serviceMonitor.honorLabels }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- tpl (toYaml . | nindent 6) $ }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ template "prometheus-pushgateway.namespace" . }} + selector: + matchLabels: + {{- include "prometheus-pushgateway.selectorLabels" . | nindent 6 }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/statefulset.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/statefulset.yaml new file mode 100644 index 0000000..6fa39ea --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/templates/statefulset.yaml @@ -0,0 +1,51 @@ +{{- if .Values.runAsStatefulSet }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 4 }} + name: {{ include "prometheus-pushgateway.fullname" . }} + namespace: {{ template "prometheus-pushgateway.namespace" . }} +spec: + replicas: {{ .Values.replicaCount }} + serviceName: {{ include "prometheus-pushgateway.fullname" . }} + selector: + matchLabels: + {{- include "prometheus-pushgateway.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus-pushgateway.defaultLabels" . | nindent 8 }} + spec: + {{- include "prometheus-pushgateway.podSpec" . | nindent 6 }} + {{- if .Values.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + {{- with .Values.persistentVolume.annotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.persistentVolumeLabels }} + labels: + {{- toYaml . | nindent 10 }} + {{- end }} + name: storage-volume + spec: + accessModes: + {{ toYaml .Values.persistentVolume.accessModes }} + {{- if .Values.persistentVolume.storageClass }} + {{- if (eq "-" .Values.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistentVolume.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: "{{ .Values.persistentVolume.size }}" + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/charts/prometheus-pushgateway/values.yaml b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/values.yaml new file mode 100644 index 0000000..93d780f --- /dev/null +++ b/utils/assets/charts/prometheus/charts/prometheus-pushgateway/values.yaml @@ -0,0 +1,393 @@ +# Default values for prometheus-pushgateway. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + imageRegistry: "" + imagePullSecrets: [] + +# Provide a name in place of prometheus-pushgateway for `app:` labels +nameOverride: "" + +# Provide a name to substitute for the full names of resources +fullnameOverride: "" + +# Provide a namespace to substitude for the namespace on resources +namespaceOverride: "" + +image: + registry: "" + repository: quay.io/prometheus/pushgateway + # if not set appVersion field from Chart.yaml is used + tag: "" + pullPolicy: IfNotPresent + +# Optional pod imagePullSecrets +imagePullSecrets: [] + +service: + type: ClusterIP + port: 9091 + targetPort: 9091 + # nodePort: 32100 + portName: http + + # Optional - Can be used for headless if value is "None" + clusterIP: "" + + ipDualStack: + enabled: false + ipFamilies: ["IPv6", "IPv4"] + ipFamilyPolicy: "PreferDualStack" + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + +# Whether to automatically mount a service account token into the pod +automountServiceAccountToken: true + +# Optional deployment annotations +deploymentAnnotations: {} + +# Optional pod annotations +podAnnotations: {} + +# Optional pod labels +podLabels: {} + +# Optional service annotations +serviceAnnotations: {} + +# Optional service labels +serviceLabels: {} + +# Optional serviceAccount labels +serviceAccountLabels: {} + +# Optional persistentVolume labels +persistentVolumeLabels: {} + +# Optional additional environment variables +extraVars: [] + +## Additional pushgateway container arguments +## +## example: +## extraArgs: +## - --persistence.file=/data/pushgateway.data +## - --persistence.interval=5m +extraArgs: [] + +## Additional InitContainers to initialize the pod +## +extraInitContainers: [] + +# Optional additional containers (sidecar) +extraContainers: [] + # - name: oAuth2-proxy + # args: + # - -https-address=:9092 + # - -upstream=http://localhost:9091 + # - -skip-auth-regex=^/metrics + # - -openshift-delegate-urls={"/":{"group":"monitoring.coreos.com","resource":"prometheuses","verb":"get"}} + # image: openshift/oauth-proxy:v1.1.0 + # ports: + # - containerPort: 9092 + # name: proxy + # resources: + # limits: + # memory: 16Mi + # requests: + # memory: 4Mi + # cpu: 20m + # volumeMounts: + # - mountPath: /etc/prometheus/secrets/pushgateway-tls + # name: secret-pushgateway-tls + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 200m + # memory: 50Mi + # requests: + # cpu: 100m + # memory: 30Mi + +# -- Sets web configuration +# To enable basic authentication, provide basicAuthUsers as a map +# If serviceMonitor.enabled is set, a secret with these credentials will be created +# and configured in serviceMonitor. serviceMonitor.basicAuth overrides this secret. +webConfiguration: {} + # basicAuthUsers: + # username: password + +liveness: + enabled: true + probe: + httpGet: + path: /-/healthy + port: 9091 + initialDelaySeconds: 10 + timeoutSeconds: 10 + +readiness: + enabled: true + probe: + httpGet: + path: /-/ready + port: 9091 + initialDelaySeconds: 10 + timeoutSeconds: 10 + +serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + +## Configure ingress resource that allow you to access the +## pushgateway installation. Set up the URL +## ref: http://kubernetes.io/docs/user-guide/ingress/ +## +ingress: + ## Enable Ingress. + ## + enabled: false + # AWS ALB requires path of /* + className: "" + path: / + pathType: ImplementationSpecific + + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + + ## Annotations. + ## + # annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## Hostnames. + ## Must be provided if Ingress is enabled. + ## + # hosts: + # - pushgateway.domain.com + + ## TLS configuration. + ## Secrets must be manually created in the namespace. + ## + # tls: + # - secretName: pushgateway-tls + # hosts: + # - pushgateway.domain.com + +tolerations: [] + # - effect: NoSchedule + # operator: Exists + +## Node labels for pushgateway pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +replicaCount: 1 + +hostAliases: [] + # - ip: "127.0.0.1" + # hostnames: + # - "foo.local" + # - "bar.local" + # - ip: "10.1.2.3" + # hostnames: + # - "foo.remote" + # - "bar.remote" + +## When running more than one replica alongside with persistence, different volumes are needed +## per replica, since sharing a `persistence.file` across replicas does not keep metrics synced. +## For this purpose, you can enable the `runAsStatefulSet` to deploy the pushgateway as a +## StatefulSet instead of as a Deployment. +runAsStatefulSet: false + +## Security context to be added to push-gateway pods +## +securityContext: + fsGroup: 65534 + runAsUser: 65534 + runAsNonRoot: true + +## Security context to be added to push-gateway containers +## Having a separate variable as securityContext differs for pods and containers. +containerSecurityContext: {} +# allowPrivilegeEscalation: false +# readOnlyRootFilesystem: true +# runAsUser: 65534 +# runAsNonRoot: true + +## Affinity for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +affinity: {} + +## Pod anti-affinity can prevent the scheduler from placing pushgateway replicas on the same node. +## The value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. +## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. +## The default value "" will disable pod anti-affinity so that no anti-affinity rules will be configured (unless set in `affinity`). +## +podAntiAffinity: "" + +## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. +## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone +## +podAntiAffinityTopologyKey: kubernetes.io/hostname + +## Topology spread constraints for pods +## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +topologySpreadConstraints: [] + +# Enable this if you're using https://github.com/coreos/prometheus-operator +serviceMonitor: + enabled: false + namespace: monitoring + + # telemetryPath: HTTP resource path from which to fetch metrics. + # Telemetry path, default /metrics, has to be prefixed accordingly if pushgateway sets a route prefix at start-up. + # + telemetryPath: "/metrics" + + # Fallback to the prometheus default unless specified + interval: "" + + ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. + scheme: "" + + ## Basic authentication + basicAuth: {} + + ## Bearer token file + bearerTokenFile: "" + + ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. + ## Of type: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#tlsconfig + tlsConfig: {} + + # bearerTokenFile: + # Fallback to the prometheus default unless specified + scrapeTimeout: "" + + ## Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + additionalLabels: {} + + # Retain the job and instance labels of the metrics pushed to the Pushgateway + # [Scraping Pushgateway](https://github.com/prometheus/pushgateway#configure-the-pushgateway-as-a-target-to-scrape) + honorLabels: true + + ## Metric relabel configs to apply to samples before ingestion. + ## [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + ## Relabel configs to apply to samples before ingestion. + ## [Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + +# The values to set in the PodDisruptionBudget spec (minAvailable/maxUnavailable) +# If not set then a PodDisruptionBudget will not be created +podDisruptionBudget: {} + +priorityClassName: + +# Deployment Strategy type +strategy: + type: Recreate + +persistentVolume: + ## If true, pushgateway will create/use a Persistent Volume Claim + ## If false, use emptyDir + ## + enabled: false + + ## pushgateway data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## pushgateway data Persistent Volume Claim annotations + ## + annotations: {} + + ## pushgateway data Persistent Volume existing claim name + ## Requires pushgateway.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## pushgateway data Persistent Volume mount root path + ## + mountPath: /data + + ## pushgateway data Persistent Volume size + ## + size: 2Gi + + ## pushgateway data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## Subdirectory of pushgateway data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + +extraVolumes: [] + # - name: extra + # emptyDir: {} +extraVolumeMounts: [] + # - name: extra + # mountPath: /usr/share/extras + # readOnly: true + +# Configuration for clusters with restrictive network policies in place: +# - allowAll allows access to the PushGateway from any namespace +# - customSelector is a list of pod/namespaceSelectors to allow access from +# These options are mutually exclusive and the latter will take precedence. +networkPolicy: {} + # allowAll: true + # customSelectors: + # - namespaceSelector: + # matchLabels: + # type: admin + # - podSelector: + # matchLabels: + # app: myapp + +# Array of extra K8s objects to deploy (evaluated as a template) +# The value can hold an array of strings as well as objects +extraManifests: [] + +# Lifecycle hooks configuration +lifecycle: {} +# preStop: +# exec: +# command: ["/bin/sh", "-c", "sleep 30"] diff --git a/utils/assets/charts/prometheus/templates/NOTES.txt b/utils/assets/charts/prometheus/templates/NOTES.txt new file mode 100644 index 0000000..b0401f6 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/NOTES.txt @@ -0,0 +1,118 @@ +The Prometheus server can be accessed via port {{ .Values.server.service.servicePort }} on the following DNS name from within your cluster: +{{ template "prometheus.server.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.server.ingress.enabled -}} +For access from outside the cluster, the server URL(s) are: +{{- range .Values.server.ingress.hosts }} +http://{{ tpl . $ }} +{{- end }} +{{- else if .Values.server.route.main.enabled }} +For access from outside the cluster, the server URL(s) are: +{{- range .Values.server.route.main.hostnames }} +http://{{ tpl . $ }} +{{- end }} +{{- else }} +Get the Prometheus server URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.server.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.server.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.server.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.server.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.server.service.servicePort }} +{{- else if contains "ClusterIP" .Values.server.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "prometheus.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME {{ include "prometheus.port" . }} +{{- end }} + + +{{- if .Values.server.persistentVolume.enabled }} +{{- else }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the Server pod is terminated. ##### +################################################################################# +{{- end }} +{{- end }} + +{{ if .Values.alertmanager.enabled }} +The Prometheus alertmanager can be accessed via port {{ .Values.alertmanager.service.port }} on the following DNS name from within your cluster: +{{ template "prometheus.alertmanager.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.alertmanager.ingress.enabled -}} +From outside the cluster, the alertmanager URL(s) are: +{{- range .Values.alertmanager.ingress.hosts }} +http://{{ . }} +{{- end }} +{{- else }} +Get the Alertmanager URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.alertmanager.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.alertmanager.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.alertmanager.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.alertmanager.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.alertmanager.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.alertmanager.service.servicePort }} +{{- else if contains "ClusterIP" .Values.alertmanager.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "alertmanager.name" .Subcharts.alertmanager }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9093 +{{- end }} +{{- end }} + +{{- if .Values.alertmanager.persistence.enabled }} +{{- else }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the AlertManager pod is terminated. ##### +################################################################################# +{{- end }} +{{- end }} + +{{- if (index .Values "prometheus-node-exporter" "enabled") }} +################################################################################# +###### WARNING: Pod Security Policy has been disabled by default since ##### +###### it deprecated after k8s 1.25+. use ##### +###### (index .Values "prometheus-node-exporter" "rbac" ##### +###### . "pspEnabled") with (index .Values ##### +###### "prometheus-node-exporter" "rbac" "pspAnnotations") ##### +###### in case you still need it. ##### +################################################################################# +{{- end }} + +{{ if (index .Values "prometheus-pushgateway" "enabled") }} +The Prometheus PushGateway can be accessed via port {{ index .Values "prometheus-pushgateway" "service" "port" }} on the following DNS name from within your cluster: +{{ include "prometheus-pushgateway.fullname" (index .Subcharts "prometheus-pushgateway") }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if (index .Values "prometheus-pushgateway" "ingress" "enabled") -}} +From outside the cluster, the pushgateway URL(s) are: +{{- range (index .Values "prometheus-pushgateway" "ingress" "hosts") }} +http://{{ . }} +{{- end }} +{{- else }} +Get the PushGateway URL by running these commands in the same shell: +{{- $pushgateway_svc_type := index .Values "prometheus-pushgateway" "service" "type" -}} +{{- if contains "NodePort" $pushgateway_svc_type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "prometheus-pushgateway.fullname" (index .Subcharts "prometheus-pushgateway") }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" $pushgateway_svc_type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ include "prometheus-pushgateway.fullname" (index .Subcharts "prometheus-pushgateway") }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "prometheus-pushgateway.fullname" (index .Subcharts "prometheus-pushgateway") }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ index .Values "prometheus-pushgateway" "service" "port" }} +{{- else if contains "ClusterIP" $pushgateway_svc_type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ include "prometheus.name" (index .Subcharts "prometheus-pushgateway") }},component=pushgateway" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9091 +{{- end }} +{{- end }} +{{- end }} + +For more information on running Prometheus, visit: +https://prometheus.io/ diff --git a/utils/assets/charts/prometheus/templates/_helpers.tpl b/utils/assets/charts/prometheus/templates/_helpers.tpl new file mode 100644 index 0000000..29c89a1 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/_helpers.tpl @@ -0,0 +1,180 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the port for prometheus. +*/}} +{{- define "prometheus.port" -}} +9090 +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create labels for prometheus +*/}} +{{- define "prometheus.common.matchLabels" -}} +app.kubernetes.io/name: {{ include "prometheus.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create unified labels for prometheus components +*/}} +{{- define "prometheus.common.metaLabels" -}} +app.kubernetes.io/version: {{ .Chart.AppVersion }} +helm.sh/chart: {{ include "prometheus.chart" . }} +app.kubernetes.io/part-of: {{ include "prometheus.name" . }} +{{- with .Values.commonMetaLabels}} +{{ toYaml . }} +{{- end }} +{{- end -}} + +{{- define "prometheus.server.labels" -}} +{{ include "prometheus.server.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.server.matchLabels" -}} +app.kubernetes.io/component: {{ .Values.server.name }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified ClusterRole name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.clusterRoleName" -}} +{{- if .Values.server.clusterRoleNameOverride -}} +{{ .Values.server.clusterRoleNameOverride | trunc 63 | trimSuffix "-" }} +{{- else -}} +{{ include "prometheus.server.fullname" . }} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified alertmanager name for communicating and check to ensure that `alertmanager` exists before trying to use it with the user via NOTES.txt +*/}} +{{- define "prometheus.alertmanager.fullname" -}} +{{- if .Subcharts.alertmanager -}} +{{- template "alertmanager.fullname" .Subcharts.alertmanager -}} +{{- else -}} +{{- "alertmanager not found" -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified Prometheus server name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.server.fullname" -}} +{{- if .Values.server.fullnameOverride -}} +{{- .Values.server.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.server.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.server.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Get KubeVersion removing pre-release information. +*/}} +{{- define "prometheus.kubeVersion" -}} + {{- default .Capabilities.KubeVersion.Version (regexFind "v[0-9]+\\.[0-9]+\\.[0-9]+" .Capabilities.KubeVersion.Version) -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "prometheus.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the server component +*/}} +{{- define "prometheus.serviceAccountName.server" -}} +{{- if .Values.serviceAccounts.server.create -}} + {{ default (include "prometheus.server.fullname" .) .Values.serviceAccounts.server.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.server.name }} +{{- end -}} +{{- end -}} + +{{/* +Define the prometheus.namespace template if set with forceNamespace or .Release.Namespace is set +*/}} +{{- define "prometheus.namespace" -}} + {{- default .Release.Namespace .Values.forceNamespace -}} +{{- end }} + +{{/* +Define template prometheus.namespaces producing a list of namespaces to monitor +*/}} +{{- define "prometheus.namespaces" -}} +{{- $namespaces := list }} +{{- if and .Values.rbac.create .Values.server.useExistingClusterRoleName }} + {{- if .Values.server.namespaces -}} + {{- range $ns := join "," .Values.server.namespaces | split "," }} + {{- $namespaces = append $namespaces (tpl $ns $) }} + {{- end -}} + {{- end -}} + {{- if .Values.server.releaseNamespace -}} + {{- $namespaces = append $namespaces (include "prometheus.namespace" .) }} + {{- end -}} +{{- end -}} +{{ mustToJson $namespaces }} +{{- end -}} + +{{/* +Define prometheus.server.remoteWrite producing a list of remoteWrite configurations with URL templating +*/}} +{{- define "prometheus.server.remoteWrite" -}} +{{- $remoteWrites := list }} +{{- range $remoteWrite := .Values.server.remoteWrite }} + {{- $remoteWrites = tpl $remoteWrite.url $ | set $remoteWrite "url" | append $remoteWrites }} +{{- end -}} +{{ toYaml $remoteWrites }} +{{- end -}} + +{{/* +Define prometheus.server.remoteRead producing a list of remoteRead configurations with URL templating +*/}} +{{- define "prometheus.server.remoteRead" -}} +{{- $remoteReads := list }} +{{- range $remoteRead := .Values.server.remoteRead }} + {{- $remoteReads = tpl $remoteRead.url $ | set $remoteRead "url" | append $remoteReads }} +{{- end -}} +{{ toYaml $remoteReads }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/templates/clusterrole.yaml b/utils/assets/charts/prometheus/templates/clusterrole.yaml new file mode 100644 index 0000000..eb6df22 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/clusterrole.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.rbac.create (empty .Values.server.useExistingClusterRoleName) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ include "prometheus.clusterRoleName" . }} +rules: + - apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - nodes/metrics + - services + - endpoints + - pods + - ingresses + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "networking.k8s.io" + resources: + - ingresses/status + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch + - nonResourceURLs: + - "/metrics" + verbs: + - get +{{- end }} diff --git a/utils/assets/charts/prometheus/templates/clusterrolebinding.yaml b/utils/assets/charts/prometheus/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..5050a9e --- /dev/null +++ b/utils/assets/charts/prometheus/templates/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.rbac.create (empty .Values.server.namespaces) (empty .Values.server.useExistingClusterRoleName) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ include "prometheus.clusterRoleName" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.server" . }} + namespace: {{ include "prometheus.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "prometheus.clusterRoleName" . }} +{{- end }} diff --git a/utils/assets/charts/prometheus/templates/cm.yaml b/utils/assets/charts/prometheus/templates/cm.yaml new file mode 100644 index 0000000..f150657 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/cm.yaml @@ -0,0 +1,107 @@ +{{- if and (empty .Values.server.configMapOverrideName) (empty .Values.server.configFromSecret) -}} +apiVersion: v1 +kind: ConfigMap +metadata: +{{- with .Values.server.configMapAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + {{- with .Values.server.extraConfigmapLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "prometheus.namespace" . }} +data: + allow-snippet-annotations: "false" +{{- $root := . -}} +{{- range $key, $value := .Values.ruleFiles }} + {{ $key }}: {{- toYaml $value | indent 2 }} +{{- end }} +{{- range $key, $value := .Values.serverFiles }} + {{ $key }}: | +{{- if eq $key "prometheus.yml" }} + global: +{{ $root.Values.server.global | toYaml | trimSuffix "\n" | indent 6 }} +{{- if $root.Values.server.remoteWrite }} + remote_write: +{{- include "prometheus.server.remoteWrite" $root | nindent 4 }} +{{- end }} +{{- if $root.Values.server.remoteRead }} + remote_read: +{{- include "prometheus.server.remoteRead" $root | nindent 4 }} +{{- end }} +{{- if or $root.Values.server.tsdb $root.Values.server.exemplars }} + storage: +{{- if $root.Values.server.tsdb }} + tsdb: +{{ $root.Values.server.tsdb | toYaml | indent 8 }} +{{- end }} +{{- if $root.Values.server.exemplars }} + exemplars: +{{ $root.Values.server.exemplars | toYaml | indent 8 }} +{{- end }} +{{- end }} +{{- if $root.Values.server.otlp }} + otlp: +{{ $root.Values.server.otlp | toYaml | indent 8 }} +{{- end }} +{{- if $root.Values.scrapeConfigFiles }} + scrape_config_files: +{{ toYaml $root.Values.scrapeConfigFiles | indent 4 }} +{{- end }} +{{- end }} +{{- if eq $key "alerts" }} +{{- if and (not (empty $value)) (empty $value.groups) }} + groups: +{{- range $ruleKey, $ruleValue := $value }} + - name: {{ $ruleKey -}}.rules + rules: +{{ $ruleValue | toYaml | trimSuffix "\n" | indent 6 }} +{{- end }} +{{- else }} +{{ toYaml $value | indent 4 }} +{{- end }} +{{- else }} +{{ toYaml $value | default "{}" | indent 4 }} +{{- end }} +{{- if eq $key "prometheus.yml" -}} +{{- if $root.Values.extraScrapeConfigs }} +{{ tpl $root.Values.extraScrapeConfigs $root | indent 4 }} +{{- end -}} +{{- if or ($root.Values.alertmanager.enabled) ($root.Values.server.alertmanagers) }} + alerting: +{{- if $root.Values.alertRelabelConfigs }} +{{ $root.Values.alertRelabelConfigs | toYaml | trimSuffix "\n" | indent 6 }} +{{- end }} + alertmanagers: +{{- if $root.Values.server.alertmanagers }} +{{ toYaml $root.Values.server.alertmanagers | indent 8 }} +{{- else }} + - kubernetes_sd_configs: + - role: pod + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + {{- if $root.Values.alertmanager.prefixURL }} + path_prefix: {{ $root.Values.alertmanager.prefixURL }} + {{- end }} + relabel_configs: + - source_labels: [__meta_kubernetes_namespace] + regex: {{ $root.Release.Namespace }} + action: keep + - source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_instance] + regex: {{ $root.Release.Name }} + action: keep + - source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name] + regex: {{ default "alertmanager" $root.Values.alertmanager.nameOverride | trunc 63 | trimSuffix "-" }} + action: keep + - source_labels: [__meta_kubernetes_pod_container_port_number] + regex: "9093" + action: keep +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/templates/deploy.yaml b/utils/assets/charts/prometheus/templates/deploy.yaml new file mode 100644 index 0000000..79bdb7d --- /dev/null +++ b/utils/assets/charts/prometheus/templates/deploy.yaml @@ -0,0 +1,488 @@ +apiVersion: apps/v1 +{{- if .Values.server.statefulSet.enabled }} +kind: StatefulSet +metadata: + {{- if .Values.server.deploymentAnnotations }} + annotations: + {{ toYaml .Values.server.deploymentAnnotations | nindent 4 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + {{- with .Values.server.statefulSet.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- else if .Values.server.daemonSet.enabled }} +kind: DaemonSet +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + {{- with .Values.server.daemonSet.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- else }} +kind: Deployment +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + {{- with .Values.server.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "prometheus.namespace" . }} +spec: + {{- if .Values.server.statefulSet.enabled }} + {{- if semverCompare ">= 1.27.x" (include "prometheus.kubeVersion" .) }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ ternary "Delete" "Retain" .Values.server.statefulSet.pvcDeleteOnStsDelete }} + whenScaled: {{ ternary "Delete" "Retain" .Values.server.statefulSet.pvcDeleteOnStsScale }} + {{- end }} + podManagementPolicy: {{ .Values.server.statefulSet.podManagementPolicy }} + serviceName: {{ template "prometheus.server.fullname" . }}-headless + {{- with .Values.server.statefulSet.updateStrategy }} + updateStrategy: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- else if .Values.server.daemonSet.enabled }} + {{- with .Values.server.daemonSet.updateStrategy }} + updateStrategy: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- else }} + {{- with .Values.server.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{ if eq .type "Recreate" }}rollingUpdate: null{{ end }} + {{- end }} + {{- end }} + selector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + {{- if not .Values.server.daemonSet.enabled }} + replicas: {{ .Values.server.replicaCount }} + {{- end }} + revisionHistoryLimit: {{ .Values.server.revisionHistoryLimit }} + template: + metadata: + {{- if .Values.server.podAnnotations }} + annotations: + {{ toYaml .Values.server.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 8 }} + {{- if .Values.server.podLabels}} + {{ toYaml .Values.server.podLabels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.server.priorityClassName }} + priorityClassName: "{{ .Values.server.priorityClassName }}" +{{- end }} +{{- if .Values.server.runtimeClassName }} + runtimeClassName: "{{ .Values.server.runtimeClassName }}" +{{- end }} +{{- if .Values.server.schedulerName }} + schedulerName: "{{ .Values.server.schedulerName }}" +{{- end }} +{{- if semverCompare ">=1.13-0" .Capabilities.KubeVersion.GitVersion }} + {{- if or (.Values.server.enableServiceLinks) (eq (.Values.server.enableServiceLinks | toString) "") }} + enableServiceLinks: true + {{- else }} + enableServiceLinks: false + {{- end }} +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.server" . }} +{{- if kindIs "bool" .Values.server.automountServiceAccountToken }} + automountServiceAccountToken: {{ .Values.server.automountServiceAccountToken }} +{{- end }} + {{- if .Values.server.extraInitContainers }} + initContainers: +{{ toYaml .Values.server.extraInitContainers | indent 8 }} + {{- end }} + containers: + {{- if .Values.configmapReload.prometheus.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }}-{{ .Values.configmapReload.prometheus.name }} + {{- if .Values.configmapReload.prometheus.image.digest }} + image: "{{ tpl .Values.configmapReload.prometheus.image.repository . }}@{{ tpl .Values.configmapReload.prometheus.image.digest . }}" + {{- else }} + image: "{{ tpl .Values.configmapReload.prometheus.image.repository . }}:{{ tpl .Values.configmapReload.prometheus.image.tag . }}" + {{- end }} + imagePullPolicy: "{{ .Values.configmapReload.prometheus.image.pullPolicy }}" + {{- with .Values.configmapReload.prometheus.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + args: + - --watched-dir=/etc/config + {{- $default_url := (printf "http://127.0.0.1:%s/-/reload" (include "prometheus.port" .)) }} + {{- with .Values.server.prefixURL }} + {{- $default_url = printf "http://127.0.0.1:%s%s/-/reload" (include "prometheus.port" .) . }} + {{- end }} + {{- if .Values.configmapReload.prometheus.containerPort }} + - --listen-address=0.0.0.0:{{ .Values.configmapReload.prometheus.containerPort }} + {{- end }} + - --reload-url={{ default $default_url .Values.configmapReload.reloadUrl }} + {{- range $key, $value := .Values.configmapReload.prometheus.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraVolumeDirs }} + - --watched-dir={{ . }} + {{- end }} + {{- with .Values.configmapReload.env }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.configmapReload.prometheus.containerPort }} + ports: + - containerPort: {{ .Values.configmapReload.prometheus.containerPort }} + {{- if .Values.configmapReload.prometheus.containerPortName }} + name: {{ .Values.configmapReload.prometheus.containerPortName }} + {{- end }} + {{- end }} + {{- with .Values.configmapReload.prometheus.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.configmapReload.prometheus.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.configmapReload.prometheus.startupProbe.enabled }} + {{- $startupProbe := omit .Values.configmapReload.prometheus.startupProbe "enabled" }} + startupProbe: + {{- toYaml $startupProbe | nindent 12 }} + {{- end }} + {{- with .Values.configmapReload.prometheus.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- with .Values.configmapReload.prometheus.extraVolumeMounts }} + {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }} + {{- if .Values.server.image.digest }} + image: "{{ tpl .Values.server.image.repository . }}@{{ tpl .Values.server.image.digest . }}" + {{- else }} + image: "{{ tpl .Values.server.image.repository . }}:{{ tpl .Values.server.image.tag . | default .Chart.AppVersion}}" + {{- end }} + imagePullPolicy: "{{ .Values.server.image.pullPolicy }}" + {{- with .Values.server.command }} + command: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.server.env }} + env: +{{ toYaml .Values.server.env | indent 12}} + {{- end }} + args: + {{- if .Values.server.defaultFlagsOverride }} + {{ toYaml .Values.server.defaultFlagsOverride | nindent 12}} + {{- else }} + {{- if .Values.server.retention }} + - --storage.tsdb.retention.time={{ .Values.server.retention }} + {{- end }} + {{- if .Values.server.retentionSize }} + - --storage.tsdb.retention.size={{ .Values.server.retentionSize }} + {{- end }} + - --config.file={{ .Values.server.configPath }} + {{- if .Values.server.storagePath }} + - --storage.tsdb.path={{ .Values.server.storagePath }} + {{- else }} + - --storage.tsdb.path={{ .Values.server.persistentVolume.mountPath }} + {{- end }} + - --web.console.libraries=/etc/prometheus/console_libraries + - --web.console.templates=/etc/prometheus/consoles + {{- range .Values.server.extraFlags }} + - --{{ . }} + {{- end }} + {{- range $key, $value := .Values.server.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + {{- if .Values.server.prefixURL }} + - --web.route-prefix={{ .Values.server.prefixURL }} + {{- end }} + {{- if .Values.server.baseURL }} + - --web.external-url={{ .Values.server.baseURL }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ include "prometheus.port" . }} + {{- if .Values.server.portName }} + name: {{ .Values.server.portName }} + {{- end }} + {{- if .Values.server.hostPort }} + hostPort: {{ .Values.server.hostPort }} + {{- end }} + readinessProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/ready + port: {{ default (include "prometheus.port" .) .Values.server.portName }} + scheme: {{ .Values.server.probeScheme }} + {{- with .Values.server.probeHeaders }} + httpHeaders: +{{- toYaml . | nindent 14 }} + {{- end }} + {{- else }} + tcpSocket: + port: {{ default (include "prometheus.port" .) .Values.server.portName }} + {{- end }} + initialDelaySeconds: {{ .Values.server.readinessProbeInitialDelay }} + periodSeconds: {{ .Values.server.readinessProbePeriodSeconds }} + timeoutSeconds: {{ .Values.server.readinessProbeTimeout }} + failureThreshold: {{ .Values.server.readinessProbeFailureThreshold }} + successThreshold: {{ .Values.server.readinessProbeSuccessThreshold }} + livenessProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/healthy + port: {{ default (include "prometheus.port" .) .Values.server.portName }} + scheme: {{ .Values.server.probeScheme }} + {{- with .Values.server.probeHeaders }} + httpHeaders: +{{- toYaml . | nindent 14 }} + {{- end }} + {{- else }} + tcpSocket: + port: {{ default (include "prometheus.port" .) .Values.server.portName }} + {{- end }} + initialDelaySeconds: {{ .Values.server.livenessProbeInitialDelay }} + periodSeconds: {{ .Values.server.livenessProbePeriodSeconds }} + timeoutSeconds: {{ .Values.server.livenessProbeTimeout }} + failureThreshold: {{ .Values.server.livenessProbeFailureThreshold }} + successThreshold: {{ .Values.server.livenessProbeSuccessThreshold }} + {{- if .Values.server.startupProbe.enabled }} + startupProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/healthy + port: {{ default (include "prometheus.port" .) .Values.server.portName }} + scheme: {{ .Values.server.probeScheme }} + {{- if .Values.server.probeHeaders }} + httpHeaders: + {{- range .Values.server.probeHeaders}} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- else }} + tcpSocket: + port: {{ default (include "prometheus.port" .) .Values.server.portName }} + {{- end }} + failureThreshold: {{ .Values.server.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.server.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.server.startupProbe.timeoutSeconds }} + {{- end }} + {{- with .Values.server.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- $storageVolumeName := ternary .Values.server.persistentVolume.statefulSetNameOverride "storage-volume" (and .Values.server.persistentVolume.enabled .Values.server.statefulSet.enabled (not (empty .Values.server.persistentVolume.statefulSetNameOverride))) }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: {{ $storageVolumeName }} + mountPath: {{ .Values.server.persistentVolume.mountPath }} + subPath: "{{ .Values.server.persistentVolume.subPath }}" + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.server.extraVolumeMounts }} + {{ toYaml .Values.server.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- with .Values.server.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.server.sidecarContainers }} + {{- range $name, $spec := .Values.server.sidecarContainers }} + - name: {{ $name }} + {{- if kindIs "string" $spec }} + {{- tpl $spec $ | nindent 10 }} + {{- else }} + {{- toYaml $spec | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.server.hostNetwork }} + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + {{- else }} + dnsPolicy: {{ .Values.server.dnsPolicy }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.server.nodeSelector }} + nodeSelector: +{{ toYaml .Values.server.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.server.hostAliases }} + hostAliases: +{{ toYaml .Values.server.hostAliases | indent 8 }} + {{- end }} + {{- if .Values.server.dnsConfig }} + dnsConfig: +{{ toYaml .Values.server.dnsConfig | indent 8 }} + {{- end }} + {{- with .Values.server.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.server.tolerations }} + tolerations: +{{ toYaml .Values.server.tolerations | indent 8 }} + {{- end }} + {{- if or .Values.server.affinity .Values.server.podAntiAffinity }} + affinity: + {{- end }} + {{- with .Values.server.affinity }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if eq .Values.server.podAntiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.server.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [{{ template "prometheus.name" . }}]} + {{- else if eq .Values.server.podAntiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: {{ .Values.server.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [{{ template "prometheus.name" . }}]} + {{- end }} + {{- with .Values.server.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + volumes: + - name: config-volume + {{- if empty .Values.server.configFromSecret }} + configMap: + name: {{ if .Values.server.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.server.configMapOverrideName }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + {{- else }} + secret: + secretName: {{ .Values.server.configFromSecret }} + {{- end }} + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} +{{- if .Values.server.extraVolumes }} +{{ toYaml .Values.server.extraVolumes | indent 8}} +{{- end }} + {{- if and .Values.server.persistentVolume.enabled (not .Values.server.statefulSet.enabled) }} + - name: {{ $storageVolumeName }} + persistentVolumeClaim: + claimName: {{ if .Values.server.persistentVolume.existingClaim }}{{ .Values.server.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + {{- else if not .Values.server.persistentVolume.enabled }} + - name: {{ $storageVolumeName }} + emptyDir: + {{- if or .Values.server.emptyDir.sizeLimit .Values.server.emptyDir.medium }} + {{- if .Values.server.emptyDir.medium }} + medium: {{ .Values.server.emptyDir.medium }} + {{- end }} + {{- if .Values.server.emptyDir.sizeLimit }} + sizeLimit: {{ .Values.server.emptyDir.sizeLimit }} + {{- end }} + {{- else }} + {} + {{- end -}} + {{- end -}} + {{- if and .Values.server.statefulSet.enabled .Values.server.persistentVolume.enabled }} + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: {{ $storageVolumeName }} + {{- with .Values.server.persistentVolume.annotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.server.persistentVolume.labels }} + labels: + {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- toYaml .Values.server.persistentVolume.accessModes | nindent 10 }} + resources: + requests: + storage: "{{ .Values.server.persistentVolume.size }}" + {{- if .Values.server.persistentVolume.storageClass }} + {{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" + {{- end }} + {{- end }} + {{- end }} diff --git a/utils/assets/charts/prometheus/templates/extra-manifests.yaml b/utils/assets/charts/prometheus/templates/extra-manifests.yaml new file mode 100644 index 0000000..2b21b71 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraManifests }} +--- +{{ tpl . $ }} +{{ end }} diff --git a/utils/assets/charts/prometheus/templates/headless-svc.yaml b/utils/assets/charts/prometheus/templates/headless-svc.yaml new file mode 100644 index 0000000..1fe4328 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/headless-svc.yaml @@ -0,0 +1,32 @@ +{{- if .Values.server.statefulSet.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.server.statefulSet.headless.annotations }} + annotations: +{{ toYaml .Values.server.statefulSet.headless.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- if .Values.server.statefulSet.headless.labels }} +{{ toYaml .Values.server.statefulSet.headless.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }}-headless + namespace: {{ include "prometheus.namespace" . }} +spec: + clusterIP: None + ports: + - name: http + port: {{ .Values.server.statefulSet.headless.servicePort }} + protocol: TCP + targetPort: {{ default (include "prometheus.port" .) .Values.server.portName }} + {{- if .Values.server.statefulSet.headless.gRPC.enabled }} + - name: grpc + port: {{ .Values.server.statefulSet.headless.gRPC.servicePort }} + protocol: TCP + targetPort: 10901 + {{- end }} + + selector: + {{- include "prometheus.server.matchLabels" . | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/templates/httproute.yaml b/utils/assets/charts/prometheus/templates/httproute.yaml new file mode 100644 index 0000000..9ee4383 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/httproute.yaml @@ -0,0 +1,45 @@ +{{- range $name, $route := .Values.server.route }} +{{- if $route.enabled }} +--- +apiVersion: {{ $route.apiVersion | default "gateway.networking.k8s.io/v1" }} +kind: {{ $route.kind | default "HTTPRoute" }} +metadata: + {{- with $route.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + name: {{ include "prometheus.server.fullname" $ }} + namespace: {{ include "prometheus.namespace" $ }} + labels: {{ include "prometheus.server.labels" $ | nindent 4 }} + {{- with $route.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with $route.parentRefs }} + parentRefs: {{ toYaml . | nindent 4 }} + {{- end }} + {{- with $route.hostnames }} + hostnames: {{ tpl (toYaml .) $ | nindent 4 }} + {{- end }} + rules: + {{- with $route.additionalRules }} + {{- tpl (toYaml .) $ | nindent 4 }} + {{- end }} + {{- if $route.httpsRedirect }} + - filters: + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 + {{- else }} + - backendRefs: + - name: {{ include "prometheus.server.fullname" $ }} + port: {{ $.Values.server.service.servicePort }} + {{- with $route.filters }} + filters: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with $route.matches }} + matches: {{ toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/templates/ingress.yaml b/utils/assets/charts/prometheus/templates/ingress.yaml new file mode 100644 index 0000000..f5613d9 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/ingress.yaml @@ -0,0 +1,47 @@ +{{- if .Values.server.ingress.enabled -}} +{{- $releaseName := .Release.Name -}} +{{- $serviceName := include "prometheus.server.fullname" . }} +{{- $servicePort := .Values.server.ingress.servicePort | default .Values.server.service.servicePort -}} +{{- $ingressPath := .Values.server.ingress.path -}} +{{- $ingressPathType := .Values.server.ingress.pathType -}} +{{- $extraPaths := .Values.server.ingress.extraPaths -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: +{{- if .Values.server.ingress.annotations }} + annotations: +{{ toYaml .Values.server.ingress.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- range $key, $value := .Values.server.ingress.extraLabels }} + {{ $key }}: {{ $value }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "prometheus.namespace" . }} +spec: + {{- if .Values.server.ingress.ingressClassName }} + ingressClassName: {{ .Values.server.ingress.ingressClassName }} + {{- end }} + rules: + {{- range .Values.server.ingress.hosts }} + {{- $url := splitList "/" . }} + - host: {{ tpl (first $url) $ }} + http: + paths: +{{ if $extraPaths }} +{{ tpl (toYaml $extraPaths | indent 10) $ }} +{{- end }} + - path: {{ tpl ($ingressPath) $ }} + pathType: {{ $ingressPathType }} + backend: + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- end -}} +{{- if .Values.server.ingress.tls }} + tls: +{{ tpl (toYaml .Values.server.ingress.tls | indent 4) $ }} + {{- end -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/templates/network-policy.yaml b/utils/assets/charts/prometheus/templates/network-policy.yaml new file mode 100644 index 0000000..0accbf5 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/network-policy.yaml @@ -0,0 +1,16 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "prometheus.namespace" . }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + ingress: + - ports: + - port: {{ default (include "prometheus.port" .) .Values.server.portName }} +{{- end }} diff --git a/utils/assets/charts/prometheus/templates/pdb.yaml b/utils/assets/charts/prometheus/templates/pdb.yaml new file mode 100644 index 0000000..db16acd --- /dev/null +++ b/utils/assets/charts/prometheus/templates/pdb.yaml @@ -0,0 +1,26 @@ +{{- if .Values.server.podDisruptionBudget.enabled }} +{{- $pdbSpec := omit .Values.server.podDisruptionBudget "enabled" }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "prometheus.namespace" . }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + {{- if not (or (hasKey $pdbSpec "minAvailable") (hasKey $pdbSpec "maxUnavailable")) }} + maxUnavailable: 1 + {{- end }} + {{- if hasKey $pdbSpec "minAvailable" }} + minAvailable: {{ $pdbSpec.minAvailable }} + {{- end }} + {{- if hasKey $pdbSpec "maxUnavailable" }} + maxUnavailable: {{ $pdbSpec.maxUnavailable }} + {{- end }} + {{- if hasKey $pdbSpec "unhealthyPodEvictionPolicy" }} + unhealthyPodEvictionPolicy: {{ $pdbSpec.unhealthyPodEvictionPolicy }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/templates/pvc.yaml b/utils/assets/charts/prometheus/templates/pvc.yaml new file mode 100644 index 0000000..d2bc403 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/pvc.yaml @@ -0,0 +1,40 @@ +{{- if not .Values.server.statefulSet.enabled -}} +{{- if .Values.server.persistentVolume.enabled -}} +{{- if not .Values.server.persistentVolume.existingClaim -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- if .Values.server.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.server.persistentVolume.annotations | indent 4 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + {{- with .Values.server.persistentVolume.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "prometheus.namespace" . }} +spec: + accessModes: +{{ toYaml .Values.server.persistentVolume.accessModes | indent 4 }} +{{- if .Values.server.persistentVolume.storageClass }} +{{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" +{{- end }} +{{- end }} + resources: + requests: + storage: "{{ .Values.server.persistentVolume.size }}" +{{- if .Values.server.persistentVolume.selector }} + selector: + {{- toYaml .Values.server.persistentVolume.selector | nindent 4 }} +{{- end -}} +{{- if .Values.server.persistentVolume.volumeName }} + volumeName: "{{ .Values.server.persistentVolume.volumeName }}" +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/prometheus/templates/rolebinding.yaml b/utils/assets/charts/prometheus/templates/rolebinding.yaml new file mode 100644 index 0000000..b7719dd --- /dev/null +++ b/utils/assets/charts/prometheus/templates/rolebinding.yaml @@ -0,0 +1,18 @@ +{{- range include "prometheus.namespaces" . | fromJsonArray }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "prometheus.server.labels" $ | nindent 4 }} + name: {{ template "prometheus.server.fullname" $ }} + namespace: {{ . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.server" $ }} + namespace: {{ include "prometheus.namespace" $ }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $.Values.server.useExistingClusterRoleName }} +{{ end -}} diff --git a/utils/assets/charts/prometheus/templates/service.yaml b/utils/assets/charts/prometheus/templates/service.yaml new file mode 100644 index 0000000..37ddb86 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/service.yaml @@ -0,0 +1,66 @@ +{{- if .Values.server.service.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.server.service.annotations }} + annotations: +{{ toYaml .Values.server.service.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- if .Values.server.service.labels }} +{{ toYaml .Values.server.service.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }} + namespace: {{ include "prometheus.namespace" . }} +spec: +{{- if .Values.server.service.clusterIP }} + clusterIP: {{ .Values.server.service.clusterIP }} +{{- end }} +{{- if .Values.server.service.externalIPs }} + externalIPs: +{{ toYaml .Values.server.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.server.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.server.service.loadBalancerIP }} +{{- end }} +{{- if .Values.server.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.server.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} +{{- if .Values.server.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.server.service.externalTrafficPolicy }} +{{- end }} + ports: + - name: http + port: {{ .Values.server.service.servicePort }} + protocol: TCP + targetPort: {{ default (include "prometheus.port" .) .Values.server.portName }} + {{- if ( and (eq .Values.server.service.type "NodePort" ) (not (empty .Values.server.service.nodePort)) ) }} + nodePort: {{ .Values.server.service.nodePort }} + {{- end }} + {{- if .Values.server.service.gRPC.enabled }} + - name: grpc + port: {{ .Values.server.service.gRPC.servicePort }} + protocol: TCP + targetPort: 10901 + {{- if ( and (eq .Values.server.service.gRPC.type "NodePort" ) (not (empty .Values.server.service.gRPC.nodePort)) ) }} + nodePort: {{ .Values.server.service.gRPC.nodePort }} + {{- end }} + {{- end }} +{{- if .Values.server.service.additionalPorts }} +{{ toYaml .Values.server.service.additionalPorts | indent 4 }} +{{- end }} + selector: + {{- if and .Values.server.statefulSet.enabled .Values.server.service.statefulsetReplica.enabled }} + statefulset.kubernetes.io/pod-name: {{ template "prometheus.server.fullname" . }}-{{ .Values.server.service.statefulsetReplica.replica }} + {{- else -}} + {{- include "prometheus.server.matchLabels" . | nindent 4 }} +{{- if .Values.server.service.sessionAffinity }} + sessionAffinity: {{ .Values.server.service.sessionAffinity }} +{{- end }} + {{- end }} + type: "{{ .Values.server.service.type }}" +{{- end -}} diff --git a/utils/assets/charts/prometheus/templates/serviceaccount.yaml b/utils/assets/charts/prometheus/templates/serviceaccount.yaml new file mode 100644 index 0000000..6d5ab0c --- /dev/null +++ b/utils/assets/charts/prometheus/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.serviceAccounts.server.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.server" . }} + namespace: {{ include "prometheus.namespace" . }} + annotations: +{{ toYaml .Values.serviceAccounts.server.annotations | indent 4 }} +{{- if kindIs "bool" .Values.server.automountServiceAccountToken }} +automountServiceAccountToken: {{ .Values.server.automountServiceAccountToken }} +{{- else if kindIs "bool" .Values.serviceAccounts.server.automountServiceAccountToken }} +automountServiceAccountToken: {{ .Values.serviceAccounts.server.automountServiceAccountToken }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/prometheus/templates/vpa.yaml b/utils/assets/charts/prometheus/templates/vpa.yaml new file mode 100644 index 0000000..9bf26e9 --- /dev/null +++ b/utils/assets/charts/prometheus/templates/vpa.yaml @@ -0,0 +1,22 @@ +{{- if .Values.server.verticalAutoscaler.enabled -}} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ template "prometheus.server.fullname" . }}-vpa + namespace: {{ include "prometheus.namespace" . }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +spec: + targetRef: + apiVersion: "apps/v1" +{{- if .Values.server.statefulSet.enabled }} + kind: StatefulSet +{{- else }} + kind: Deployment +{{- end }} + name: {{ template "prometheus.server.fullname" . }} + updatePolicy: + updateMode: {{ .Values.server.verticalAutoscaler.updateMode | default "Off" | quote }} + resourcePolicy: + containerPolicies: {{ .Values.server.verticalAutoscaler.containerPolicies | default list | toYaml | trim | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/prometheus/values.schema.json b/utils/assets/charts/prometheus/values.schema.json new file mode 100644 index 0000000..3e98792 --- /dev/null +++ b/utils/assets/charts/prometheus/values.schema.json @@ -0,0 +1,739 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "alertRelabelConfigs": { + "type": "object" + }, + "alertmanager": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "persistence": { + "type": "object", + "properties": { + "size": { + "type": "string" + } + } + }, + "podSecurityContext": { + "type": "object", + "properties": { + "fsGroup": { + "type": "integer" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + } + } + } + } + }, + "configmapReload": { + "type": "object", + "properties": { + "env": { + "type": "array" + }, + "prometheus": { + "type": "object", + "properties": { + "containerSecurityContext": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "extraArgs": { + "type": "object" + }, + "extraConfigmapMounts": { + "type": "array" + }, + "extraVolumeDirs": { + "type": "array" + }, + "extraVolumeMounts": { + "type": "array" + }, + "image": { + "type": "object", + "properties": { + "digest": { + "type": "string" + }, + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "name": { + "type": "string" + }, + "resources": { + "type": "object" + } + } + }, + "reloadUrl": { + "type": "string" + } + } + }, + "extraManifests": { + "type": "array" + }, + "extraScrapeConfigs": { + "type": "string" + }, + "forceNamespace": { + "type": "string" + }, + "imagePullSecrets": { + "type": "array" + }, + "kube-state-metrics": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "networkPolicy": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "prometheus-node-exporter": { + "type": "object", + "properties": { + "containerSecurityContext": { + "type": "object", + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + } + } + }, + "enabled": { + "type": "boolean" + }, + "rbac": { + "type": "object", + "properties": { + "pspEnabled": { + "type": "boolean" + } + } + } + } + }, + "prometheus-pushgateway": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "serviceAnnotations": { + "type": "object", + "properties": { + "prometheus.io/probe": { + "type": "string" + } + } + } + } + }, + "rbac": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + } + } + }, + "ruleFiles": { + "type": "object" + }, + "server": { + "type": "object", + "properties": { + "affinity": { + "type": "object" + }, + "alertmanagers": { + "type": "array" + }, + "baseURL": { + "type": "string" + }, + "clusterRoleNameOverride": { + "type": "string" + }, + "command": { + "type": "array" + }, + "configMapAnnotations": { + "type": "object" + }, + "configMapOverrideName": { + "type": "string" + }, + "configPath": { + "type": "string" + }, + "containerSecurityContext": { + "type": "object" + }, + "defaultFlagsOverride": { + "type": "array" + }, + "deploymentAnnotations": { + "type": "object" + }, + "dnsConfig": { + "type": "object" + }, + "dnsPolicy": { + "type": "string" + }, + "emptyDir": { + "type": "object", + "properties": { + "sizeLimit": { + "type": "string" + } + } + }, + "enableServiceLinks": { + "type": "boolean" + }, + "env": { + "type": "array" + }, + "exemplars": { + "type": "object" + }, + "extraArgs": { + "type": "object" + }, + "extraConfigmapLabels": { + "type": "object" + }, + "extraConfigmapMounts": { + "type": "array" + }, + "extraFlags": { + "type": "array", + "items": { + "type": "string" + } + }, + "extraHostPathMounts": { + "type": "array" + }, + "extraInitContainers": { + "type": "array" + }, + "extraSecretMounts": { + "type": "array" + }, + "extraVolumeMounts": { + "type": "array" + }, + "extraVolumes": { + "type": "array" + }, + "fullnameOverride": { + "type": "string" + }, + "global": { + "type": "object", + "properties": { + "evaluation_interval": { + "type": "string" + }, + "scrape_interval": { + "type": "string" + }, + "scrape_timeout": { + "type": "string" + } + } + }, + "hostAliases": { + "type": "array" + }, + "hostNetwork": { + "type": "boolean" + }, + "image": { + "type": "object", + "properties": { + "digest": { + "type": "string" + }, + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ingress": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "extraLabels": { + "type": "object" + }, + "extraPaths": { + "type": "array" + }, + "hosts": { + "type": "array" + }, + "path": { + "type": "string" + }, + "pathType": { + "type": "string" + }, + "tls": { + "type": "array" + } + } + }, + "livenessProbeFailureThreshold": { + "type": "integer" + }, + "livenessProbeInitialDelay": { + "type": "integer" + }, + "livenessProbePeriodSeconds": { + "type": "integer" + }, + "livenessProbeSuccessThreshold": { + "type": "integer" + }, + "livenessProbeTimeout": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "nodeSelector": { + "type": "object" + }, + "persistentVolume": { + "type": "object", + "properties": { + "accessModes": { + "type": "array", + "items": { + "type": "string" + } + }, + "annotations": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "existingClaim": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "mountPath": { + "type": "string" + }, + "size": { + "type": "string" + }, + "statefulSetNameOverride": { + "type": "string" + }, + "subPath": { + "type": "string" + } + } + }, + "podAnnotations": { + "type": "object" + }, + "podAntiAffinity": { + "type": "string", + "enum": ["", "soft", "hard"], + "default": "" + }, + "podAntiAffinityTopologyKey": { + "type": "string" + }, + "podDisruptionBudget": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "maxUnavailable": { + "type": [ + "string", + "integer" + ] + } + } + }, + "podLabels": { + "type": "object" + }, + "portName": { + "type": "string" + }, + "prefixURL": { + "type": "string" + }, + "priorityClassName": { + "type": "string" + }, + "runtimeClassName": { + "type": "string" + }, + "probeHeaders": { + "type": "array" + }, + "probeScheme": { + "type": "string" + }, + "readinessProbeFailureThreshold": { + "type": "integer" + }, + "readinessProbeInitialDelay": { + "type": "integer" + }, + "readinessProbePeriodSeconds": { + "type": "integer" + }, + "readinessProbeSuccessThreshold": { + "type": "integer" + }, + "readinessProbeTimeout": { + "type": "integer" + }, + "releaseNamespace": { + "type": "boolean" + }, + "remoteRead": { + "type": "array" + }, + "remoteWrite": { + "type": "array" + }, + "replicaCount": { + "type": "integer" + }, + "resources": { + "type": "object" + }, + "retention": { + "type": "string" + }, + "retentionSize": { + "type": "string" + }, + "revisionHistoryLimit": { + "type": "integer" + }, + "securityContext": { + "type": "object", + "properties": { + "fsGroup": { + "type": "integer" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + } + } + }, + "service": { + "type": "object", + "properties": { + "additionalPorts": { + "type": "array" + }, + "annotations": { + "type": "object" + }, + "clusterIP": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "externalIPs": { + "type": "array" + }, + "gRPC": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "servicePort": { + "type": "integer" + } + } + }, + "labels": { + "type": "object" + }, + "loadBalancerIP": { + "type": "string" + }, + "loadBalancerSourceRanges": { + "type": "array" + }, + "servicePort": { + "type": "integer" + }, + "sessionAffinity": { + "type": "string" + }, + "statefulsetReplica": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "replica": { + "type": "integer" + } + } + }, + "type": { + "type": "string" + } + } + }, + "sidecarContainers": { + "type": "object" + }, + "sidecarTemplateValues": { + "type": "object" + }, + "startupProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "statefulSet": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "headless": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "gRPC": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "servicePort": { + "type": "integer" + } + } + }, + "labels": { + "type": "object" + }, + "servicePort": { + "type": "integer" + } + } + }, + "labels": { + "type": "object" + }, + "podManagementPolicy": { + "type": "string" + }, + "pvcDeleteOnStsDelete": { + "type": "boolean" + }, + "pvcDeleteOnStsScale": { + "type": "boolean" + } + } + }, + "storagePath": { + "type": "string" + }, + "strategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + }, + "tcpSocketProbeEnabled": { + "type": "boolean" + }, + "terminationGracePeriodSeconds": { + "type": "integer" + }, + "tolerations": { + "type": "array" + }, + "topologySpreadConstraints": { + "type": "array" + }, + "tsdb": { + "type": "object" + }, + "verticalAutoscaler": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + } + } + }, + "scrapeConfigFiles": { + "type": "array" + }, + "serverFiles": { + "type": "object", + "properties": { + "alerting_rules.yml": { + "type": "object" + }, + "alerts": { + "type": "object" + }, + "prometheus.yml": { + "type": "object", + "properties": { + "rule_files": { + "type": "array", + "items": { + "type": "string" + } + }, + "scrape_configs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "job_name": { + "type": "string" + }, + "static_configs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "targets": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "recording_rules.yml": { + "type": "object" + }, + "rules": { + "type": "object" + } + } + }, + "serviceAccounts": { + "type": "object", + "properties": { + "server": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "automountServiceAccountToken": { + "type": "boolean" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/utils/assets/charts/prometheus/values.yaml b/utils/assets/charts/prometheus/values.yaml new file mode 100644 index 0000000..92eb43d --- /dev/null +++ b/utils/assets/charts/prometheus/values.yaml @@ -0,0 +1,1380 @@ +# yaml-language-server: $schema=values.schema.json +# Default values for prometheus. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +rbac: + create: true + +imagePullSecrets: [] +# - name: "image-pull-secret" + +## Define serviceAccount names for components. Defaults to component's fully qualified name. +## +serviceAccounts: + server: + create: true + name: "" + annotations: {} + + ## Opt out of automounting Kubernetes API credentials. + ## It will be overriden by server.automountServiceAccountToken value, if set. + # automountServiceAccountToken: false + +## Additional labels to attach to all resources +commonMetaLabels: {} + +## Monitors ConfigMap changes and POSTs to a URL +## Ref: https://github.com/prometheus-operator/prometheus-operator/tree/main/cmd/prometheus-config-reloader +## +configmapReload: + ## URL for configmap-reload to use for reloads + ## + reloadUrl: "" + + ## env sets environment variables to pass to the container. Can be set as name/value pairs, + ## read from secrets or configmaps. + env: [] + # - name: SOMEVAR + # value: somevalue + # - name: PASSWORD + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: password + # optional: false + + prometheus: + ## If false, the configmap-reload container will not be deployed + ## + enabled: true + + ## configmap-reload container name + ## + name: configmap-reload + + ## configmap-reload container image + ## + image: + repository: quay.io/prometheus-operator/prometheus-config-reloader + tag: v0.86.2 + # When digest is set to a non-empty value, images will be pulled by digest (regardless of tag value). + digest: "" + pullPolicy: IfNotPresent + + ## config-reloader's container port and port name for probes and metrics + containerPort: 8080 + containerPortName: metrics + + ## Additional configmap-reload container arguments + ## Set to null for argumentless flags + ## + extraArgs: {} + + ## Additional configmap-reload volume directories + ## + extraVolumeDirs: [] + + ## Additional configmap-reload volume mounts + ## + extraVolumeMounts: [] + + ## Additional configmap-reload mounts + ## + extraConfigmapMounts: [] + # - name: prometheus-alerts + # mountPath: /etc/alerts.d + # subPath: "" + # configMap: prometheus-alerts + # readOnly: true + + ## Security context to be added to configmap-reload container + containerSecurityContext: {} + + ## Settings for Prometheus reloader's readiness, liveness and startup probes + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## + + livenessProbe: + httpGet: + path: /healthz + port: metrics + scheme: HTTP + periodSeconds: 10 + initialDelaySeconds: 2 + + readinessProbe: + httpGet: + path: /healthz + port: metrics + scheme: HTTP + periodSeconds: 10 + + startupProbe: + enabled: false + httpGet: + path: /healthz + port: metrics + scheme: HTTP + periodSeconds: 10 + + ## configmap-reload resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + +server: + ## Prometheus server container name + ## + name: server + + ## Opt out of automounting Kubernetes API credentials. + ## If set it will override serviceAccounts.server.automountServiceAccountToken value for ServiceAccount. + # automountServiceAccountToken: false + + ## Use a ClusterRole (and ClusterRoleBinding) + ## - If set to false - we define a RoleBinding in the defined namespaces ONLY + ## + ## NB: because we need a Role with nonResourceURL's ("/metrics") - you must get someone with Cluster-admin privileges to define this role for you, before running with this setting enabled. + ## This makes prometheus work - for users who do not have ClusterAdmin privs, but wants prometheus to operate on their own namespaces, instead of clusterwide. + ## + ## You MUST also set namespaces to the ones you have access to and want monitored by Prometheus. + ## + # useExistingClusterRoleName: nameofclusterrole + + ## If set it will override prometheus.server.fullname value for ClusterRole and ClusterRoleBinding + ## + clusterRoleNameOverride: "" + + # Enable only the release namespace for monitoring. By default all namespaces are monitored. + # If releaseNamespace and namespaces are both set a merged list will be monitored. + releaseNamespace: false + + ## namespaces to monitor (instead of monitoring all - clusterwide). Needed if you want to run without Cluster-admin privileges. + # namespaces: + # - yournamespace + + # sidecarContainers - add more containers to prometheus server + # Key/Value where Key is the sidecar `- name: ` + # Example: + # sidecarContainers: + # webserver: + # image: nginx + # OR for adding OAuth authentication to Prometheus + # sidecarContainers: + # oauth-proxy: + # image: quay.io/oauth2-proxy/oauth2-proxy:v7.13.0 + # args: + # - --upstream=http://127.0.0.1:9090 + # - --http-address=0.0.0.0:8081 + # - ... + # ports: + # - containerPort: 8081 + # name: oauth-proxy + # protocol: TCP + # resources: {} + sidecarContainers: {} + + # sidecarTemplateValues - context to be used in template for sidecarContainers + # Example: + # sidecarTemplateValues: *your-custom-globals + # sidecarContainers: + # webserver: |- + # {{ include "webserver-container-template" . }} + # Template for `webserver-container-template` might looks like this: + # image: "{{ .Values.server.sidecarTemplateValues.repository }}:{{ .Values.server.sidecarTemplateValues.tag }}" + # ... + # + sidecarTemplateValues: {} + + ## Prometheus server container image + ## + image: + repository: quay.io/prometheus/prometheus + # if not set appVersion field from Chart.yaml is used + tag: "" + # When digest is set to a non-empty value, images will be pulled by digest (regardless of tag value). + digest: "" + pullPolicy: IfNotPresent + + ## Prometheus server command + ## + command: [] + + ## prometheus server priorityClassName + ## + priorityClassName: "" + ## prometheus server runtimeClassName + ## + runtimeClassName: "" + + ## EnableServiceLinks indicates whether information about services should be injected + ## into pod's environment variables, matching the syntax of Docker links. + ## WARNING: the field is unsupported and will be skipped in K8s prior to v1.13.0. + ## + enableServiceLinks: true + + ## The URL prefix at which the container can be accessed. Useful in the case the '-web.external-url' includes a slug + ## so that the various internal URLs are still able to access as they are in the default case. + ## (Optional) + prefixURL: "" + + ## External URL which can access prometheus + ## Maybe same with Ingress host name + baseURL: "" + + ## Additional server container environment variables + ## + ## You specify this manually like you would a raw deployment manifest. + ## This means you can bind in environment variables from secrets. + ## + ## e.g. static environment variable: + ## - name: DEMO_GREETING + ## value: "Hello from the environment" + ## + ## e.g. secret environment variable: + ## - name: USERNAME + ## valueFrom: + ## secretKeyRef: + ## name: mysecret + ## key: username + env: [] + + # List of flags to override default parameters, e.g: + # - --enable-feature=agent + # - --storage.agent.retention.max-time=30m + # - --config.file=/etc/config/prometheus.yml + defaultFlagsOverride: [] + + extraFlags: + - web.enable-lifecycle + ## web.enable-admin-api flag controls access to the administrative HTTP API which includes functionality such as + ## deleting time series. This is disabled by default. + # - web.enable-admin-api + ## + ## storage.tsdb.no-lockfile flag controls BD locking + # - storage.tsdb.no-lockfile + ## + ## storage.tsdb.wal-compression flag enables compression of the write-ahead log (WAL) + # - storage.tsdb.wal-compression + + ## Path to a configuration file on prometheus server container FS + configPath: /etc/config/prometheus.yml + + ### The data directory used by prometheus to set --storage.tsdb.path + ### When empty server.persistentVolume.mountPath is used instead + storagePath: "" + + global: + ## How frequently to scrape targets by default + ## + scrape_interval: 1m + ## How long until a scrape request times out + ## + scrape_timeout: 10s + ## How frequently to evaluate rules + ## + evaluation_interval: 1m + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write + ## + remoteWrite: [] + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_read + ## + remoteRead: [] + + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tsdb + ## + tsdb: {} + # out_of_order_time_window: 0s + + ## https://prometheus.io/docs/guides/opentelemetry + ## + otlp: {} + # promote_resource_attributes: [] + # keep_identifying_resource_attributes: false + # translation_strategy: NoUTF8EscapingWithSuffixes + + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#exemplars + ## Must be enabled via --enable-feature=exemplar-storage + ## + exemplars: {} + # max_exemplars: 100000 + + ## Custom HTTP headers for Liveness/Readiness/Startup Probe + ## + ## Useful for providing HTTP Basic Auth to healthchecks + probeHeaders: [] + # - name: "Authorization" + # value: "Bearer ABCDEabcde12345" + + ## Additional Prometheus server container arguments + ## Set to null for argumentless flags + ## + extraArgs: {} + # web.enable-remote-write-receiver: null + + ## Additional InitContainers to initialize the pod + ## + extraInitContainers: [] + + ## Additional Prometheus server Volume mounts + ## + extraVolumeMounts: [] + + ## Additional Prometheus server Volumes + ## + extraVolumes: [] + + ## Additional Prometheus server hostPath mounts + ## + extraHostPathMounts: [] + # - name: certs-dir + # mountPath: /etc/kubernetes/certs + # subPath: "" + # hostPath: /etc/kubernetes/certs + # readOnly: true + + extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /prometheus + # subPath: "" + # configMap: certs-configmap + # readOnly: true + + ## Additional Prometheus server Secret mounts + # Defines additional mounts with secrets. Secrets must be manually created in the namespace. + extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # subPath: "" + # secretName: prom-secret-files + # readOnly: true + + ## Prometheus server configuration from a secret + ## Do not set both `configMapOverrideName` and `configFromSecret` simultaneously. + ## Use either `configMapOverrideName` or `configFromSecret`. + ## If `configFromSecret` is defined, a ConfigMap resource will NOT be generated. + configFromSecret: "" + + ## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.server.configMapOverrideName}} + ## Defining configMapOverrideName will cause templates/server-configmap.yaml + ## to NOT generate a ConfigMap resource + ## + configMapOverrideName: "" + + ## Extra labels for Prometheus server ConfigMap (ConfigMap that holds serverFiles) + extraConfigmapLabels: {} + + ## Override the prometheus.server.fullname for all objects related to the Prometheus server + fullnameOverride: "" + + ingress: + ## If true, Prometheus server Ingress will be created + ## + enabled: false + + ingressClassName: "" + + ## Prometheus server Ingress annotations + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## Prometheus server Ingress additional labels + ## + extraLabels: {} + + ## Redirect ingress to an additional defined port on the service + # servicePort: 8081 + + ## Prometheus server Ingress hostnames with optional path (passed through tpl) + ## Must be provided if Ingress is enabled + ## + hosts: [] + # - prometheus.domain.com + # - domain.com/prometheus + + path: / + + # pathType is only for k8s >= 1.18 + pathType: Prefix + + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. (passed through tpl) + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + + ## Prometheus server Ingress TLS configuration (hosts passed through tpl) + ## Secrets must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-server-tls + # hosts: + # - prometheus.domain.com + + ## route (map) allows configuration of HTTPRoute resources + ## Requires Gateway API resources and suitable controller installed within the cluster + ## Ref. https://gateway-api.sigs.k8s.io/guides/http-routing/ + route: + main: + ## Enable this route + enabled: false + + ## ApiVersion set by default to "gateway.networking.k8s.io/v1" + apiVersion: "" + ## kind set by default to HTTPRoute + kind: "" + + ## Annotations to attach to the HTTPRoute resource + annotations: {} + ## Labels to attach to the HTTPRoute resource + labels: {} + + ## ParentRefs refers to resources this HTTPRoute is to be attached to (Gateways) + parentRefs: [] + # - name: contour + # sectionName: http + + ## Hostnames (templated) defines a set of hostnames that should match against the HTTP Host + ## header to select a HTTPRoute used to process the request + hostnames: [] + # - my.example.com + + ## additionalRules (templated) allows adding custom rules to the route + additionalRules: [] + + ## Filters define the filters that are applied to requests that match + ## this rule + filters: [] + + ## Matches define conditions used for matching the rule against incoming + ## HTTP requests + matches: + - path: + type: PathPrefix + value: / + + ## httpsRedirect adds a filter for redirecting to https (HTTP 301 Moved Permanently). + ## To redirect HTTP traffic to HTTPS, you need to have a Gateway with both HTTP and HTTPS listeners. + ## Matches and filters do not take effect if enabled. + ## Ref. https://gateway-api.sigs.k8s.io/guides/http-redirect-rewrite/ + httpsRedirect: false + + ## Server Deployment Strategy type + strategy: + type: Recreate + + ## hostAliases allows adding entries to /etc/hosts inside the containers + hostAliases: [] + # - ip: "127.0.0.1" + # hostnames: + # - "example.com" + + ## Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for Prometheus server pod assignment + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + ## + nodeSelector: {} + + ## Pod affinity + ## + affinity: {} + + ## Pod anti-affinity can prevent the scheduler from placing Prometheus server replicas on the same node. + ## The value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. + ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. + ## The default value "" will disable pod anti-affinity so that no anti-affinity rules will be configured (unless set in `server.affinity`). + ## + podAntiAffinity: "" + + ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. + ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone + ## + podAntiAffinityTopologyKey: kubernetes.io/hostname + + ## Pod topology spread constraints + ## ref. https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ + topologySpreadConstraints: [] + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + # maxUnavailable: 1 + # minAvailable: 1 + ## unhealthyPodEvictionPolicy is available since 1.27.0 (beta) + ## https://kubernetes.io/docs/tasks/run-application/configure-pdb/#unhealthy-pod-eviction-policy + # unhealthyPodEvictionPolicy: IfHealthyBudget + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + + persistentVolume: + ## If true, Prometheus server will create/use a Persistent Volume Claim + ## If false, use emptyDir + ## + enabled: true + + ## If set it will override the name of the created persistent volume claim + ## generated by the stateful set. + ## + statefulSetNameOverride: "" + + ## Prometheus server data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## Prometheus server data Persistent Volume labels + ## + labels: {} + + ## Prometheus server data Persistent Volume annotations + ## + annotations: {} + + ## Prometheus server data Persistent Volume existing claim name + ## Requires server.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## Prometheus server data Persistent Volume mount root path + ## + mountPath: /data + + ## Prometheus server data Persistent Volume size + ## + size: 8Gi + + ## Prometheus server data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## Subdirectory of Prometheus server data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + + ## Persistent Volume Claim Selector + ## Useful if Persistent Volumes have been provisioned in advance + ## Ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector + ## + # selector: + # matchLabels: + # release: "stable" + # matchExpressions: + # - { key: environment, operator: In, values: [ dev ] } + + ## Persistent Volume Name + ## Useful if Persistent Volumes have been provisioned in advance and you want to use a specific one + ## + # volumeName: "" + + emptyDir: + ## Prometheus server emptyDir volume + ## Configure size limit and medium + ## + medium: "" + sizeLimit: "" + + ## Annotations to be added to Prometheus server pods + ## + podAnnotations: {} + # iam.amazonaws.com/role: prometheus + + ## Labels to be added to Prometheus server pods + ## + podLabels: {} + + ## Prometheus AlertManager configuration + ## + alertmanagers: [] + + ## Use a StatefulSet if replicaCount needs to be greater than 1 (see below) + ## + replicaCount: 1 + + ## Number of old history to retain to allow rollback + ## Default Kubernetes value is set to 10 + ## + revisionHistoryLimit: 10 + + ## Annotations to be added to ConfigMap + ## + configMapAnnotations: {} + + ## Annotations to be added to deployment + ## + deploymentAnnotations: {} + + statefulSet: + ## If true, use a statefulset instead of a deployment for pod management. + ## This allows to scale replicas to more than 1 pod + ## + enabled: false + + annotations: {} + labels: {} + podManagementPolicy: OrderedReady + + ## Alertmanager headless service to use for the statefulset + ## + headless: + annotations: {} + labels: {} + servicePort: 80 + ## Enable gRPC port on service to allow auto discovery with thanos-querier + gRPC: + enabled: false + servicePort: 10901 + # nodePort: 10901 + + ## Statefulset's persistent volume claim retention policy + ## pvcDeleteOnStsDelete and pvcDeleteOnStsScale determine whether + ## statefulset's PVCs are deleted (true) or retained (false) on scaling down + ## and deleting statefulset, respectively. Requires 1.27.0+. + ## Ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention + ## + pvcDeleteOnStsDelete: false + pvcDeleteOnStsScale: false + + daemonSet: + ## If true, use a daemonset instead of a deployment for pod management. + ## This allows to run prometheus agent on every node in the cluster. + ## + enabled: false + annotations: {} + labels: {} + + ## Prometheus server readiness and liveness probe initial delay and timeout + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## + tcpSocketProbeEnabled: false + probeScheme: HTTP + readinessProbeInitialDelay: 30 + readinessProbePeriodSeconds: 5 + readinessProbeTimeout: 4 + readinessProbeFailureThreshold: 3 + readinessProbeSuccessThreshold: 1 + livenessProbeInitialDelay: 30 + livenessProbePeriodSeconds: 15 + livenessProbeTimeout: 10 + livenessProbeFailureThreshold: 3 + livenessProbeSuccessThreshold: 1 + startupProbe: + enabled: false + periodSeconds: 5 + failureThreshold: 30 + timeoutSeconds: 10 + + ## Prometheus server resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 500m + # memory: 512Mi + # requests: + # cpu: 500m + # memory: 512Mi + + # Required for use in managed kubernetes clusters (such as AWS EKS) with custom CNI (such as calico), + # because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working + ## + hostNetwork: false + + # When hostNetwork is enabled, this will set to ClusterFirstWithHostNet automatically + dnsPolicy: ClusterFirst + + # Use hostPort + # hostPort: 9090 + + # Use portName + portName: "" + + ## Vertical Pod Autoscaler config + ## Ref: https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler + verticalAutoscaler: + ## If true a VPA object will be created for the controller (either StatefulSet or Deployemnt, based on above configs) + enabled: false + # updateMode: "Auto" + # containerPolicies: + # - containerName: 'prometheus-server' + + # Custom DNS configuration to be added to prometheus server pods + dnsConfig: {} + # nameservers: + # - 1.2.3.4 + # searches: + # - ns1.svc.cluster-domain.example + # - my.dns.search.suffix + # options: + # - name: ndots + # value: "2" + # - name: edns0 + + ## Security context to be added to server pods + ## + securityContext: + runAsUser: 65534 + runAsNonRoot: true + runAsGroup: 65534 + fsGroup: 65534 + + ## Security context to be added to server container + ## + containerSecurityContext: {} + + service: + ## If false, no Service will be created for the Prometheus server + ## + enabled: true + + annotations: {} + labels: {} + clusterIP: "" + + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + ## + externalIPs: [] + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 80 + sessionAffinity: None + type: ClusterIP + ## externalTrafficPolicy is applicable to service with externally-facing addresses (NodePorts, ExternalIPs, and LoadBalancer IPs) + externalTrafficPolicy: "" + + ## Enable gRPC port on service to allow auto discovery with thanos-querier + gRPC: + enabled: false + servicePort: 10901 + # nodePort: 10901 + + ## If using a statefulSet (statefulSet.enabled=true), configure the + ## service to connect to a specific replica to have a consistent view + ## of the data. + statefulsetReplica: + enabled: false + replica: 0 + + ## Additional port to define in the Service + additionalPorts: [] + # additionalPorts: + # - name: authenticated + # port: 8081 + # targetPort: 8081 + + ## Prometheus server pod termination grace period + ## + terminationGracePeriodSeconds: 300 + + ## Prometheus data retention period (default if not specified is 15 days) + ## + retention: "15d" + + ## Prometheus' data retention size. Supported units: B, KB, MB, GB, TB, PB, EB. + ## + retentionSize: "" + +## Prometheus server ConfigMap entries for rule files (allow prometheus labels interpolation) +ruleFiles: {} + +## Prometheus server ConfigMap entries for scrape_config_files +## (allows scrape configs defined in additional files) +## +scrapeConfigFiles: [] + +## Prometheus server ConfigMap entries +## +serverFiles: + ## Alerts configuration + ## Ref: https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ + alerting_rules.yml: {} + # groups: + # - name: Instances + # rules: + # - alert: InstanceDown + # expr: up == 0 + # for: 5m + # labels: + # severity: page + # annotations: + # description: '{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.' + # summary: 'Instance {{ $labels.instance }} down' + ## DEPRECATED DEFAULT VALUE, unless explicitly naming your files, please use alerting_rules.yml + alerts: {} + + ## Records configuration + ## Ref: https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/ + recording_rules.yml: {} + ## DEPRECATED DEFAULT VALUE, unless explicitly naming your files, please use recording_rules.yml + rules: {} + + prometheus.yml: + rule_files: + - /etc/config/recording_rules.yml + - /etc/config/alerting_rules.yml + ## Below two files are DEPRECATED will be removed from this default values file + - /etc/config/rules + - /etc/config/alerts + + scrape_configs: + - job_name: prometheus + static_configs: + - targets: + - localhost:9090 + + # A scrape configuration for running Prometheus on a Kubernetes cluster. + # This uses separate scrape configs for cluster components (i.e. API server, node) + # and services to allow each to use different authentication configs. + # + # Kubernetes labels will be added as Prometheus labels on metrics via the + # `labelmap` relabeling action. + + # Scrape config for API servers. + # + # Kubernetes exposes API servers as endpoints to the default/kubernetes + # service so this uses `endpoints` role and uses relabelling to only keep + # the endpoints associated with the default/kubernetes service using the + # default named port `https`. This works for single API server deployments as + # well as HA API server deployments. + - job_name: 'kubernetes-apiservers' + + kubernetes_sd_configs: + - role: endpoints + + # Default to scraping over https. If required, just disable this or change to + # `http`. + scheme: https + + # This TLS & bearer token file config is used to connect to the actual scrape + # endpoints for cluster components. This is separate to discovery auth + # configuration because discovery & scraping are two separate concerns in + # Prometheus. The discovery auth config is automatic if Prometheus runs inside + # the cluster. Otherwise, more config options have to be provided within the + # . + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # If your node certificates are self-signed or use a different CA to the + # master CA, then disable certificate verification below. Note that + # certificate verification is an integral part of a secure infrastructure + # so this should only be disabled in a controlled environment. You can + # disable certificate verification by uncommenting the line below. + # + # insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + # Keep only the default/kubernetes service endpoints for the https port. This + # will add targets for each API server which Kubernetes adds an endpoint to + # the default/kubernetes service. + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: default;kubernetes;https + + - job_name: 'kubernetes-nodes' + + # Default to scraping over https. If required, just disable this or change to + # `http`. + scheme: https + + # This TLS & bearer token file config is used to connect to the actual scrape + # endpoints for cluster components. This is separate to discovery auth + # configuration because discovery & scraping are two separate concerns in + # Prometheus. The discovery auth config is automatic if Prometheus runs inside + # the cluster. Otherwise, more config options have to be provided within the + # . + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # If your node certificates are self-signed or use a different CA to the + # master CA, then disable certificate verification below. Note that + # certificate verification is an integral part of a secure infrastructure + # so this should only be disabled in a controlled environment. You can + # disable certificate verification by uncommenting the line below. + # + # insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + kubernetes_sd_configs: + - role: node + + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/$1/proxy/metrics + + + - job_name: 'kubernetes-nodes-cadvisor' + + # Default to scraping over https. If required, just disable this or change to + # `http`. + scheme: https + + # This TLS & bearer token file config is used to connect to the actual scrape + # endpoints for cluster components. This is separate to discovery auth + # configuration because discovery & scraping are two separate concerns in + # Prometheus. The discovery auth config is automatic if Prometheus runs inside + # the cluster. Otherwise, more config options have to be provided within the + # . + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # If your node certificates are self-signed or use a different CA to the + # master CA, then disable certificate verification below. Note that + # certificate verification is an integral part of a secure infrastructure + # so this should only be disabled in a controlled environment. You can + # disable certificate verification by uncommenting the line below. + # + # insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + kubernetes_sd_configs: + - role: node + + # This configuration will work only on kubelet 1.7.3+ + # As the scrape endpoints for cAdvisor have changed + # if you are using older version you need to change the replacement to + # replacement: /api/v1/nodes/$1:4194/proxy/metrics + # more info here https://github.com/coreos/prometheus-operator/issues/633 + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor + + # Metric relabel configs to apply to samples before ingestion. + # [Metric Relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) + # metric_relabel_configs: + # - action: labeldrop + # regex: (kubernetes_io_hostname|failure_domain_beta_kubernetes_io_region|beta_kubernetes_io_os|beta_kubernetes_io_arch|beta_kubernetes_io_instance_type|failure_domain_beta_kubernetes_io_zone) + + # Scrape config for service endpoints. + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/scrape`: Only scrape services that have a value of + # `true`, except if `prometheus.io/scrape-slow` is set to `true` as well. + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: If the metrics are exposed on a different port to the + # service then set this appropriately. + # * `prometheus.io/param_`: If the metrics endpoint uses parameters + # then you can set any parameter + - job_name: 'kubernetes-service-endpoints' + honor_labels: true + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow] + action: drop + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: (.+?)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: service + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + + # Scrape config for slow service endpoints; same as above, but with a larger + # timeout and a larger interval + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/scrape-slow`: Only scrape services that have a value of `true` + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: If the metrics are exposed on a different port to the + # service then set this appropriately. + # * `prometheus.io/param_`: If the metrics endpoint uses parameters + # then you can set any parameter + - job_name: 'kubernetes-service-endpoints-slow' + honor_labels: true + + scrape_interval: 5m + scrape_timeout: 30s + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: (.+?)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: service + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + + - job_name: 'prometheus-pushgateway' + honor_labels: true + + kubernetes_sd_configs: + - role: service + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] + action: keep + regex: pushgateway + + # Example scrape config for probing services via the Blackbox Exporter. + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/probe`: Only probe services that have a value of `true` + - job_name: 'kubernetes-services' + honor_labels: true + + metrics_path: /probe + params: + module: [http_2xx] + + kubernetes_sd_configs: + - role: service + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] + action: keep + regex: true + - source_labels: [__address__] + target_label: __param_target + - target_label: __address__ + replacement: blackbox + - source_labels: [__param_target] + target_label: instance + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + target_label: namespace + - source_labels: [__meta_kubernetes_service_name] + target_label: service + + # Example scrape config for pods + # + # The relabeling allows the actual pod scrape endpoint to be configured via the + # following annotations: + # + # * `prometheus.io/scrape`: Only scrape pods that have a value of `true`, + # except if `prometheus.io/scrape-slow` is set to `true` as well. + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: Scrape the pod on the indicated port instead of the default of `9102`. + - job_name: 'kubernetes-pods' + honor_labels: true + + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape_slow] + action: drop + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme] + action: replace + regex: (https?) + target_label: __scheme__ + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port, __meta_kubernetes_pod_ip] + action: replace + regex: (\d+);(([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}) + replacement: '[$2]:$1' + target_label: __address__ + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port, __meta_kubernetes_pod_ip] + action: replace + regex: (\d+);((([0-9]+?)(\.|$)){4}) + replacement: $2:$1 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod + - source_labels: [__meta_kubernetes_pod_phase] + regex: Pending|Succeeded|Failed|Completed + action: drop + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + + # Example Scrape config for pods which should be scraped slower. An useful example + # would be stackriver-exporter which queries an API on every scrape of the pod + # + # The relabeling allows the actual pod scrape endpoint to be configured via the + # following annotations: + # + # * `prometheus.io/scrape-slow`: Only scrape pods that have a value of `true` + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: Scrape the pod on the indicated port instead of the default of `9102`. + - job_name: 'kubernetes-pods-slow' + honor_labels: true + + scrape_interval: 5m + scrape_timeout: 30s + + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape_slow] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme] + action: replace + regex: (https?) + target_label: __scheme__ + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port, __meta_kubernetes_pod_ip] + action: replace + regex: (\d+);(([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}) + replacement: '[$2]:$1' + target_label: __address__ + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port, __meta_kubernetes_pod_ip] + action: replace + regex: (\d+);((([0-9]+?)(\.|$)){4}) + replacement: $2:$1 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod + - source_labels: [__meta_kubernetes_pod_phase] + regex: Pending|Succeeded|Failed|Completed + action: drop + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + +# adds additional scrape configs to prometheus.yml +# must be a string so you have to add a | after extraScrapeConfigs: +# example adds prometheus-blackbox-exporter scrape config +extraScrapeConfigs: "" + # - job_name: 'prometheus-blackbox-exporter' + # metrics_path: /probe + # params: + # module: [http_2xx] + # static_configs: + # - targets: + # - https://example.com + # relabel_configs: + # - source_labels: [__address__] + # target_label: __param_target + # - source_labels: [__param_target] + # target_label: instance + # - target_label: __address__ + # replacement: prometheus-blackbox-exporter:9115 + +# Adds option to add alert_relabel_configs to avoid duplicate alerts in alertmanager +# useful in H/A prometheus with different external labels but the same alerts +alertRelabelConfigs: {} + # alert_relabel_configs: + # - source_labels: [dc] + # regex: (.+)\d+ + # target_label: dc + +networkPolicy: + ## Enable creation of NetworkPolicy resources. + ## + enabled: false + +# Force namespace of namespaced resources +forceNamespace: "" + +# Extra manifests to deploy as an array +extraManifests: [] + # - | + # apiVersion: v1 + # kind: ConfigMap + # metadata: + # labels: + # name: prometheus-extra + # data: + # extra-data: "value" + +# Configuration of subcharts defined in Chart.yaml + +## alertmanager sub-chart configurable values +## Please see https://github.com/prometheus-community/helm-charts/tree/main/charts/alertmanager +## +alertmanager: + ## If false, alertmanager will not be installed + ## + enabled: true + + persistence: + ## If true, storage will create or use Persistence Volume + ## If false, storage will use emptyDir + ## + enabled: true + + ## Custom annotations for the PVC created by the alertmanager StatefulSet. + ## Useful for configuring storage provider options such as disk type, KMS encryption keys, or custom volume name prefixes. + annotations: {} + + ## Custom labels for the PVC created by the alertmanager StatefulSet. + ## Useful for selecting, grouping, and organizing so that they can be queried or targeted in deployments, policies, etc. + labels: {} + + ## Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. + ## + # storageClass: "-" + accessModes: + - ReadWriteOnce + size: 2Gi + + ## Configure emptyDir volume + ## + emptyDir: {} + + podSecurityContext: + runAsUser: 65534 + runAsNonRoot: true + runAsGroup: 65534 + fsGroup: 65534 + +## kube-state-metrics sub-chart configurable values +## Please see https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics +## +kube-state-metrics: + ## If false, kube-state-metrics sub-chart will not be installed + ## + enabled: true + +## prometheus-node-exporter sub-chart configurable values +## Please see https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-node-exporter +## +prometheus-node-exporter: + ## If false, node-exporter will not be installed + ## + enabled: true + + rbac: + pspEnabled: false + + containerSecurityContext: + allowPrivilegeEscalation: false + +## prometheus-pushgateway sub-chart configurable values +## Please see https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-pushgateway +## +prometheus-pushgateway: + ## If false, pushgateway will not be installed + ## + enabled: true + + # Optional service annotations + serviceAnnotations: + prometheus.io/probe: pushgateway diff --git a/utils/assets/charts/traefik/.helmignore b/utils/assets/charts/traefik/.helmignore new file mode 100644 index 0000000..9c42ddd --- /dev/null +++ b/utils/assets/charts/traefik/.helmignore @@ -0,0 +1,2 @@ +tests/ +crds/kustomization.yaml diff --git a/utils/assets/charts/traefik/Changelog.md b/utils/assets/charts/traefik/Changelog.md new file mode 100644 index 0000000..be5ee51 --- /dev/null +++ b/utils/assets/charts/traefik/Changelog.md @@ -0,0 +1,10505 @@ +# Change Log + +## 33.0.0 ![AppVersion: v3.2.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.2.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-10-30 + +* fix: 🐛 http3 with internal service +* fix: use correct children indentation for logs.access.filters +* fix(schema): :bug: targetPort can also be a string +* fix(certificateResolvers)!: :boom: :bug: use same syntax in Chart and in Traefik +* fix(Traefik)!: :boom: set 8080 as default port for `traefik` entrypoint +* fix(Traefik Hub): RBAC for distributedAcme +* fix(Kubernetes Ingress)!: :boom: :sparkles: enable publishedService by default +* fix(Gateway API): :bug: add missing required RBAC for v3.2 with experimental Channel +* fix(Env Variables)!: allow extending env without overwrite +* feat(deps): update traefik docker tag to v3.2.0 +* feat(deps): update traefik docker tag to v3.1.6 +* feat(Traefik): ✨ support Gateway API statusAddress +* feat(Traefik Proxy): CRDs for v3.2+ +* feat(Gateway API): :sparkles: standard install CRD v1.2.0 +* feat(Gateway API): :sparkles: add infrastructure in the values +* chore: allow TRACE log level +* chore(release): 🚀 publish v33.0.0 +* Update topology spread constraints comments + +**Upgrade Notes** + +There are multiple breaking changes in this release: + +1. The default port of `traefik` entrypoint has changed from `9000` to `8080`, just like the Traefik Proxy default port + * You _may_ have to update probes accordingly (or set this port back to 9000) +2. `publishedService` is enabled by default on Ingress provider + * You _can_ disable it, if needed +3. The `POD_NAME` and `POD_NAMESPACE` environment variables are now set by default, without values. + * It is no longer necessary to add them in values and so, it can be removed from user values. +4. In _values_, **certResolvers** specific syntax has been reworked to align with Traefik Proxy syntax. + * PR [#1214](https://github.com/traefik/traefik-helm-chart/pull/1214) contains a complete before / after example on how to update _values_ +5. Traefik Proxy 3.2 supports Gateway API v1.2 + * The CRDs of this version comes with Gateway API CRD v1.2 of standard channel. + * The CRDs needs to be updated, as documented in the README. + * It is recommended to check that other software using Gateway API on your cluster are compatible + +:information_source: A separate helm chart, just for CRDs, is being considered for a future release. See PR [#1123](https://github.com/traefik/traefik-helm-chart/pull/1223) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 73371f3..be89b00 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -95,7 +95,7 @@ deployment: + # postStart: + # httpGet: + # path: /ping +- # port: 9000 ++ # port: 8080 + # host: localhost + # scheme: HTTP + # -- Set a runtimeClassName on pod +@@ -138,6 +138,8 @@ gateway: + namespace: "" + # -- Additional gateway annotations (e.g. for cert-manager.io/issuer) + annotations: {} ++ # -- [Infrastructure](https://kubernetes.io/blog/2023/11/28/gateway-api-ga/#gateway-infrastructure-labels) ++ infrastructure: {} + # -- Define listeners + listeners: + web: +@@ -283,10 +285,11 @@ providers: # @schema additionalProperties: false + namespaces: [] + # IP used for Kubernetes Ingress endpoints + publishedService: +- enabled: false +- # Published Kubernetes Service to copy status from. Format: namespace/servicename +- # By default this Traefik service +- # pathOverride: "" ++ # -- Enable [publishedService](https://doc.traefik.io/traefik/providers/kubernetes-ingress/#publishedservice) ++ enabled: true ++ # -- Override path of Kubernetes Service used to copy status from. Format: namespace/servicename. ++ # Default to Service deployed with this Chart. ++ pathOverride: "" + # -- Defines whether to use Native Kubernetes load-balancing mode by default. + nativeLBByDefault: false + +@@ -300,6 +303,15 @@ providers: # @schema additionalProperties: false + namespaces: [] + # -- A label selector can be defined to filter on specific GatewayClass objects only. + labelselector: "" ++ statusAddress: ++ # -- This IP will get copied to the Gateway status.addresses, and currently only supports one IP value (IPv4 or IPv6). ++ ip: "" ++ # -- This Hostname will get copied to the Gateway status.addresses. ++ hostname: "" ++ # -- The Kubernetes service to copy status addresses from. When using third parties tools like External-DNS, this option can be used to copy the service loadbalancer.status (containing the service's endpoints IPs) to the gateways. Default to Service of this Chart. ++ service: ++ name: "{{ (include \"traefik.fullname\" .) }}" ++ namespace: "{{ .Release.Namespace }}" + + file: + # -- Create a file provider +@@ -335,8 +347,8 @@ logs: + # -- Set [logs format](https://doc.traefik.io/traefik/observability/logs/#format) + format: # @schema enum:["common", "json", null]; type:[string, null]; default: "common" + # By default, the level is set to INFO. +- # -- Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. +- level: "INFO" # @schema enum:[INFO,WARN,ERROR,FATAL,PANIC,DEBUG]; default: "INFO" ++ # -- Alternative logging levels are TRACE, DEBUG, INFO, WARN, ERROR, FATAL, and PANIC. ++ level: "INFO" # @schema enum:[TRACE,DEBUG,INFO,WARN,ERROR,FATAL,PANIC]; default: "INFO" + # -- To write the logs into a log file, use the filePath option. + filePath: "" + # -- When set to true and format is common, it disables the colorized output. +@@ -350,10 +362,13 @@ logs: + # -- Set [bufferingSize](https://doc.traefik.io/traefik/observability/access-logs/#bufferingsize) + bufferingSize: # @schema type:[integer, null] + # -- Set [filtering](https://docs.traefik.io/observability/access-logs/#filtering) +- filters: {} +- statuscodes: "" +- retryattempts: false +- minduration: "" ++ filters: # @schema additionalProperties: false ++ # -- Set statusCodes, to limit the access logs to requests with a status codes in the specified range ++ statuscodes: "" ++ # -- Set retryAttempts, to keep the access logs when at least one retry has happened ++ retryattempts: false ++ # -- Set minDuration, to keep access logs when requests take longer than the specified duration ++ minduration: "" + # -- Enables accessLogs for internal resources. Default: false. + addInternals: false + fields: +@@ -566,24 +581,16 @@ additionalArguments: [] + # - "--providers.kubernetesingress.ingressclass=traefik-internal" + # - "--log.level=DEBUG" + +-# -- Environment variables to be passed to Traefik's binary ++# -- Additional Environment variables to be passed to Traefik's binary + # @default -- See _values.yaml_ +-env: +-- name: POD_NAME +- valueFrom: +- fieldRef: +- fieldPath: metadata.name +-- name: POD_NAMESPACE +- valueFrom: +- fieldRef: +- fieldPath: metadata.namespace ++env: [] + + # -- Environment variables to be passed to Traefik's binary from configMaps or secrets + envFrom: [] + + ports: + traefik: +- port: 9000 ++ port: 8080 + # -- Use hostPort if set. + hostPort: # @schema type:[integer, null]; minimum:0 + # -- Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which +@@ -601,7 +608,7 @@ ports: + expose: + default: false + # -- The exposed port for this service +- exposedPort: 9000 ++ exposedPort: 8080 + # -- The port protocol (TCP/UDP) + protocol: TCP + web: +@@ -614,7 +621,7 @@ ports: + default: true + exposedPort: 80 + ## -- Different target traefik port on the cluster, useful for IP type LB +- targetPort: # @schema type:[integer, null]; minimum:0 ++ targetPort: # @schema type:[string, integer, null]; minimum:0 + # The port protocol (TCP/UDP) + protocol: TCP + # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) +@@ -653,7 +660,7 @@ ports: + default: true + exposedPort: 443 + ## -- Different target traefik port on the cluster, useful for IP type LB +- targetPort: # @schema type:[integer, null]; minimum:0 ++ targetPort: # @schema type:[string, integer, null]; minimum:0 + ## -- The port protocol (TCP/UDP) + protocol: TCP + # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) +@@ -780,8 +787,8 @@ autoscaling: + + persistence: + # -- Enable persistence using Persistent Volume Claims +- # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +- # It can be used to store TLS certificates, see `storage` in certResolvers ++ # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/. ++ # It can be used to store TLS certificates along with `certificatesResolvers..acme.storage` option + enabled: false + name: data + existingClaim: "" +@@ -797,7 +804,7 @@ persistence: + # -- Certificates resolvers configuration. + # Ref: https://doc.traefik.io/traefik/https/acme/#certificate-resolvers + # See EXAMPLES.md for more details. +-certResolvers: {} ++certificatesResolvers: {} + + # -- If hostNetwork is true, runs traefik in the host network namespace + # To prevent unschedulabel pods due to port collisions, if hostNetwork=true +@@ -860,7 +867,7 @@ topologySpreadConstraints: [] + # on nodes where no other traefik pods are scheduled. + # - labelSelector: + # matchLabels: +-# app: '{{ template "traefik.name" . }}' ++# app.kubernetes.io/name: '{{ template "traefik.name" . }}' + # maxSkew: 1 + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: DoNotSchedule +``` + +## 32.1.0 ![AppVersion: v3.1.5](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.5&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-10-04 + +* fix: :bug: set disableIngressClassLookup until 3.1.4 +* feat(deps): update traefik docker tag to v3.1.5 +* feat(Traefik Proxy): update rbac following v3.2 migration guide +* chore(release): 🚀 publish v32.1.0 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index f36a9dd..73371f3 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -809,9 +809,9 @@ hostNetwork: false + rbac: # @schema additionalProperties: false + enabled: true + # When set to true: +- # 1. Use `Role` and `RoleBinding` instead of `ClusterRole` and `ClusterRoleBinding`. +- # 2. Set `disableIngressClassLookup` on Kubernetes Ingress providers with Traefik Proxy v3 until v3.1.1 +- # 3. Set `disableClusterScopeResources` on Kubernetes Ingress and CRD providers with Traefik Proxy v3.1.2+ ++ # 1. It switches respectively the use of `ClusterRole` and `ClusterRoleBinding` to `Role` and `RoleBinding`. ++ # 2. It adds `disableIngressClassLookup` on Kubernetes Ingress with Traefik Proxy v3 until v3.1.4 ++ # 3. It adds `disableClusterScopeResources` on Ingress and CRD (Kubernetes) providers with Traefik Proxy v3.1.2+ + # **NOTE**: `IngressClass`, `NodePortLB` and **Gateway** provider cannot be used with namespaced RBAC. + # See [upstream documentation](https://doc.traefik.io/traefik/providers/kubernetes-ingress/#disableclusterscoperesources) for more details. + namespaced: false + +## 32.0.0 ![AppVersion: v3.1.4](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.4&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-09-27 + +* chore(release): :rocket: publish 32.0.0 +* fix: replace `CLF` with `common` in `values.yaml` +* feat(Traefik Hub): add APIPlans and APIBundles CRDs + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 51dec67..f36a9dd 100644 +index d5173dc..f36a9dd 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -345,7 +345,7 @@ logs: + # -- To enable access logs + enabled: false + # -- Set [access log format](https://doc.traefik.io/traefik/observability/access-logs/#format) +- format: # @schema enum:["CLF", "json", null]; type:[string, null]; default: "CLF" ++ format: # @schema enum:["common", "json", null]; type:[string, null]; default: "common" + # filePath: "/var/log/traefik/access.log + # -- Set [bufferingSize](https://doc.traefik.io/traefik/observability/access-logs/#bufferingsize) + bufferingSize: # @schema type:[integer, null] +@@ -911,35 +911,34 @@ hub: + # -- Certificate of the WebHook admission server. Default: "hub-agent-cert". + secretName: "" + +- ratelimit: +- redis: +- # -- Enable Redis Cluster. Default: true. +- cluster: # @schema type:[boolean, null] +- # -- Database used to store information. Default: "0". +- database: # @schema type:[string, null] +- # -- Endpoints of the Redis instances to connect to. Default: "". +- endpoints: "" +- # -- The username to use when connecting to Redis endpoints. Default: "". ++ redis: ++ # -- Enable Redis Cluster. Default: true. ++ cluster: # @schema type:[boolean, null] ++ # -- Database used to store information. Default: "0". ++ database: # @schema type:[string, null] ++ # -- Endpoints of the Redis instances to connect to. Default: "". ++ endpoints: "" ++ # -- The username to use when connecting to Redis endpoints. Default: "". ++ username: "" ++ # -- The password to use when connecting to Redis endpoints. Default: "". ++ password: "" ++ sentinel: ++ # -- Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". ++ masterset: "" ++ # -- Username to use for sentinel authentication (can be different from endpoint username). Default: "". + username: "" +- # -- The password to use when connecting to Redis endpoints. Default: "". ++ # -- Password to use for sentinel authentication (can be different from endpoint password). Default: "". + password: "" +- sentinel: +- # -- Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". +- masterset: "" +- # -- Username to use for sentinel authentication (can be different from endpoint username). Default: "". +- username: "" +- # -- Password to use for sentinel authentication (can be different from endpoint password). Default: "". +- password: "" +- # -- Timeout applied on connection with redis. Default: "0s". +- timeout: "" +- tls: +- # -- Path to the certificate authority used for the secured connection. +- ca: "" +- # -- Path to the public certificate used for the secure connection. +- cert: "" +- # -- Path to the private key used for the secure connection. +- key: "" +- # -- When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. +- insecureSkipVerify: false ++ # -- Timeout applied on connection with redis. Default: "0s". ++ timeout: "" ++ tls: ++ # -- Path to the certificate authority used for the secured connection. ++ ca: "" ++ # -- Path to the public certificate used for the secure connection. ++ cert: "" ++ # -- Path to the private key used for the secure connection. ++ key: "" ++ # -- When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. ++ insecureSkipVerify: false + # Enable export of errors logs to the platform. Default: true. + sendlogs: # @schema type:[boolean, null] +``` + +## 32.0.0-rc1 ![AppVersion: v3.1.4](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.4&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-09-20 + +* feat(Traefik Hub): add APIPlans and APIBundles CRDs +* chore(release): 🚀 publish 32.0.0-rc1 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d5173dc..51dec67 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -911,35 +911,34 @@ hub: + # -- Certificate of the WebHook admission server. Default: "hub-agent-cert". + secretName: "" + +- ratelimit: +- redis: +- # -- Enable Redis Cluster. Default: true. +- cluster: # @schema type:[boolean, null] +- # -- Database used to store information. Default: "0". +- database: # @schema type:[string, null] +- # -- Endpoints of the Redis instances to connect to. Default: "". +- endpoints: "" +- # -- The username to use when connecting to Redis endpoints. Default: "". ++ redis: ++ # -- Enable Redis Cluster. Default: true. ++ cluster: # @schema type:[boolean, null] ++ # -- Database used to store information. Default: "0". ++ database: # @schema type:[string, null] ++ # -- Endpoints of the Redis instances to connect to. Default: "". ++ endpoints: "" ++ # -- The username to use when connecting to Redis endpoints. Default: "". ++ username: "" ++ # -- The password to use when connecting to Redis endpoints. Default: "". ++ password: "" ++ sentinel: ++ # -- Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". ++ masterset: "" ++ # -- Username to use for sentinel authentication (can be different from endpoint username). Default: "". + username: "" +- # -- The password to use when connecting to Redis endpoints. Default: "". ++ # -- Password to use for sentinel authentication (can be different from endpoint password). Default: "". + password: "" +- sentinel: +- # -- Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". +- masterset: "" +- # -- Username to use for sentinel authentication (can be different from endpoint username). Default: "". +- username: "" +- # -- Password to use for sentinel authentication (can be different from endpoint password). Default: "". +- password: "" +- # -- Timeout applied on connection with redis. Default: "0s". +- timeout: "" +- tls: +- # -- Path to the certificate authority used for the secured connection. +- ca: "" +- # -- Path to the public certificate used for the secure connection. +- cert: "" +- # -- Path to the private key used for the secure connection. +- key: "" +- # -- When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. +- insecureSkipVerify: false ++ # -- Timeout applied on connection with redis. Default: "0s". ++ timeout: "" ++ tls: ++ # -- Path to the certificate authority used for the secured connection. ++ ca: "" ++ # -- Path to the public certificate used for the secure connection. ++ cert: "" ++ # -- Path to the private key used for the secure connection. ++ key: "" ++ # -- When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. ++ insecureSkipVerify: false + # Enable export of errors logs to the platform. Default: true. + sendlogs: # @schema type:[boolean, null] +``` + +## 31.1.1 ![AppVersion: v3.1.4](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.4&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-09-20 + +* fix: 🐛 updateStrategy behavior +* feat(deps): update traefik docker tag to v3.1.4 +* chore(release): 🚀 publish v31.1.1 + +## 31.1.0 ![AppVersion: v3.1.3](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.3&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-09-18 + +* fix: 🐛 update CRD to v3.1 +* feat: ✨ input validation using schema +* feat: ✨ add AllowACMEByPass and improve schema/doc on ports values +* feat: add new webhooks and removes unnecessary ones +* feat(deps): update traefik docker tag to v3.1.3 +* chore(release): 🚀 publish v31.1.0 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 2232d9e..1b9d0fd 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -2,13 +2,13 @@ + # This is a YAML-formatted file. + # Declare variables to be passed into templates + +-image: ++image: # @schema additionalProperties: false + # -- Traefik image host registry + registry: docker.io + # -- Traefik image repository + repository: traefik + # -- defaults to appVersion +- tag: ++ tag: # @schema type:[string, null] + # -- Traefik image pull policy + pullPolicy: IfNotPresent + +@@ -23,27 +23,27 @@ deployment: + # -- Number of pods of the deployment (only applies when kind == Deployment) + replicas: 1 + # -- Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) +- # revisionHistoryLimit: 1 ++ revisionHistoryLimit: # @schema type:[integer, null];minimum:0 + # -- Amount of time (in seconds) before Kubernetes will send the SIGKILL signal if Traefik does not shut down + terminationGracePeriodSeconds: 60 + # -- The minimum number of seconds Traefik needs to be up and running before the DaemonSet/Deployment controller considers it available + minReadySeconds: 0 +- ## Override the liveness/readiness port. This is useful to integrate traefik ++ ## -- Override the liveness/readiness port. This is useful to integrate traefik + ## with an external Load Balancer that performs healthchecks. + ## Default: ports.traefik.port +- # healthchecksPort: 9000 +- ## Override the liveness/readiness host. Useful for getting ping to respond on non-default entryPoint. ++ healthchecksPort: # @schema type:[integer, null];minimum:0 ++ ## -- Override the liveness/readiness host. Useful for getting ping to respond on non-default entryPoint. + ## Default: ports.traefik.hostIP if set, otherwise Pod IP +- # healthchecksHost: localhost +- ## Override the liveness/readiness scheme. Useful for getting ping to ++ healthchecksHost: "" ++ ## -- Override the liveness/readiness scheme. Useful for getting ping to + ## respond on websecure entryPoint. +- # healthchecksScheme: HTTPS +- ## Override the readiness path. ++ healthchecksScheme: # @schema enum:[HTTP, HTTPS, null]; type:[string, null]; default: HTTP ++ ## -- Override the readiness path. + ## Default: /ping +- # readinessPath: /ping +- # Override the liveness path. ++ readinessPath: "" ++ # -- Override the liveness path. + # Default: /ping +- # livenessPath: /ping ++ livenessPath: "" + # -- Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} + # -- Additional deployment labels (e.g. for filtering deployment by custom labels) +@@ -80,7 +80,7 @@ deployment: + # -- Use process namespace sharing + shareProcessNamespace: false + # -- Custom pod DNS policy. Apply if `hostNetwork: true` +- # dnsPolicy: ClusterFirstWithHostNet ++ dnsPolicy: "" + # -- Custom pod [DNS config](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#poddnsconfig-v1-core) + dnsConfig: {} + # -- Custom [host aliases](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/) +@@ -99,24 +99,24 @@ deployment: + # host: localhost + # scheme: HTTP + # -- Set a runtimeClassName on pod +- runtimeClassName: ++ runtimeClassName: "" + + # -- [Pod Disruption Budget](https://kubernetes.io/docs/reference/kubernetes-api/policy-resources/pod-disruption-budget-v1/) +-podDisruptionBudget: +- enabled: +- maxUnavailable: +- minAvailable: ++podDisruptionBudget: # @schema additionalProperties: false ++ enabled: false ++ maxUnavailable: # @schema type:[string, integer, null];minimum:0 ++ minAvailable: # @schema type:[string, integer, null];minimum:0 + + # -- Create a default IngressClass for Traefik +-ingressClass: ++ingressClass: # @schema additionalProperties: false + enabled: true + isDefaultClass: true +- # name: my-custom-class ++ name: "" + +-core: ++core: # @schema additionalProperties: false + # -- Can be used to use globally v2 router syntax + # See https://doc.traefik.io/traefik/v3.0/migration/v2-to-v3/#new-v3-syntax-notable-changes +- defaultRuleSyntax: ++ defaultRuleSyntax: "" + + # Traefik experimental features + experimental: +@@ -133,11 +133,11 @@ gateway: + # -- When providers.kubernetesGateway.enabled, deploy a default gateway + enabled: true + # -- Set a custom name to gateway +- name: ++ name: "" + # -- By default, Gateway is created in the same `Namespace` than Traefik. +- namespace: ++ namespace: "" + # -- Additional gateway annotations (e.g. for cert-manager.io/issuer) +- annotations: ++ annotations: {} + # -- Define listeners + listeners: + web: +@@ -145,11 +145,11 @@ gateway: + # The port must match a port declared in ports section. + port: 8000 + # -- Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) +- hostname: ++ hostname: "" + # Specify expected protocol on this listener. See [ProtocolType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ProtocolType) + protocol: HTTP + # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces +- namespacePolicy: ++ namespacePolicy: # @schema type:[string, null] + # websecure listener is disabled by default because certificateRefs needs to be added, + # or you may specify TLS protocol with Passthrough mode and add "--providers.kubernetesGateway.experimentalChannel=true" in additionalArguments section. + # websecure: +@@ -167,13 +167,13 @@ gateway: + # # -- TLS behavior for the TLS session initiated by the client. See [TLSModeType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.TLSModeType). + # mode: + +-gatewayClass: ++gatewayClass: # @schema additionalProperties: false + # -- When providers.kubernetesGateway.enabled and gateway.enabled, deploy a default gatewayClass + enabled: true + # -- Set a custom name to GatewayClass +- name: ++ name: "" + # -- Additional gatewayClass labels (e.g. for filtering gateway objects by custom labels) +- labels: ++ labels: {} + + ingressRoute: + dashboard: +@@ -218,14 +218,14 @@ ingressRoute: + # -- TLS options (e.g. secret containing certificate) + tls: {} + +-updateStrategy: ++updateStrategy: # @schema additionalProperties: false + # -- Customize updateStrategy: RollingUpdate or OnDelete + type: RollingUpdate + rollingUpdate: +- maxUnavailable: 0 +- maxSurge: 1 ++ maxUnavailable: 0 # @schema type:[integer, string, null] ++ maxSurge: 1 # @schema type:[integer, string, null] + +-readinessProbe: ++readinessProbe: # @schema additionalProperties: false + # -- The number of consecutive failures allowed before considering the probe as failed. + failureThreshold: 1 + # -- The number of seconds to wait before starting the first probe. +@@ -236,7 +236,7 @@ readinessProbe: + successThreshold: 1 + # -- The number of seconds to wait for a probe response before considering it as failed. + timeoutSeconds: 2 +-livenessProbe: ++livenessProbe: # @schema additionalProperties: false + # -- The number of consecutive failures allowed before considering the probe as failed. + failureThreshold: 3 + # -- The number of seconds to wait before starting the first probe. +@@ -249,9 +249,9 @@ livenessProbe: + timeoutSeconds: 2 + + # -- Define [Startup Probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes) +-startupProbe: ++startupProbe: {} + +-providers: ++providers: # @schema additionalProperties: false + kubernetesCRD: + # -- Load Kubernetes IngressRoute provider + enabled: true +@@ -262,12 +262,12 @@ providers: + # -- Allows to return 503 when there is no endpoints available + allowEmptyServices: true + # -- When the parameter is set, only resources containing an annotation with the same value are processed. Otherwise, resources missing the annotation, having an empty value, or the value traefik are processed. It will also set required annotation on Dashboard and Healthcheck IngressRoute when enabled. +- ingressClass: ++ ingressClass: "" + # labelSelector: environment=production,method=traefik + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] + # -- Defines whether to use Native Kubernetes load-balancing mode by default. +- nativeLBByDefault: ++ nativeLBByDefault: false + + kubernetesIngress: + # -- Load Kubernetes Ingress provider +@@ -277,7 +277,7 @@ providers: + # -- Allows to return 503 when there is no endpoints available + allowEmptyServices: true + # -- When ingressClass is set, only Ingresses containing an annotation with the same value are processed. Otherwise, Ingresses missing the annotation, having an empty value, or the value traefik are processed. +- ingressClass: ++ ingressClass: # @schema type:[string, null] + # labelSelector: environment=production,method=traefik + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] +@@ -288,7 +288,7 @@ providers: + # By default this Traefik service + # pathOverride: "" + # -- Defines whether to use Native Kubernetes load-balancing mode by default. +- nativeLBByDefault: ++ nativeLBByDefault: false + + kubernetesGateway: + # -- Enable Traefik Gateway provider for Gateway API +@@ -299,7 +299,7 @@ providers: + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] + # -- A label selector can be defined to filter on specific GatewayClass objects only. +- labelselector: ++ labelselector: "" + + file: + # -- Create a file provider +@@ -307,7 +307,7 @@ providers: + # -- Allows Traefik to automatically watch for file changes + watch: true + # -- File content (YAML format, go template supported) (see https://doc.traefik.io/traefik/providers/file/) +- content: ++ content: "" + + # -- Add volumes to the traefik pod. The volume name will be passed to tpl. + # This can be used to mount a cert pair or a configmap that holds a config.toml file. +@@ -333,90 +333,88 @@ additionalVolumeMounts: [] + logs: + general: + # -- Set [logs format](https://doc.traefik.io/traefik/observability/logs/#format) +- # @default common +- format: ++ format: # @schema enum:["common", "json", null]; type:[string, null]; default: "common" + # By default, the level is set to INFO. + # -- Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. +- level: INFO +- # +- # filePath: "/var/log/traefik/traefik.log +- # noColor: true ++ level: "INFO" # @schema enum:[INFO,WARN,ERROR,FATAL,PANIC,DEBUG]; default: "INFO" ++ # -- To write the logs into a log file, use the filePath option. ++ filePath: "" ++ # -- When set to true and format is common, it disables the colorized output. ++ noColor: false + access: + # -- To enable access logs + enabled: false + # -- Set [access log format](https://doc.traefik.io/traefik/observability/access-logs/#format) +- format: ++ format: # @schema enum:["CLF", "json", null]; type:[string, null]; default: "CLF" + # filePath: "/var/log/traefik/access.log + # -- Set [bufferingSize](https://doc.traefik.io/traefik/observability/access-logs/#bufferingsize) +- bufferingSize: ++ bufferingSize: # @schema type:[integer, null] + # -- Set [filtering](https://docs.traefik.io/observability/access-logs/#filtering) + filters: {} +- # statuscodes: "200,300-302" +- # retryattempts: true +- # minduration: 10ms ++ statuscodes: "" ++ retryattempts: false ++ minduration: "" + # -- Enables accessLogs for internal resources. Default: false. +- addInternals: ++ addInternals: false + fields: + general: +- # -- Available modes: keep, drop, redact. +- defaultmode: keep ++ # -- Set default mode for fields.names ++ defaultmode: keep # @schema enum:[keep, drop, redact]; default: keep + # -- Names of the fields to limit. + names: {} +- ## Examples: +- # ClientUsername: drop + # -- [Limit logged fields or headers](https://doc.traefik.io/traefik/observability/access-logs/#limiting-the-fieldsincluding-headers) + headers: +- # -- Available modes: keep, drop, redact. +- defaultmode: drop ++ # -- Set default mode for fields.headers ++ defaultmode: drop # @schema enum:[keep, drop, redact]; default: drop + names: {} + + metrics: + ## -- Enable metrics for internal resources. Default: false +- addInternals: ++ addInternals: false + + ## -- Prometheus is enabled by default. + ## -- It can be disabled by setting "prometheus: null" + prometheus: + # -- Entry point used to expose metrics. + entryPoint: metrics +- ## Enable metrics on entry points. Default=true +- # addEntryPointsLabels: false +- ## Enable metrics on routers. Default=false +- # addRoutersLabels: true +- ## Enable metrics on services. Default=true +- # addServicesLabels: false ++ ## Enable metrics on entry points. Default: true ++ addEntryPointsLabels: # @schema type:[boolean, null] ++ ## Enable metrics on routers. Default: false ++ addRoutersLabels: # @schema type:[boolean, null] ++ ## Enable metrics on services. Default: true ++ addServicesLabels: # @schema type:[boolean, null] + ## Buckets for latency metrics. Default="0.1,0.3,1.2,5.0" +- # buckets: "0.5,1.0,2.5" ++ buckets: "" + ## When manualRouting is true, it disables the default internal router in + ## order to allow creating a custom router for prometheus@internal service. +- # manualRouting: true ++ manualRouting: false + service: + # -- Create a dedicated metrics service to use with ServiceMonitor +- enabled: +- labels: +- annotations: ++ enabled: false ++ labels: {} ++ annotations: {} + # -- When set to true, it won't check if Prometheus Operator CRDs are deployed +- disableAPICheck: ++ disableAPICheck: # @schema type:[boolean, null] + serviceMonitor: + # -- Enable optional CR for Prometheus Operator. See EXAMPLES.md for more details. + enabled: false +- metricRelabelings: +- relabelings: +- jobLabel: +- interval: +- honorLabels: +- scrapeTimeout: +- honorTimestamps: +- enableHttp2: +- followRedirects: +- additionalLabels: +- namespace: +- namespaceSelector: ++ metricRelabelings: [] ++ relabelings: [] ++ jobLabel: "" ++ interval: "" ++ honorLabels: false ++ scrapeTimeout: "" ++ honorTimestamps: false ++ enableHttp2: false ++ followRedirects: false ++ additionalLabels: {} ++ namespace: "" ++ namespaceSelector: {} + prometheusRule: + # -- Enable optional CR for Prometheus Operator. See EXAMPLES.md for more details. + enabled: false +- additionalLabels: +- namespace: ++ additionalLabels: {} ++ namespace: "" + + # datadog: + # ## Address instructs exporter to send metrics to datadog-agent at this address. +@@ -469,55 +467,55 @@ metrics: + # -- Set to true in order to enable the OpenTelemetry metrics + enabled: false + # -- Enable metrics on entry points. Default: true +- addEntryPointsLabels: ++ addEntryPointsLabels: # @schema type:[boolean, null] + # -- Enable metrics on routers. Default: false +- addRoutersLabels: ++ addRoutersLabels: # @schema type:[boolean, null] + # -- Enable metrics on services. Default: true +- addServicesLabels: ++ addServicesLabels: # @schema type:[boolean, null] + # -- Explicit boundaries for Histogram data points. Default: [.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10] +- explicitBoundaries: ++ explicitBoundaries: [] + # -- Interval at which metrics are sent to the OpenTelemetry Collector. Default: 10s +- pushInterval: ++ pushInterval: "" + http: + # -- Set to true in order to send metrics to the OpenTelemetry Collector using HTTP. + enabled: false + # -- Format: ://:. Default: http://localhost:4318/v1/metrics +- endpoint: ++ endpoint: "" + # -- Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. +- headers: ++ headers: {} + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. +- ca: ++ ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. +- cert: ++ cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. +- key: ++ key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. +- insecureSkipVerify: ++ insecureSkipVerify: # @schema type:[boolean, null] + grpc: + # -- Set to true in order to send metrics to the OpenTelemetry Collector using gRPC + enabled: false + # -- Format: ://:. Default: http://localhost:4318/v1/metrics +- endpoint: ++ endpoint: "" + # -- Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. +- insecure: ++ insecure: false + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. +- ca: ++ ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. +- cert: ++ cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. +- key: ++ key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. +- insecureSkipVerify: ++ insecureSkipVerify: false + + ## Tracing + # -- https://doc.traefik.io/traefik/observability/tracing/overview/ +-tracing: ++tracing: # @schema additionalProperties: false + # -- Enables tracing for internal resources. Default: false. +- addInternals: ++ addInternals: false + otlp: + # -- See https://doc.traefik.io/traefik/v3.0/observability/tracing/opentelemetry/ + enabled: false +@@ -525,36 +523,36 @@ tracing: + # -- Set to true in order to send metrics to the OpenTelemetry Collector using HTTP. + enabled: false + # -- Format: ://:. Default: http://localhost:4318/v1/metrics +- endpoint: ++ endpoint: "" + # -- Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. +- headers: ++ headers: {} + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. +- ca: ++ ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. +- cert: ++ cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. +- key: ++ key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. +- insecureSkipVerify: ++ insecureSkipVerify: false + grpc: + # -- Set to true in order to send metrics to the OpenTelemetry Collector using gRPC + enabled: false + # -- Format: ://:. Default: http://localhost:4318/v1/metrics +- endpoint: ++ endpoint: "" + # -- Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. +- insecure: ++ insecure: false + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. +- ca: ++ ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. +- cert: ++ cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. +- key: ++ key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. +- insecureSkipVerify: ++ insecureSkipVerify: false + + # -- Global command arguments to be passed to all traefik's pods + globalArguments: +@@ -587,13 +585,12 @@ ports: + traefik: + port: 9000 + # -- Use hostPort if set. +- # hostPort: 9000 +- # ++ hostPort: # @schema type:[integer, null]; minimum:0 + # -- Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which + # means it's listening on all your interfaces and all your IPs. You may want + # to set this value if you need traefik to listen on specific interface + # only. +- # hostIP: 192.168.100.10 ++ hostIP: # @schema type:[string, null] + + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. +@@ -617,112 +614,93 @@ ports: + default: true + exposedPort: 80 + ## -- Different target traefik port on the cluster, useful for IP type LB +- # targetPort: 80 ++ targetPort: # @schema type:[integer, null]; minimum:0 + # The port protocol (TCP/UDP) + protocol: TCP +- # -- Use nodeport if set. This is useful if you have configured Traefik in a +- # LoadBalancer. +- # nodePort: 32080 ++ # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) ++ nodePort: # @schema type:[integer, null]; minimum:0 + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection +- # redirectTo: +- # port: websecure +- # (Optional) +- # priority: 10 +- # permanent: true +- # +- # -- Trust forwarded headers information (X-Forwarded-*). +- # forwardedHeaders: +- # trustedIPs: [] +- # insecure: false +- # +- # -- Enable the Proxy Protocol header parsing for the entry point +- # proxyProtocol: +- # trustedIPs: [] +- # insecure: false +- # ++ redirectTo: {} ++ forwardedHeaders: ++ # -- Trust forwarded headers information (X-Forwarded-*). ++ trustedIPs: [] ++ insecure: false ++ proxyProtocol: ++ # -- Enable the Proxy Protocol header parsing for the entry point ++ trustedIPs: [] ++ insecure: false + # -- Set transport settings for the entrypoint; see also + # https://doc.traefik.io/traefik/routing/entrypoints/#transport + transport: + respondingTimeouts: +- readTimeout: +- writeTimeout: +- idleTimeout: ++ readTimeout: # @schema type:[string, integer, null] ++ writeTimeout: # @schema type:[string, integer, null] ++ idleTimeout: # @schema type:[string, integer, null] + lifeCycle: +- requestAcceptGraceTimeout: +- graceTimeOut: +- keepAliveMaxRequests: +- keepAliveMaxTime: ++ requestAcceptGraceTimeout: # @schema type:[string, integer, null] ++ graceTimeOut: # @schema type:[string, integer, null] ++ keepAliveMaxRequests: # @schema type:[integer, null]; minimum:0 ++ keepAliveMaxTime: # @schema type:[string, integer, null] + websecure: + ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8443 +- # hostPort: 8443 +- # containerPort: 8443 ++ hostPort: # @schema type:[integer, null]; minimum:0 ++ containerPort: # @schema type:[integer, null]; minimum:0 + expose: + default: true + exposedPort: 443 + ## -- Different target traefik port on the cluster, useful for IP type LB +- # targetPort: 80 ++ targetPort: # @schema type:[integer, null]; minimum:0 + ## -- The port protocol (TCP/UDP) + protocol: TCP +- # nodePort: 32443 +- ## -- Specify an application protocol. This may be used as a hint for a Layer 7 load balancer. +- # appProtocol: https +- # +- ## -- Enable HTTP/3 on the entrypoint +- ## Enabling it will also enable http3 experimental feature +- ## https://doc.traefik.io/traefik/routing/entrypoints/#http3 +- ## There are known limitations when trying to listen on same ports for +- ## TCP & UDP (Http3). There is a workaround in this chart using dual Service. +- ## https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741 ++ # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) ++ nodePort: # @schema type:[integer, null]; minimum:0 ++ # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol) ++ appProtocol: # @schema type:[string, null] ++ # -- See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#allowacmebypass) ++ allowACMEByPass: false + http3: ++ ## -- Enable HTTP/3 on the entrypoint ++ ## Enabling it will also enable http3 experimental feature ++ ## https://doc.traefik.io/traefik/routing/entrypoints/#http3 ++ ## There are known limitations when trying to listen on same ports for ++ ## TCP & UDP (Http3). There is a workaround in this chart using dual Service. ++ ## https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741 + enabled: false +- # advertisedPort: 4443 +- # +- # -- Trust forwarded headers information (X-Forwarded-*). +- # forwardedHeaders: +- # trustedIPs: [] +- # insecure: false +- # +- # -- Enable the Proxy Protocol header parsing for the entry point +- # proxyProtocol: +- # trustedIPs: [] +- # insecure: false +- # +- # -- Set transport settings for the entrypoint; see also +- # https://doc.traefik.io/traefik/routing/entrypoints/#transport ++ advertisedPort: # @schema type:[integer, null]; minimum:0 ++ forwardedHeaders: ++ # -- Trust forwarded headers information (X-Forwarded-*). ++ trustedIPs: [] ++ insecure: false ++ proxyProtocol: ++ # -- Enable the Proxy Protocol header parsing for the entry point ++ trustedIPs: [] ++ insecure: false ++ # -- See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#transport) + transport: + respondingTimeouts: +- readTimeout: +- writeTimeout: +- idleTimeout: ++ readTimeout: # @schema type:[string, integer, null] ++ writeTimeout: # @schema type:[string, integer, null] ++ idleTimeout: # @schema type:[string, integer, null] + lifeCycle: +- requestAcceptGraceTimeout: +- graceTimeOut: +- keepAliveMaxRequests: +- keepAliveMaxTime: +- # +- ## Set TLS at the entrypoint +- ## https://doc.traefik.io/traefik/routing/entrypoints/#tls ++ requestAcceptGraceTimeout: # @schema type:[string, integer, null] ++ graceTimeOut: # @schema type:[string, integer, null] ++ keepAliveMaxRequests: # @schema type:[integer, null]; minimum:0 ++ keepAliveMaxTime: # @schema type:[string, integer, null] ++ # -- See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#tls) + tls: + enabled: true +- # this is the name of a TLSOption definition + options: "" + certResolver: "" + domains: [] +- # - main: example.com +- # sans: +- # - foo.example.com +- # - bar.example.com +- # + # -- One can apply Middlewares on an entrypoint + # https://doc.traefik.io/traefik/middlewares/overview/ + # https://doc.traefik.io/traefik/routing/entrypoints/#middlewares + # -- /!\ It introduces here a link between your static configuration and your dynamic configuration /!\ + # It follows the provider naming convention: https://doc.traefik.io/traefik/providers/overview/#provider-namespace +- # middlewares: + # - namespace-name1@kubernetescrd + # - namespace-name2@kubernetescrd + middlewares: [] +@@ -730,10 +708,6 @@ ports: + # -- When using hostNetwork, use another port to avoid conflict with node exporter: + # https://github.com/prometheus/prometheus/wiki/Default-port-allocations + port: 9100 +- # hostPort: 9100 +- # Defines whether the port is exposed if service.type is LoadBalancer or +- # NodePort. +- # + # -- You may not want to expose the metrics port on production deployments. + # If you want to access it from outside your cluster, + # use `kubectl port-forward` or create a secure ingress +@@ -810,15 +784,15 @@ persistence: + # It can be used to store TLS certificates, see `storage` in certResolvers + enabled: false + name: data +- # existingClaim: "" ++ existingClaim: "" + accessMode: ReadWriteOnce + size: 128Mi +- # storageClass: "" +- # volumeName: "" ++ storageClass: "" ++ volumeName: "" + path: /data + annotations: {} + # -- Only mount a subpath of the Volume into the pod +- # subPath: "" ++ subPath: "" + + # -- Certificates resolvers configuration. + # Ref: https://doc.traefik.io/traefik/https/acme/#certificate-resolvers +@@ -832,7 +806,7 @@ certResolvers: {} + hostNetwork: false + + # -- Whether Role Based Access Control objects like roles and rolebindings should be created +-rbac: ++rbac: # @schema additionalProperties: false + enabled: true + # When set to true: + # 1. Use `Role` and `RoleBinding` instead of `ClusterRole` and `ClusterRoleBinding`. +@@ -843,7 +817,7 @@ rbac: + namespaced: false + # Enable user-facing roles + # https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles +- # aggregateTo: [ "admin" ] ++ aggregateTo: [] + # List of Kubernetes secrets that are accessible for Traefik. If empty, then access is granted to every secret. + secretResourceNames: [] + +@@ -852,7 +826,7 @@ podSecurityPolicy: + enabled: false + + # -- The service account the pods will use to interact with the Kubernetes API +-serviceAccount: ++serviceAccount: # @schema additionalProperties: false + # If set, an existing service account is used + # If not set, a service account is created automatically using the fullname template + name: "" +@@ -918,54 +892,54 @@ extraObjects: [] + + # -- This field override the default Release Namespace for Helm. + # It will not affect optional CRDs such as `ServiceMonitor` and `PrometheusRules` +-namespaceOverride: ++namespaceOverride: "" + + ## -- This field override the default app.kubernetes.io/instance label for all Objects. +-instanceLabelOverride: ++instanceLabelOverride: "" + + # Traefik Hub configuration. See https://doc.traefik.io/traefik-hub/ + hub: + # -- Name of `Secret` with key 'token' set to a valid license token. + # It enables API Gateway. +- token: ++ token: "" + apimanagement: + # -- Set to true in order to enable API Management. Requires a valid license token. +- enabled: ++ enabled: false + admission: + # -- WebHook admission server listen address. Default: "0.0.0.0:9943". +- listenAddr: ++ listenAddr: "" + # -- Certificate of the WebHook admission server. Default: "hub-agent-cert". +- secretName: ++ secretName: "" + + ratelimit: + redis: + # -- Enable Redis Cluster. Default: true. +- cluster: ++ cluster: # @schema type:[boolean, null] + # -- Database used to store information. Default: "0". +- database: ++ database: # @schema type:[string, null] + # -- Endpoints of the Redis instances to connect to. Default: "". +- endpoints: ++ endpoints: "" + # -- The username to use when connecting to Redis endpoints. Default: "". +- username: ++ username: "" + # -- The password to use when connecting to Redis endpoints. Default: "". +- password: ++ password: "" + sentinel: + # -- Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". +- masterset: ++ masterset: "" + # -- Username to use for sentinel authentication (can be different from endpoint username). Default: "". +- username: ++ username: "" + # -- Password to use for sentinel authentication (can be different from endpoint password). Default: "". +- password: ++ password: "" + # -- Timeout applied on connection with redis. Default: "0s". +- timeout: ++ timeout: "" + tls: + # -- Path to the certificate authority used for the secured connection. +- ca: ++ ca: "" + # -- Path to the public certificate used for the secure connection. +- cert: ++ cert: "" + # -- Path to the private key used for the secure connection. +- key: ++ key: "" + # -- When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. +- insecureSkipVerify: ++ insecureSkipVerify: false + # Enable export of errors logs to the platform. Default: true. +- sendlogs: ++ sendlogs: # @schema type:[boolean, null] +``` + +## 31.0.0 ![AppVersion: v3.1.2](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.2&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-09-03 + +* fix(Traefik Hub): update CRDs to v1.5.0 +* fix(HTTP3): split udp and tcp Service when service.single is false +* fix!: 🐛 set allowEmptyServices to true by default +* feat(Traefik Hub): update CRDs to v1.7.0 +* chore(release): 🚀 publish v31.0.0 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 78eeacf..2232d9e 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -260,7 +260,7 @@ providers: + # -- Allows to reference ExternalName services in IngressRoute + allowExternalNameServices: false + # -- Allows to return 503 when there is no endpoints available +- allowEmptyServices: false ++ allowEmptyServices: true + # -- When the parameter is set, only resources containing an annotation with the same value are processed. Otherwise, resources missing the annotation, having an empty value, or the value traefik are processed. It will also set required annotation on Dashboard and Healthcheck IngressRoute when enabled. + ingressClass: + # labelSelector: environment=production,method=traefik +@@ -275,7 +275,7 @@ providers: + # -- Allows to reference ExternalName services in Ingress + allowExternalNameServices: false + # -- Allows to return 503 when there is no endpoints available +- allowEmptyServices: false ++ allowEmptyServices: true + # -- When ingressClass is set, only Ingresses containing an annotation with the same value are processed. Otherwise, Ingresses missing the annotation, having an empty value, or the value traefik are processed. + ingressClass: + # labelSelector: environment=production,method=traefik +``` + +## 30.1.0 ![AppVersion: v3.1.2](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.2&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-08-14 + +* fix: disable default HTTPS listener for gateway +* fix(Gateway API): wildcard support in hostname +* fix(Gateway API): use Standard channel by default +* feat: ✨ rework namespaced RBAC with `disableClusterScopeResources` +* chore(release): 🚀 publish v30.1.0 +* chore(deps): update traefik docker tag to v3.1.2 +* chore(deps): update traefik docker tag to v3.1.1 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 83b6d98..78eeacf 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -150,20 +150,22 @@ gateway: + protocol: HTTP + # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces + namespacePolicy: +- websecure: +- # -- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. +- # The port must match a port declared in ports section. +- port: 8443 +- # -- Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) +- hostname: +- # Specify expected protocol on this listener See [ProtocolType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ProtocolType) +- protocol: HTTPS +- # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces) +- namespacePolicy: +- # -- Add certificates for TLS or HTTPS protocols. See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig) +- certificateRefs: +- # -- TLS behavior for the TLS session initiated by the client. See [TLSModeType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.TLSModeType). +- mode: ++ # websecure listener is disabled by default because certificateRefs needs to be added, ++ # or you may specify TLS protocol with Passthrough mode and add "--providers.kubernetesGateway.experimentalChannel=true" in additionalArguments section. ++ # websecure: ++ # # -- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. ++ # # The port must match a port declared in ports section. ++ # port: 8443 ++ # # -- Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) ++ # hostname: ++ # # Specify expected protocol on this listener See [ProtocolType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ProtocolType) ++ # protocol: HTTPS ++ # # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces) ++ # namespacePolicy: ++ # # -- Add certificates for TLS or HTTPS protocols. See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig) ++ # certificateRefs: ++ # # -- TLS behavior for the TLS session initiated by the client. See [TLSModeType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.TLSModeType). ++ # mode: + + gatewayClass: + # -- When providers.kubernetesGateway.enabled and gateway.enabled, deploy a default gatewayClass +@@ -279,10 +281,6 @@ providers: + # labelSelector: environment=production,method=traefik + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] +- # - "default" +- # Disable cluster IngressClass Lookup - Requires Traefik V3. +- # When combined with rbac.namespaced: true, ClusterRole will not be created and ingresses must use kubernetes.io/ingress.class annotation instead of spec.ingressClassName. +- disableIngressClassLookup: false + # IP used for Kubernetes Ingress endpoints + publishedService: + enabled: false +@@ -836,9 +834,12 @@ hostNetwork: false + # -- Whether Role Based Access Control objects like roles and rolebindings should be created + rbac: + enabled: true +- # If set to false, installs ClusterRole and ClusterRoleBinding so Traefik can be used across namespaces. +- # If set to true, installs Role and RoleBinding instead of ClusterRole/ClusterRoleBinding. Providers will only watch target namespace. +- # When combined with providers.kubernetesIngress.disableIngressClassLookup: true and Traefik V3, ClusterRole to watch IngressClass is also disabled. ++ # When set to true: ++ # 1. Use `Role` and `RoleBinding` instead of `ClusterRole` and `ClusterRoleBinding`. ++ # 2. Set `disableIngressClassLookup` on Kubernetes Ingress providers with Traefik Proxy v3 until v3.1.1 ++ # 3. Set `disableClusterScopeResources` on Kubernetes Ingress and CRD providers with Traefik Proxy v3.1.2+ ++ # **NOTE**: `IngressClass`, `NodePortLB` and **Gateway** provider cannot be used with namespaced RBAC. ++ # See [upstream documentation](https://doc.traefik.io/traefik/providers/kubernetes-ingress/#disableclusterscoperesources) for more details. + namespaced: false + # Enable user-facing roles + # https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles +``` + +## 30.0.2 ![AppVersion: v3.1.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-07-30 + +* fix(Traefik Hub): missing RBACs for Traefik Hub +* chore(release): 🚀 publish v30.0.2 + +## 30.0.1 ![AppVersion: v3.1.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-07-29 + +* fix(Traefik Hub): support new RBACs for upcoming traefik hub release +* fix(Traefik Hub): RBACs missing with API Gateway +* feat: :release: v30.0.1 + +## 30.0.0 ![AppVersion: v3.1.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.1.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-07-24 + +* fix: 🐛 ingressroute default name +* fix: namespaced RBACs hub api gateway +* fix: can't set gateway name +* fix(Gateway API): provide expected roles when using namespaced RBAC +* fix(Gateway API)!: revamp Gateway implementation +* feat: ✨ display release name and image full path in installation notes +* feat: use single ingressRoute template +* feat: handle log filePath and noColor +* chore(release): 🚀 publish v30.0.0 +* chore(deps): update traefik docker tag to v3.1.0 + +**Upgrade Notes** + +There is a breaking upgrade on how to configure Gateway with _values_. +This release supports Traefik Proxy v3.0 **and** v3.1. + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index c8bfd5b..83b6d98 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -134,14 +134,36 @@ gateway: + enabled: true + # -- Set a custom name to gateway + name: +- # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.FromNamespaces) +- namespacePolicy: +- # -- See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig) +- certificateRefs: + # -- By default, Gateway is created in the same `Namespace` than Traefik. + namespace: + # -- Additional gateway annotations (e.g. for cert-manager.io/issuer) + annotations: ++ # -- Define listeners ++ listeners: ++ web: ++ # -- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. ++ # The port must match a port declared in ports section. ++ port: 8000 ++ # -- Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) ++ hostname: ++ # Specify expected protocol on this listener. See [ProtocolType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ProtocolType) ++ protocol: HTTP ++ # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces ++ namespacePolicy: ++ websecure: ++ # -- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. ++ # The port must match a port declared in ports section. ++ port: 8443 ++ # -- Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) ++ hostname: ++ # Specify expected protocol on this listener See [ProtocolType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ProtocolType) ++ protocol: HTTPS ++ # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces) ++ namespacePolicy: ++ # -- Add certificates for TLS or HTTPS protocols. See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig) ++ certificateRefs: ++ # -- TLS behavior for the TLS session initiated by the client. See [TLSModeType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.TLSModeType). ++ mode: + + gatewayClass: + # -- When providers.kubernetesGateway.enabled and gateway.enabled, deploy a default gatewayClass +@@ -161,6 +183,10 @@ ingressRoute: + labels: {} + # -- The router match rule used for the dashboard ingressRoute + matchRule: PathPrefix(`/dashboard`) || PathPrefix(`/api`) ++ # -- The internal service used for the dashboard ingressRoute ++ services: ++ - name: api@internal ++ kind: TraefikService + # -- Specify the allowed entrypoints to use for the dashboard ingress route, (e.g. traefik, web, websecure). + # By default, it's using traefik entrypoint, which is not exposed. + # /!\ Do not expose your dashboard without any protection over the internet /!\ +@@ -178,6 +204,10 @@ ingressRoute: + labels: {} + # -- The router match rule used for the healthcheck ingressRoute + matchRule: PathPrefix(`/ping`) ++ # -- The internal service used for the healthcheck ingressRoute ++ services: ++ - name: ping@internal ++ kind: TraefikService + # -- Specify the allowed entrypoints to use for the healthcheck ingress route, (e.g. traefik, web, websecure). + # By default, it's using traefik entrypoint, which is not exposed. + entryPoints: ["traefik"] +@@ -307,9 +337,12 @@ logs: + # -- Set [logs format](https://doc.traefik.io/traefik/observability/logs/#format) + # @default common + format: +- # By default, the level is set to ERROR. ++ # By default, the level is set to INFO. + # -- Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. + level: INFO ++ # ++ # filePath: "/var/log/traefik/traefik.log ++ # noColor: true + access: + # -- To enable access logs + enabled: false +``` + + +## 29.0.1 ![AppVersion: v3.0.4](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.4&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-07-09 + +* fix: semverCompare failing on some legitimate tags +* fix: RBACs for hub and disabled namespaced RBACs +* chore(release): 🚀 publish v29.0.1 +* chore(deps): update jnorwood/helm-docs docker tag to v1.14.0 + +## 29.0.0 ![AppVersion: v3.0.4](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.4&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Upgrade Notes** + +This is a major breaking upgrade. [Migration guide](https://doc.traefik.io/traefik/v3.1/migration/v3/#v30-to-v31) from v3.0 to v3.1rc has been applied on this chart. + +This release supports both Traefik Proxy v3.0.x and v3.1rc. + +It comes with those breaking changes: + +- Far better support on Gateway API v1.1: Gateway, GatewayClass, CRDs & RBAC (#1107) +- Many changes on CRDs & RBAC (#1072 & #1108) +- Refactor on Prometheus Operator support. Values has changed (#1114) +- Dashboard `IngressRoute` is now disabled by default (#1111) + +CRDs needs to be upgraded: `kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik/crds/` + +**Release date:** 2024-07-05 + +* fix: 🐛 improve error message on additional service without ports +* fix: allow multiples values in the `secretResourceNames` slice +* fix(rbac)!: nodes API permissions for Traefik v3.1+ +* fix(dashboard): Only set ingressClass annotation when kubernetesCRD provider is listening for it +* fix!: prometheus operator settings +* feat: ✨ update CRDs & RBAC for Traefik Proxy +* feat: ✨ migrate to endpointslices rbac +* feat: allow to set hostAliases for traefik pod +* feat(providers): add nativeLBByDefault support +* feat(providers)!: improve kubernetesGateway and Gateway API support +* feat(dashboard)!: dashboard `IngressRoute` should be disabled by default +* docs: fix typos and broken link +* chore: update CRDs to v1.5.0 +* chore: update CRDs to v1.4.0 +* chore(release): publish v29.0.0 +* chore(deps): update traefik docker tag to v3.0.4 +* chore(deps): update traefik docker tag to v3.0.3 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e440dcf..c8bfd5b 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -8,7 +8,7 @@ image: + # -- Traefik image repository + repository: traefik + # -- defaults to appVersion +- tag: "" ++ tag: + # -- Traefik image pull policy + pullPolicy: IfNotPresent + +@@ -81,19 +81,12 @@ deployment: + shareProcessNamespace: false + # -- Custom pod DNS policy. Apply if `hostNetwork: true` + # dnsPolicy: ClusterFirstWithHostNet ++ # -- Custom pod [DNS config](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#poddnsconfig-v1-core) + dnsConfig: {} +- # nameservers: +- # - 192.0.2.1 # this is an example +- # searches: +- # - ns1.svc.cluster-domain.example +- # - my.dns.search.suffix +- # options: +- # - name: ndots +- # value: "2" +- # - name: edns0 +- # -- Additional imagePullSecrets ++ # -- Custom [host aliases](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/) ++ hostAliases: [] ++ # -- Pull secret for fetching traefik container image + imagePullSecrets: [] +- # - name: myRegistryKeySecretName + # -- Pod lifecycle actions + lifecycle: {} + # preStop: +@@ -135,24 +128,33 @@ experimental: + kubernetesGateway: + # -- Enable traefik experimental GatewayClass CRD + enabled: false +- ## Routes are restricted to namespace of the gateway by default. +- ## https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.FromNamespaces +- # namespacePolicy: All +- # certificate: +- # group: "core" +- # kind: "Secret" +- # name: "mysecret" +- # -- By default, Gateway would be created to the Namespace you are deploying Traefik to. +- # You may create that Gateway in another namespace, setting its name below: +- # namespace: default +- # Additional gateway annotations (e.g. for cert-manager.io/issuer) +- # annotations: +- # cert-manager.io/issuer: letsencrypt ++ ++gateway: ++ # -- When providers.kubernetesGateway.enabled, deploy a default gateway ++ enabled: true ++ # -- Set a custom name to gateway ++ name: ++ # -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.FromNamespaces) ++ namespacePolicy: ++ # -- See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig) ++ certificateRefs: ++ # -- By default, Gateway is created in the same `Namespace` than Traefik. ++ namespace: ++ # -- Additional gateway annotations (e.g. for cert-manager.io/issuer) ++ annotations: ++ ++gatewayClass: ++ # -- When providers.kubernetesGateway.enabled and gateway.enabled, deploy a default gatewayClass ++ enabled: true ++ # -- Set a custom name to GatewayClass ++ name: ++ # -- Additional gatewayClass labels (e.g. for filtering gateway objects by custom labels) ++ labels: + + ingressRoute: + dashboard: + # -- Create an IngressRoute for the dashboard +- enabled: true ++ enabled: false + # -- Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) + annotations: {} + # -- Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) +@@ -227,11 +229,13 @@ providers: + allowExternalNameServices: false + # -- Allows to return 503 when there is no endpoints available + allowEmptyServices: false +- # ingressClass: traefik-internal ++ # -- When the parameter is set, only resources containing an annotation with the same value are processed. Otherwise, resources missing the annotation, having an empty value, or the value traefik are processed. It will also set required annotation on Dashboard and Healthcheck IngressRoute when enabled. ++ ingressClass: + # labelSelector: environment=production,method=traefik + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] +- # - "default" ++ # -- Defines whether to use Native Kubernetes load-balancing mode by default. ++ nativeLBByDefault: + + kubernetesIngress: + # -- Load Kubernetes Ingress provider +@@ -240,7 +244,8 @@ providers: + allowExternalNameServices: false + # -- Allows to return 503 when there is no endpoints available + allowEmptyServices: false +- # ingressClass: traefik-internal ++ # -- When ingressClass is set, only Ingresses containing an annotation with the same value are processed. Otherwise, Ingresses missing the annotation, having an empty value, or the value traefik are processed. ++ ingressClass: + # labelSelector: environment=production,method=traefik + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] +@@ -254,6 +259,19 @@ providers: + # Published Kubernetes Service to copy status from. Format: namespace/servicename + # By default this Traefik service + # pathOverride: "" ++ # -- Defines whether to use Native Kubernetes load-balancing mode by default. ++ nativeLBByDefault: ++ ++ kubernetesGateway: ++ # -- Enable Traefik Gateway provider for Gateway API ++ enabled: false ++ # -- Toggles support for the Experimental Channel resources (Gateway API release channels documentation). ++ # This option currently enables support for TCPRoute and TLSRoute. ++ experimentalChannel: false ++ # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. ++ namespaces: [] ++ # -- A label selector can be defined to filter on specific GatewayClass objects only. ++ labelselector: + + file: + # -- Create a file provider +@@ -341,6 +359,34 @@ metrics: + ## When manualRouting is true, it disables the default internal router in + ## order to allow creating a custom router for prometheus@internal service. + # manualRouting: true ++ service: ++ # -- Create a dedicated metrics service to use with ServiceMonitor ++ enabled: ++ labels: ++ annotations: ++ # -- When set to true, it won't check if Prometheus Operator CRDs are deployed ++ disableAPICheck: ++ serviceMonitor: ++ # -- Enable optional CR for Prometheus Operator. See EXAMPLES.md for more details. ++ enabled: false ++ metricRelabelings: ++ relabelings: ++ jobLabel: ++ interval: ++ honorLabels: ++ scrapeTimeout: ++ honorTimestamps: ++ enableHttp2: ++ followRedirects: ++ additionalLabels: ++ namespace: ++ namespaceSelector: ++ prometheusRule: ++ # -- Enable optional CR for Prometheus Operator. See EXAMPLES.md for more details. ++ enabled: false ++ additionalLabels: ++ namespace: ++ + # datadog: + # ## Address instructs exporter to send metrics to datadog-agent at this address. + # address: "127.0.0.1:8125" +@@ -436,55 +482,6 @@ metrics: + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. + insecureSkipVerify: + +- ## -- enable optional CRDs for Prometheus Operator +- ## +- ## Create a dedicated metrics service for use with ServiceMonitor +- # service: +- # enabled: false +- # labels: {} +- # annotations: {} +- ## When set to true, it won't check if Prometheus Operator CRDs are deployed +- # disableAPICheck: false +- # serviceMonitor: +- # metricRelabelings: [] +- # - sourceLabels: [__name__] +- # separator: ; +- # regex: ^fluentd_output_status_buffer_(oldest|newest)_.+ +- # replacement: $1 +- # action: drop +- # relabelings: [] +- # - sourceLabels: [__meta_kubernetes_pod_node_name] +- # separator: ; +- # regex: ^(.*)$ +- # targetLabel: nodename +- # replacement: $1 +- # action: replace +- # jobLabel: traefik +- # interval: 30s +- # honorLabels: true +- # # (Optional) +- # # scrapeTimeout: 5s +- # # honorTimestamps: true +- # # enableHttp2: true +- # # followRedirects: true +- # # additionalLabels: +- # # foo: bar +- # # namespace: "another-namespace" +- # # namespaceSelector: {} +- # prometheusRule: +- # additionalLabels: {} +- # namespace: "another-namespace" +- # rules: +- # - alert: TraefikDown +- # expr: up{job="traefik"} == 0 +- # for: 5m +- # labels: +- # context: traefik +- # severity: warning +- # annotations: +- # summary: "Traefik Down" +- # description: "{{ $labels.pod }} on {{ $labels.nodename }} is down" +- + ## Tracing + # -- https://doc.traefik.io/traefik/observability/tracing/overview/ + tracing: +``` + +## 28.3.0 ![AppVersion: v3.0.2](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.2&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-06-14 + +* fix: 🐛 namespaced rbac when kubernetesIngress provider is disabled +* fix: 🐛 add divisor: '1' to GOMAXPROCS and GOMEMLIMIT +* fix(security): 🐛 🔒️ mount service account token on pod level +* fix(Traefik Hub): remove obsolete CRD +* fix(Traefik Hub): remove namespace in mutating webhook +* feat: allow setting permanent on redirectTo +* chore(release): publish v28.3.0 +* chore(deps): update traefik docker tag to v3.0.2 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index c558c78..e440dcf 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -602,6 +602,7 @@ ports: + # port: websecure + # (Optional) + # priority: 10 ++ # permanent: true + # + # -- Trust forwarded headers information (X-Forwarded-*). + # forwardedHeaders: +``` + +## 28.2.0 ![AppVersion: v3.0.1](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.1&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-05-28 + +* fix(IngressClass): provides annotation on IngressRoutes when it's enabled +* feat: ✨ simplify values and provide more examples +* feat: add deletecollection right on secrets +* chore(release): 🚀 publish v28.2.0 +* chore(deps): update traefik docker tag to v3.0.1 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 2fd9282..c558c78 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,4 +1,7 @@ + # Default values for Traefik ++# This is a YAML-formatted file. ++# Declare variables to be passed into templates ++ + image: + # -- Traefik image host registry + registry: docker.io +@@ -12,9 +15,6 @@ image: + # -- Add additional label to all resources + commonLabels: {} + +-# +-# Configure the deployment +-# + deployment: + # -- Enable deployment + enabled: true +@@ -74,10 +74,6 @@ deployment: + # - name: volume-permissions + # image: busybox:latest + # command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"] +- # securityContext: +- # runAsNonRoot: true +- # runAsGroup: 65532 +- # runAsUser: 65532 + # volumeMounts: + # - name: data + # mountPath: /data +@@ -112,13 +108,11 @@ deployment: + # -- Set a runtimeClassName on pod + runtimeClassName: + +-# -- Pod disruption budget ++# -- [Pod Disruption Budget](https://kubernetes.io/docs/reference/kubernetes-api/policy-resources/pod-disruption-budget-v1/) + podDisruptionBudget: +- enabled: false +- # maxUnavailable: 1 +- # maxUnavailable: 33% +- # minAvailable: 0 +- # minAvailable: 25% ++ enabled: ++ maxUnavailable: ++ minAvailable: + + # -- Create a default IngressClass for Traefik + ingressClass: +@@ -155,7 +149,6 @@ experimental: + # annotations: + # cert-manager.io/issuer: letsencrypt + +-## Create an IngressRoute for the dashboard + ingressRoute: + dashboard: + # -- Create an IngressRoute for the dashboard +@@ -221,15 +214,7 @@ livenessProbe: + # -- The number of seconds to wait for a probe response before considering it as failed. + timeoutSeconds: 2 + +-# -- Define Startup Probe for container: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes +-# eg. +-# `startupProbe: +-# exec: +-# command: +-# - mycommand +-# - foo +-# initialDelaySeconds: 5 +-# periodSeconds: 5` ++# -- Define [Startup Probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes) + startupProbe: + + providers: +@@ -276,18 +261,8 @@ providers: + # -- Allows Traefik to automatically watch for file changes + watch: true + # -- File content (YAML format, go template supported) (see https://doc.traefik.io/traefik/providers/file/) +- content: "" +- # http: +- # routers: +- # router0: +- # entryPoints: +- # - web +- # middlewares: +- # - my-basic-auth +- # service: service-foo +- # rule: Path(`/foo`) ++ content: + +-# + # -- Add volumes to the traefik pod. The volume name will be passed to tpl. + # This can be used to mount a cert pair or a configmap that holds a config.toml file. + # After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: +@@ -311,26 +286,21 @@ additionalVolumeMounts: [] + + logs: + general: +- # -- By default, the logs use a text format (common), but you can +- # also ask for the json format in the format option +- # format: json ++ # -- Set [logs format](https://doc.traefik.io/traefik/observability/logs/#format) ++ # @default common ++ format: + # By default, the level is set to ERROR. + # -- Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. + level: INFO + access: + # -- To enable access logs + enabled: false +- ## By default, logs are written using the Common Log Format (CLF) on stdout. +- ## To write logs in JSON, use json in the format option. +- ## If the given format is unsupported, the default (CLF) is used instead. +- # format: json ++ # -- Set [access log format](https://doc.traefik.io/traefik/observability/access-logs/#format) ++ format: + # filePath: "/var/log/traefik/access.log +- ## To write the logs in an asynchronous fashion, specify a bufferingSize option. +- ## This option represents the number of log lines Traefik will keep in memory before writing +- ## them to the selected output. In some cases, this option can greatly help performances. +- # bufferingSize: 100 +- ## Filtering +- # -- https://docs.traefik.io/observability/access-logs/#filtering ++ # -- Set [bufferingSize](https://doc.traefik.io/traefik/observability/access-logs/#bufferingsize) ++ bufferingSize: ++ # -- Set [filtering](https://docs.traefik.io/observability/access-logs/#filtering) + filters: {} + # statuscodes: "200,300-302" + # retryattempts: true +@@ -345,15 +315,11 @@ logs: + names: {} + ## Examples: + # ClientUsername: drop ++ # -- [Limit logged fields or headers](https://doc.traefik.io/traefik/observability/access-logs/#limiting-the-fieldsincluding-headers) + headers: + # -- Available modes: keep, drop, redact. + defaultmode: drop +- # -- Names of the headers to limit. + names: {} +- ## Examples: +- # User-Agent: redact +- # Authorization: drop +- # Content-Type: keep + + metrics: + ## -- Enable metrics for internal resources. Default: false +@@ -567,16 +533,15 @@ globalArguments: + - "--global.checknewversion" + - "--global.sendanonymoususage" + +-# +-# Configure Traefik static configuration + # -- Additional arguments to be passed at Traefik's binary +-# All available options available on https://docs.traefik.io/reference/static-configuration/cli/ +-## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}"` ++# See [CLI Reference](https://docs.traefik.io/reference/static-configuration/cli/) ++# Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}"` + additionalArguments: [] + # - "--providers.kubernetesingress.ingressclass=traefik-internal" + # - "--log.level=DEBUG" + + # -- Environment variables to be passed to Traefik's binary ++# @default -- See _values.yaml_ + env: + - name: POD_NAME + valueFrom: +@@ -586,25 +551,9 @@ env: + valueFrom: + fieldRef: + fieldPath: metadata.namespace +-# - name: SOME_VAR +-# value: some-var-value +-# - name: SOME_VAR_FROM_CONFIG_MAP +-# valueFrom: +-# configMapRef: +-# name: configmap-name +-# key: config-key +-# - name: SOME_SECRET +-# valueFrom: +-# secretKeyRef: +-# name: secret-name +-# key: secret-key + + # -- Environment variables to be passed to Traefik's binary from configMaps or secrets + envFrom: [] +-# - configMapRef: +-# name: config-map-name +-# - secretRef: +-# name: secret-name + + ports: + traefik: +@@ -766,28 +715,12 @@ ports: + # -- The port protocol (TCP/UDP) + protocol: TCP + +-# -- TLS Options are created as TLSOption CRDs +-# https://doc.traefik.io/traefik/https/tls/#tls-options ++# -- TLS Options are created as [TLSOption CRDs](https://doc.traefik.io/traefik/https/tls/#tls-options) + # When using `labelSelector`, you'll need to set labels on tlsOption accordingly. +-# Example: +-# tlsOptions: +-# default: +-# labels: {} +-# sniStrict: true +-# custom-options: +-# labels: {} +-# curvePreferences: +-# - CurveP521 +-# - CurveP384 ++# See EXAMPLE.md for details. + tlsOptions: {} + +-# -- TLS Store are created as TLSStore CRDs. This is useful if you want to set a default certificate +-# https://doc.traefik.io/traefik/https/tls/#default-certificate +-# Example: +-# tlsStore: +-# default: +-# defaultCertificate: +-# secretName: tls-cert ++# -- TLS Store are created as [TLSStore CRDs](https://doc.traefik.io/traefik/https/tls/#default-certificate). This is useful if you want to set a default certificate. See EXAMPLE.md for details. + tlsStore: {} + + service: +@@ -839,29 +772,8 @@ service: + + autoscaling: + # -- Create HorizontalPodAutoscaler object. ++ # See EXAMPLES.md for more details. + enabled: false +-# minReplicas: 1 +-# maxReplicas: 10 +-# metrics: +-# - type: Resource +-# resource: +-# name: cpu +-# target: +-# type: Utilization +-# averageUtilization: 60 +-# - type: Resource +-# resource: +-# name: memory +-# target: +-# type: Utilization +-# averageUtilization: 60 +-# behavior: +-# scaleDown: +-# stabilizationWindowSeconds: 300 +-# policies: +-# - type: Pods +-# value: 1 +-# periodSeconds: 60 + + persistence: + # -- Enable persistence using Persistent Volume Claims +@@ -879,27 +791,10 @@ persistence: + # -- Only mount a subpath of the Volume into the pod + # subPath: "" + +-# -- Certificates resolvers configuration ++# -- Certificates resolvers configuration. ++# Ref: https://doc.traefik.io/traefik/https/acme/#certificate-resolvers ++# See EXAMPLES.md for more details. + certResolvers: {} +-# letsencrypt: +-# # for challenge options cf. https://doc.traefik.io/traefik/https/acme/ +-# email: email@example.com +-# dnsChallenge: +-# # also add the provider's required configuration under env +-# # or expand then from secrets/configmaps with envfrom +-# # cf. https://doc.traefik.io/traefik/https/acme/#providers +-# provider: digitalocean +-# # add futher options for the dns challenge as needed +-# # cf. https://doc.traefik.io/traefik/https/acme/#dnschallenge +-# delayBeforeCheck: 30 +-# resolvers: +-# - 1.1.1.1 +-# - 8.8.8.8 +-# tlsChallenge: true +-# httpChallenge: +-# entryPoint: "web" +-# # It has to match the path with a persistent volume +-# storage: /data/acme.json + + # -- If hostNetwork is true, runs traefik in the host network namespace + # To prevent unschedulabel pods due to port collisions, if hostNetwork=true +@@ -933,14 +828,8 @@ serviceAccount: + # -- Additional serviceAccount annotations (e.g. for oidc authentication) + serviceAccountAnnotations: {} + +-# -- The resources parameter defines CPU and memory requirements and limits for Traefik's containers. ++# -- [Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for `traefik` container. + resources: {} +-# requests: +-# cpu: "100m" +-# memory: "50Mi" +-# limits: +-# cpu: "300m" +-# memory: "150Mi" + + # -- This example pod anti-affinity forces the scheduler to put traefik pods + # -- on nodes where no other traefik pods are scheduled. +@@ -970,30 +859,22 @@ topologySpreadConstraints: [] + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: DoNotSchedule + +-# -- Pods can have priority. +-# -- Priority indicates the importance of a Pod relative to other Pods. ++# -- [Pod Priority and Preemption](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) + priorityClassName: "" + +-# -- Set the container security context +-# -- To run the container with ports below 1024 this will need to be adjusted to run as root ++# -- [SecurityContext](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1) ++# @default -- See _values.yaml_ + securityContext: ++ allowPrivilegeEscalation: false + capabilities: + drop: [ALL] + readOnlyRootFilesystem: true +- allowPrivilegeEscalation: false + ++# -- [Pod Security Context](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context) ++# @default -- See _values.yaml_ + podSecurityContext: +- # /!\ When setting fsGroup, Kubernetes will recursively change ownership and +- # permissions for the contents of each volume to match the fsGroup. This can +- # be an issue when storing sensitive content like TLS Certificates /!\ +- # fsGroup: 65532 +- # -- Specifies the policy for changing ownership and permissions of volume contents to match the fsGroup. +- fsGroupChangePolicy: "OnRootMismatch" +- # -- The ID of the group for all containers in the pod to run as. + runAsGroup: 65532 +- # -- Specifies whether the containers should run as a non-root user. + runAsNonRoot: true +- # -- The ID of the user for all containers in the pod to run as. + runAsUser: 65532 + + # +@@ -1003,16 +884,16 @@ podSecurityContext: + # See #595 for more details and traefik/tests/values/extra.yaml for example. + extraObjects: [] + +-# This will override the default Release Namespace for Helm. ++# -- This field override the default Release Namespace for Helm. + # It will not affect optional CRDs such as `ServiceMonitor` and `PrometheusRules` +-# namespaceOverride: traefik +-# +-## -- This will override the default app.kubernetes.io/instance label for all Objects. +-# instanceLabelOverride: traefik ++namespaceOverride: ++ ++## -- This field override the default app.kubernetes.io/instance label for all Objects. ++instanceLabelOverride: + +-# -- Traefik Hub configuration. See https://doc.traefik.io/traefik-hub/ ++# Traefik Hub configuration. See https://doc.traefik.io/traefik-hub/ + hub: +- # Name of Secret with key 'token' set to a valid license token. ++ # -- Name of `Secret` with key 'token' set to a valid license token. + # It enables API Gateway. + token: + apimanagement: +``` + +## 28.1.0 ![AppVersion: v3.0.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +* fix(Traefik Hub): do not deploy mutating webhook when enabling only API Gateway +* feat(Traefik Hub): use Traefik Proxy otlp config +* chore: 🔧 update Traefik Hub CRD to v1.3.3 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 70297f6..2fd9282 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1010,3 +1010,49 @@ + ## -- This will override the default app.kubernetes.io/instance label for all Objects. + # instanceLabelOverride: traefik + ++# -- Traefik Hub configuration. See https://doc.traefik.io/traefik-hub/ ++hub: ++ # Name of Secret with key 'token' set to a valid license token. ++ # It enables API Gateway. ++ token: ++ apimanagement: ++ # -- Set to true in order to enable API Management. Requires a valid license token. ++ enabled: ++ admission: ++ # -- WebHook admission server listen address. Default: "0.0.0.0:9943". ++ listenAddr: ++ # -- Certificate of the WebHook admission server. Default: "hub-agent-cert". ++ secretName: ++ ++ ratelimit: ++ redis: ++ # -- Enable Redis Cluster. Default: true. ++ cluster: ++ # -- Database used to store information. Default: "0". ++ database: ++ # -- Endpoints of the Redis instances to connect to. Default: "". ++ endpoints: ++ # -- The username to use when connecting to Redis endpoints. Default: "". ++ username: ++ # -- The password to use when connecting to Redis endpoints. Default: "". ++ password: ++ sentinel: ++ # -- Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". ++ masterset: ++ # -- Username to use for sentinel authentication (can be different from endpoint username). Default: "". ++ username: ++ # -- Password to use for sentinel authentication (can be different from endpoint password). Default: "". ++ password: ++ # -- Timeout applied on connection with redis. Default: "0s". ++ timeout: ++ tls: ++ # -- Path to the certificate authority used for the secured connection. ++ ca: ++ # -- Path to the public certificate used for the secure connection. ++ cert: ++ # -- Path to the private key used for the secure connection. ++ key: ++ # -- When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. ++ insecureSkipVerify: ++ # Enable export of errors logs to the platform. Default: true. ++ sendlogs: +``` + +## 28.1.0-beta.3 ![AppVersion: v3.0.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-05-03 + +* chore: 🔧 update Traefik Hub CRD to v1.3.2 +* chore(release): 🚀 publish v28.1.0-beta.3 + +## 28.1.0-beta.2 ![AppVersion: v3.0.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-05-02 + +* fix: 🐛 refine Traefik Hub support +* chore(release): 🚀 publish v28.1.0-beta.2 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ce0a7a3..70297f6 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1015,13 +1015,15 @@ hub: + # Name of Secret with key 'token' set to a valid license token. + # It enables API Gateway. + token: +- admission: +- # -- WebHook admission server listen address. Default: "0.0.0.0:9943". +- listenAddr: +- # -- Certificate of the WebHook admission server. Default: "hub-agent-cert". +- secretName: +- # -- Set to true in order to enable API Management. Requires a valid license token. + apimanagement: ++ # -- Set to true in order to enable API Management. Requires a valid license token. ++ enabled: ++ admission: ++ # -- WebHook admission server listen address. Default: "0.0.0.0:9943". ++ listenAddr: ++ # -- Certificate of the WebHook admission server. Default: "hub-agent-cert". ++ secretName: ++ + metrics: + opentelemetry: + # -- Set to true to enable OpenTelemetry metrics exporter of Traefik Hub. +``` + +## 28.1.0-beta.1 ![AppVersion: v3.0.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-04-30 + +* feat: :rocket: add initial support for Traefik Hub Api Gateway +* chore(release): 🚀 publish v28.1.0-beta.1 + +## 28.0.0 ![AppVersion: v3.0.0](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.0&color=success&logo=) ![Kubernetes: >=1.22.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.22.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-04-30 + +* style: 🎨 consistent capitalization on `--entryPoints` CLI flag +* fix: 🐛 only expose http3 port on service when TCP variant is exposed +* fix: 🐛 logs filters on status codes +* feat: ✨ add support of `experimental-v3.0` unstable version +* feat: ability to override liveness and readiness probe paths +* feat(ports): add transport options +* chore(release): publish v28.0.0 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index c0d72d8..2bff10d 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -38,6 +38,12 @@ deployment: + ## Override the liveness/readiness scheme. Useful for getting ping to + ## respond on websecure entryPoint. + # healthchecksScheme: HTTPS ++ ## Override the readiness path. ++ ## Default: /ping ++ # readinessPath: /ping ++ # Override the liveness path. ++ # Default: /ping ++ # livenessPath: /ping + # -- Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} + # -- Additional deployment labels (e.g. for filtering deployment by custom labels) +@@ -648,15 +654,28 @@ ports: + # (Optional) + # priority: 10 + # +- # Trust forwarded headers information (X-Forwarded-*). ++ # -- Trust forwarded headers information (X-Forwarded-*). + # forwardedHeaders: + # trustedIPs: [] + # insecure: false + # +- # Enable the Proxy Protocol header parsing for the entry point ++ # -- Enable the Proxy Protocol header parsing for the entry point + # proxyProtocol: + # trustedIPs: [] + # insecure: false ++ # ++ # -- Set transport settings for the entrypoint; see also ++ # https://doc.traefik.io/traefik/routing/entrypoints/#transport ++ transport: ++ respondingTimeouts: ++ readTimeout: ++ writeTimeout: ++ idleTimeout: ++ lifeCycle: ++ requestAcceptGraceTimeout: ++ graceTimeOut: ++ keepAliveMaxRequests: ++ keepAliveMaxTime: + websecure: + ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true +@@ -684,16 +703,29 @@ ports: + enabled: false + # advertisedPort: 4443 + # +- ## -- Trust forwarded headers information (X-Forwarded-*). ++ # -- Trust forwarded headers information (X-Forwarded-*). + # forwardedHeaders: + # trustedIPs: [] + # insecure: false + # +- ## -- Enable the Proxy Protocol header parsing for the entry point ++ # -- Enable the Proxy Protocol header parsing for the entry point + # proxyProtocol: + # trustedIPs: [] + # insecure: false + # ++ # -- Set transport settings for the entrypoint; see also ++ # https://doc.traefik.io/traefik/routing/entrypoints/#transport ++ transport: ++ respondingTimeouts: ++ readTimeout: ++ writeTimeout: ++ idleTimeout: ++ lifeCycle: ++ requestAcceptGraceTimeout: ++ graceTimeOut: ++ keepAliveMaxRequests: ++ keepAliveMaxTime: ++ # + ## Set TLS at the entrypoint + ## https://doc.traefik.io/traefik/routing/entrypoints/#tls + tls: +``` + +## 28.0.0-rc1 ![AppVersion: v3.0.0-rc5](https://img.shields.io/static/v1?label=AppVersion&message=v3.0.0-rc5&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-04-17 + +**Upgrade Notes** + +This is a major breaking upgrade. [Migration guide](https://doc.traefik.io/traefik/v3.0/migration/v2-to-v3/) have been applied on the chart. + +It needs a Kubernetes v1.22 or higher. +All CRDs using _API Group_ `traefik.containo.us` are not supported anymore in Traefik Proxy v3 + +CRDs needs to be upgraded: `kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik/crds/` + +After upgrade, CRDs with _API Group_ `traefik.containo.us` can be removed: + +```shell +kubectl delete crds \ + ingressroutes.traefik.containo.us \ + ingressroutetcps.traefik.containo.us \ + ingressrouteudps.traefik.containo.us \ + middlewares.traefik.containo.us \ + middlewaretcps.traefik.containo.us \ + serverstransports.traefik.containo.us \ + tlsoptions.traefik.containo.us \ + tlsstores.traefik.containo.us \ + traefikservices.traefik.containo.us +``` + +**Changes** + +* feat(podtemplate): set GOMEMLIMIT, GOMAXPROCS when limits are defined +* feat: ✨ fail gracefully when required port number is not set +* feat!: :boom: initial support of Traefik Proxy v3 +* docs: 📚️ improve EXAMPLES on acme resolver +* chore(release): 🚀 publish v28 rc1 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index cd9fb6e..c0d72d8 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -120,12 +120,13 @@ ingressClass: + isDefaultClass: true + # name: my-custom-class + ++core: ++ # -- Can be used to use globally v2 router syntax ++ # See https://doc.traefik.io/traefik/v3.0/migration/v2-to-v3/#new-v3-syntax-notable-changes ++ defaultRuleSyntax: ++ + # Traefik experimental features + experimental: +- # This value is no longer used, set the image.tag to a semver higher than 3.0, e.g. "v3.0.0-beta3" +- # v3: +- # -- Enable traefik version 3 +- + # -- Enable traefik experimental plugins + plugins: {} + # demo: +@@ -309,7 +310,7 @@ logs: + # format: json + # By default, the level is set to ERROR. + # -- Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. +- level: ERROR ++ level: INFO + access: + # -- To enable access logs + enabled: false +@@ -328,6 +329,8 @@ logs: + # statuscodes: "200,300-302" + # retryattempts: true + # minduration: 10ms ++ # -- Enables accessLogs for internal resources. Default: false. ++ addInternals: + fields: + general: + # -- Available modes: keep, drop, redact. +@@ -347,6 +350,9 @@ logs: + # Content-Type: keep + + metrics: ++ ## -- Enable metrics for internal resources. Default: false ++ addInternals: ++ + ## -- Prometheus is enabled by default. + ## -- It can be disabled by setting "prometheus: null" + prometheus: +@@ -376,31 +382,6 @@ metrics: + # # addRoutersLabels: true + # ## Enable metrics on services. Default=true + # # addServicesLabels: false +- # influxdb: +- # ## Address instructs exporter to send metrics to influxdb at this address. +- # address: localhost:8089 +- # ## InfluxDB's address protocol (udp or http). Default="udp" +- # protocol: udp +- # ## InfluxDB database used when protocol is http. Default="" +- # # database: "" +- # ## InfluxDB retention policy used when protocol is http. Default="" +- # # retentionPolicy: "" +- # ## InfluxDB username (only with http). Default="" +- # # username: "" +- # ## InfluxDB password (only with http). Default="" +- # # password: "" +- # ## The interval used by the exporter to push metrics to influxdb. Default=10s +- # # pushInterval: 30s +- # ## Additional labels (influxdb tags) on all metrics. +- # # additionalLabels: +- # # env: production +- # # foo: bar +- # ## Enable metrics on entry points. Default=true +- # # addEntryPointsLabels: false +- # ## Enable metrics on routers. Default=false +- # # addRoutersLabels: true +- # ## Enable metrics on services. Default=true +- # # addServicesLabels: false + # influxdb2: + # ## Address instructs exporter to send metrics to influxdb v2 at this address. + # address: localhost:8086 +@@ -435,43 +416,53 @@ metrics: + # # addRoutersLabels: true + # ## Enable metrics on services. Default=true + # # addServicesLabels: false +- # openTelemetry: +- # ## Address of the OpenTelemetry Collector to send metrics to. +- # address: "localhost:4318" +- # ## Enable metrics on entry points. +- # addEntryPointsLabels: true +- # ## Enable metrics on routers. +- # addRoutersLabels: true +- # ## Enable metrics on services. +- # addServicesLabels: true +- # ## Explicit boundaries for Histogram data points. +- # explicitBoundaries: +- # - "0.1" +- # - "0.3" +- # - "1.2" +- # - "5.0" +- # ## Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. +- # headers: +- # foo: bar +- # test: test +- # ## Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. +- # insecure: true +- # ## Interval at which metrics are sent to the OpenTelemetry Collector. +- # pushInterval: 10s +- # ## Allows to override the default URL path used for sending metrics. This option has no effect when using gRPC transport. +- # path: /foo/v1/traces +- # ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. +- # tls: +- # ## The path to the certificate authority, it defaults to the system bundle. +- # ca: path/to/ca.crt +- # ## The path to the public certificate. When using this option, setting the key option is required. +- # cert: path/to/foo.cert +- # ## The path to the private key. When using this option, setting the cert option is required. +- # key: path/to/key.key +- # ## If set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. +- # insecureSkipVerify: true +- # ## This instructs the reporter to send metrics to the OpenTelemetry Collector using gRPC. +- # grpc: true ++ otlp: ++ # -- Set to true in order to enable the OpenTelemetry metrics ++ enabled: false ++ # -- Enable metrics on entry points. Default: true ++ addEntryPointsLabels: ++ # -- Enable metrics on routers. Default: false ++ addRoutersLabels: ++ # -- Enable metrics on services. Default: true ++ addServicesLabels: ++ # -- Explicit boundaries for Histogram data points. Default: [.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10] ++ explicitBoundaries: ++ # -- Interval at which metrics are sent to the OpenTelemetry Collector. Default: 10s ++ pushInterval: ++ http: ++ # -- Set to true in order to send metrics to the OpenTelemetry Collector using HTTP. ++ enabled: false ++ # -- Format: ://:. Default: http://localhost:4318/v1/metrics ++ endpoint: ++ # -- Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. ++ headers: ++ ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. ++ tls: ++ # -- The path to the certificate authority, it defaults to the system bundle. ++ ca: ++ # -- The path to the public certificate. When using this option, setting the key option is required. ++ cert: ++ # -- The path to the private key. When using this option, setting the cert option is required. ++ key: ++ # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. ++ insecureSkipVerify: ++ grpc: ++ # -- Set to true in order to send metrics to the OpenTelemetry Collector using gRPC ++ enabled: false ++ # -- Format: ://:. Default: http://localhost:4318/v1/metrics ++ endpoint: ++ # -- Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. ++ insecure: ++ ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. ++ tls: ++ # -- The path to the certificate authority, it defaults to the system bundle. ++ ca: ++ # -- The path to the public certificate. When using this option, setting the key option is required. ++ cert: ++ # -- The path to the private key. When using this option, setting the cert option is required. ++ key: ++ # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. ++ insecureSkipVerify: + + ## -- enable optional CRDs for Prometheus Operator + ## +@@ -524,51 +515,46 @@ metrics: + + ## Tracing + # -- https://doc.traefik.io/traefik/observability/tracing/overview/ +-tracing: {} +-# openTelemetry: # traefik v3+ only +-# grpc: true +-# insecure: true +-# address: localhost:4317 +-# instana: +-# localAgentHost: 127.0.0.1 +-# localAgentPort: 42699 +-# logLevel: info +-# enableAutoProfile: true +-# datadog: +-# localAgentHostPort: 127.0.0.1:8126 +-# debug: false +-# globalTag: "" +-# prioritySampling: false +-# jaeger: +-# samplingServerURL: http://localhost:5778/sampling +-# samplingType: const +-# samplingParam: 1.0 +-# localAgentHostPort: 127.0.0.1:6831 +-# gen128Bit: false +-# propagation: jaeger +-# traceContextHeaderName: uber-trace-id +-# disableAttemptReconnecting: true +-# collector: +-# endpoint: "" +-# user: "" +-# password: "" +-# zipkin: +-# httpEndpoint: http://localhost:9411/api/v2/spans +-# sameSpan: false +-# id128Bit: true +-# sampleRate: 1.0 +-# haystack: +-# localAgentHost: 127.0.0.1 +-# localAgentPort: 35000 +-# globalTag: "" +-# traceIDHeaderName: "" +-# parentIDHeaderName: "" +-# spanIDHeaderName: "" +-# baggagePrefixHeaderName: "" +-# elastic: +-# serverURL: http://localhost:8200 +-# secretToken: "" +-# serviceEnvironment: "" ++tracing: ++ # -- Enables tracing for internal resources. Default: false. ++ addInternals: ++ otlp: ++ # -- See https://doc.traefik.io/traefik/v3.0/observability/tracing/opentelemetry/ ++ enabled: false ++ http: ++ # -- Set to true in order to send metrics to the OpenTelemetry Collector using HTTP. ++ enabled: false ++ # -- Format: ://:. Default: http://localhost:4318/v1/metrics ++ endpoint: ++ # -- Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. ++ headers: ++ ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. ++ tls: ++ # -- The path to the certificate authority, it defaults to the system bundle. ++ ca: ++ # -- The path to the public certificate. When using this option, setting the key option is required. ++ cert: ++ # -- The path to the private key. When using this option, setting the cert option is required. ++ key: ++ # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. ++ insecureSkipVerify: ++ grpc: ++ # -- Set to true in order to send metrics to the OpenTelemetry Collector using gRPC ++ enabled: false ++ # -- Format: ://:. Default: http://localhost:4318/v1/metrics ++ endpoint: ++ # -- Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. ++ insecure: ++ ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. ++ tls: ++ # -- The path to the certificate authority, it defaults to the system bundle. ++ ca: ++ # -- The path to the public certificate. When using this option, setting the key option is required. ++ cert: ++ # -- The path to the private key. When using this option, setting the cert option is required. ++ key: ++ # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. ++ insecureSkipVerify: + + # -- Global command arguments to be passed to all traefik's pods + globalArguments: +@@ -756,7 +742,6 @@ ports: + # default: + # labels: {} + # sniStrict: true +-# preferServerCipherSuites: true + # custom-options: + # labels: {} + # curvePreferences: +``` + +## 27.0.0 ![AppVersion: v2.11.0](https://img.shields.io/static/v1?label=AppVersion&message=v2.11.0&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-04-02 + +**Upgrade notes** + +Custom services and port exposure have been redesigned, requiring the following changes: +- if you were overriding port exposure behavior using the `expose` or `exposeInternal` flags, you should replace them with a service name to boolean mapping, i.e. replace this: + +```yaml +ports: + web: + expose: false + exposeInternal: true +``` + +with this: + +```yaml +ports: + web: + expose: + default: false + internal: true +``` + +- if you were previously using the `service.internal` value, you should migrate the values to the `service.additionalServices.internal` value instead; this should yield the same results, but make sure to carefully check for any changes! + +**Changes** + +* fix: remove null annotations on dashboard `IngressRoute` +* fix(rbac): do not create clusterrole for namespace deployment on Traefik v3 +* feat: restrict access to secrets +* feat!: :boom: refactor custom services and port exposure +* chore(release): 🚀 publish v27.0.0 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index dbd078f..363871d 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -250,6 +250,9 @@ providers: + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] + # - "default" ++ # Disable cluster IngressClass Lookup - Requires Traefik V3. ++ # When combined with rbac.namespaced: true, ClusterRole will not be created and ingresses must use kubernetes.io/ingress.class annotation instead of spec.ingressClassName. ++ disableIngressClassLookup: false + # IP used for Kubernetes Ingress endpoints + publishedService: + enabled: false +@@ -626,22 +629,20 @@ ports: + # -- You SHOULD NOT expose the traefik port on production deployments. + # If you want to access it from outside your cluster, + # use `kubectl port-forward` or create a secure ingress +- expose: false ++ expose: ++ default: false + # -- The exposed port for this service + exposedPort: 9000 + # -- The port protocol (TCP/UDP) + protocol: TCP +- # -- Defines whether the port is exposed on the internal service; +- # note that ports exposed on the default service are exposed on the internal +- # service by default as well. +- exposeInternal: false + web: + ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8000 + # hostPort: 8000 + # containerPort: 8000 +- expose: true ++ expose: ++ default: true + exposedPort: 80 + ## -- Different target traefik port on the cluster, useful for IP type LB + # targetPort: 80 +@@ -650,10 +651,6 @@ ports: + # -- Use nodeport if set. This is useful if you have configured Traefik in a + # LoadBalancer. + # nodePort: 32080 +- # -- Defines whether the port is exposed on the internal service; +- # note that ports exposed on the default service are exposed on the internal +- # service by default as well. +- exposeInternal: false + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection +@@ -677,17 +674,14 @@ ports: + port: 8443 + # hostPort: 8443 + # containerPort: 8443 +- expose: true ++ expose: ++ default: true + exposedPort: 443 + ## -- Different target traefik port on the cluster, useful for IP type LB + # targetPort: 80 + ## -- The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 +- # -- Defines whether the port is exposed on the internal service; +- # note that ports exposed on the default service are exposed on the internal +- # service by default as well. +- exposeInternal: false + ## -- Specify an application protocol. This may be used as a hint for a Layer 7 load balancer. + # appProtocol: https + # +@@ -744,15 +738,12 @@ ports: + # -- You may not want to expose the metrics port on production deployments. + # If you want to access it from outside your cluster, + # use `kubectl port-forward` or create a secure ingress +- expose: false ++ expose: ++ default: false + # -- The exposed port for this service + exposedPort: 9100 + # -- The port protocol (TCP/UDP) + protocol: TCP +- # -- Defines whether the port is exposed on the internal service; +- # note that ports exposed on the default service are exposed on the internal +- # service by default as well. +- exposeInternal: false + + # -- TLS Options are created as TLSOption CRDs + # https://doc.traefik.io/traefik/https/tls/#tls-options +@@ -814,6 +805,7 @@ service: + # - IPv4 + # - IPv6 + ## ++ additionalServices: {} + ## -- An additional and optional internal Service. + ## Same parameters as external Service + # internal: +@@ -899,11 +891,14 @@ hostNetwork: false + rbac: + enabled: true + # If set to false, installs ClusterRole and ClusterRoleBinding so Traefik can be used across namespaces. +- # If set to true, installs Role and RoleBinding. Providers will only watch target namespace. ++ # If set to true, installs Role and RoleBinding instead of ClusterRole/ClusterRoleBinding. Providers will only watch target namespace. ++ # When combined with providers.kubernetesIngress.disableIngressClassLookup: true and Traefik V3, ClusterRole to watch IngressClass is also disabled. + namespaced: false + # Enable user-facing roles + # https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + # aggregateTo: [ "admin" ] ++ # List of Kubernetes secrets that are accessible for Traefik. If empty, then access is granted to every secret. ++ secretResourceNames: [] + + # -- Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding + podSecurityPolicy: +``` + +## 26.1.0 ![AppVersion: v2.11.0](https://img.shields.io/static/v1?label=AppVersion&message=v2.11.0&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2024-02-19 + +* fix: 🐛 set runtimeClassName at pod level +* fix: 🐛 missing quote on experimental plugin args +* fix: update traefik v3 serverstransporttcps CRD +* feat: set runtimeClassName on pod spec +* feat: create v1 Gateway and GatewayClass Version for Traefik v3 +* feat: allow exposure of ports on internal service only +* doc: fix invalid suggestion on TLSOption (#996) +* chore: 🔧 update maintainers +* chore: 🔧 promote jnoordsij to Traefik Helm Chart maintainer +* chore(release): 🚀 publish v26.1.0 +* chore(deps): update traefik docker tag to v2.11.0 +* chore(deps): update traefik docker tag to v2.10.7 +* chore(crds): update definitions for traefik v2.11 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index f9dac91..dbd078f 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -100,6 +100,8 @@ deployment: + # port: 9000 + # host: localhost + # scheme: HTTP ++ # -- Set a runtimeClassName on pod ++ runtimeClassName: + + # -- Pod disruption budget + podDisruptionBudget: +@@ -629,6 +631,10 @@ ports: + exposedPort: 9000 + # -- The port protocol (TCP/UDP) + protocol: TCP ++ # -- Defines whether the port is exposed on the internal service; ++ # note that ports exposed on the default service are exposed on the internal ++ # service by default as well. ++ exposeInternal: false + web: + ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true +@@ -644,6 +650,10 @@ ports: + # -- Use nodeport if set. This is useful if you have configured Traefik in a + # LoadBalancer. + # nodePort: 32080 ++ # -- Defines whether the port is exposed on the internal service; ++ # note that ports exposed on the default service are exposed on the internal ++ # service by default as well. ++ exposeInternal: false + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection +@@ -674,6 +684,10 @@ ports: + ## -- The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 ++ # -- Defines whether the port is exposed on the internal service; ++ # note that ports exposed on the default service are exposed on the internal ++ # service by default as well. ++ exposeInternal: false + ## -- Specify an application protocol. This may be used as a hint for a Layer 7 load balancer. + # appProtocol: https + # +@@ -735,6 +749,10 @@ ports: + exposedPort: 9100 + # -- The port protocol (TCP/UDP) + protocol: TCP ++ # -- Defines whether the port is exposed on the internal service; ++ # note that ports exposed on the default service are exposed on the internal ++ # service by default as well. ++ exposeInternal: false + + # -- TLS Options are created as TLSOption CRDs + # https://doc.traefik.io/traefik/https/tls/#tls-options +@@ -745,7 +763,7 @@ ports: + # labels: {} + # sniStrict: true + # preferServerCipherSuites: true +-# customOptions: ++# custom-options: + # labels: {} + # curvePreferences: + # - CurveP521 +@@ -796,7 +814,7 @@ service: + # - IPv4 + # - IPv6 + ## +- ## -- An additionnal and optional internal Service. ++ ## -- An additional and optional internal Service. + ## Same parameters as external Service + # internal: + # type: ClusterIP +``` + +## 26.0.0 ![AppVersion: v2.10.6](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.6&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-12-05 + +* fix: 🐛 improve confusing suggested value on openTelemetry.grpc +* fix: 🐛 declare http3 udp port, with or without hostport +* feat: 💥 deployment.podannotations support interpolation with tpl +* feat: allow update of namespace policy for websecure listener +* feat: allow defining startupProbe +* feat: add file provider +* feat: :boom: unify plugin import between traefik and this chart +* chore(release): 🚀 publish v26 +* chore(deps): update traefik docker tag to v2.10.6 +* Release namespace for Prometheus Operator resources + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 71e377e..f9dac91 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -40,6 +40,7 @@ deployment: + # -- Additional deployment labels (e.g. for filtering deployment by custom labels) + labels: {} + # -- Additional pod annotations (e.g. for mesh injection or prometheus scraping) ++ # It supports templating. One can set it with values like traefik/name: '{{ template "traefik.name" . }}' + podAnnotations: {} + # -- Additional Pod labels (e.g. for filtering Pod by custom labels) + podLabels: {} +@@ -119,10 +120,12 @@ experimental: + # This value is no longer used, set the image.tag to a semver higher than 3.0, e.g. "v3.0.0-beta3" + # v3: + # -- Enable traefik version 3 +- # enabled: false +- plugins: +- # -- Enable traefik experimental plugins +- enabled: false ++ ++ # -- Enable traefik experimental plugins ++ plugins: {} ++ # demo: ++ # moduleName: github.com/traefik/plugindemo ++ # version: v0.2.1 + kubernetesGateway: + # -- Enable traefik experimental GatewayClass CRD + enabled: false +@@ -206,6 +209,17 @@ livenessProbe: + # -- The number of seconds to wait for a probe response before considering it as failed. + timeoutSeconds: 2 + ++# -- Define Startup Probe for container: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes ++# eg. ++# `startupProbe: ++# exec: ++# command: ++# - mycommand ++# - foo ++# initialDelaySeconds: 5 ++# periodSeconds: 5` ++startupProbe: ++ + providers: + kubernetesCRD: + # -- Load Kubernetes IngressRoute provider +@@ -241,6 +255,23 @@ providers: + # By default this Traefik service + # pathOverride: "" + ++ file: ++ # -- Create a file provider ++ enabled: false ++ # -- Allows Traefik to automatically watch for file changes ++ watch: true ++ # -- File content (YAML format, go template supported) (see https://doc.traefik.io/traefik/providers/file/) ++ content: "" ++ # http: ++ # routers: ++ # router0: ++ # entryPoints: ++ # - web ++ # middlewares: ++ # - my-basic-auth ++ # service: service-foo ++ # rule: Path(`/foo`) ++ + # + # -- Add volumes to the traefik pod. The volume name will be passed to tpl. + # This can be used to mount a cert pair or a configmap that holds a config.toml file. +@@ -487,7 +518,7 @@ metrics: + # -- https://doc.traefik.io/traefik/observability/tracing/overview/ + tracing: {} + # openTelemetry: # traefik v3+ only +-# grpc: {} ++# grpc: true + # insecure: true + # address: localhost:4317 + # instana: +``` + +## 25.0.0 ![AppVersion: v2.10.5](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.5&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-10-23 + +* revert: "fix: 🐛 remove old CRDs using traefik.containo.us" +* fix: 🐛 remove old CRDs using traefik.containo.us +* fix: disable ClusterRole and ClusterRoleBinding when not needed +* fix: detect correctly v3 version when using sha in `image.tag` +* fix: allow updateStrategy.rollingUpdate.maxUnavailable to be passed in as an int or string +* fix: add missing separator in crds +* fix: add Prometheus scraping annotations only if serviceMonitor not created +* feat: ✨ add healthcheck ingressRoute +* feat: :boom: support http redirections and http challenges with cert-manager +* feat: :boom: rework and allow update of namespace policy for Gateway +* docs: Fix typo in the default values file +* chore: remove label whitespace at TLSOption +* chore(release): publish v25.0.0 +* chore(deps): update traefik docker tag to v2.10.5 +* chore(deps): update docker.io/helmunittest/helm-unittest docker tag to v3.12.3 +* chore(ci): 🔧 👷 add e2e test when releasing + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index aeec85c..71e377e 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -45,60 +45,60 @@ deployment: + podLabels: {} + # -- Additional containers (e.g. for metric offloading sidecars) + additionalContainers: [] +- # https://docs.datadoghq.com/developers/dogstatsd/unix_socket/?tab=host +- # - name: socat-proxy +- # image: alpine/socat:1.0.5 +- # args: ["-s", "-u", "udp-recv:8125", "unix-sendto:/socket/socket"] +- # volumeMounts: +- # - name: dsdsocket +- # mountPath: /socket ++ # https://docs.datadoghq.com/developers/dogstatsd/unix_socket/?tab=host ++ # - name: socat-proxy ++ # image: alpine/socat:1.0.5 ++ # args: ["-s", "-u", "udp-recv:8125", "unix-sendto:/socket/socket"] ++ # volumeMounts: ++ # - name: dsdsocket ++ # mountPath: /socket + # -- Additional volumes available for use with initContainers and additionalContainers + additionalVolumes: [] +- # - name: dsdsocket +- # hostPath: +- # path: /var/run/statsd-exporter ++ # - name: dsdsocket ++ # hostPath: ++ # path: /var/run/statsd-exporter + # -- Additional initContainers (e.g. for setting file permission as shown below) + initContainers: [] +- # The "volume-permissions" init container is required if you run into permission issues. +- # Related issue: https://github.com/traefik/traefik-helm-chart/issues/396 +- # - name: volume-permissions +- # image: busybox:latest +- # command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"] +- # securityContext: +- # runAsNonRoot: true +- # runAsGroup: 65532 +- # runAsUser: 65532 +- # volumeMounts: +- # - name: data +- # mountPath: /data ++ # The "volume-permissions" init container is required if you run into permission issues. ++ # Related issue: https://github.com/traefik/traefik-helm-chart/issues/396 ++ # - name: volume-permissions ++ # image: busybox:latest ++ # command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"] ++ # securityContext: ++ # runAsNonRoot: true ++ # runAsGroup: 65532 ++ # runAsUser: 65532 ++ # volumeMounts: ++ # - name: data ++ # mountPath: /data + # -- Use process namespace sharing + shareProcessNamespace: false + # -- Custom pod DNS policy. Apply if `hostNetwork: true` + # dnsPolicy: ClusterFirstWithHostNet + dnsConfig: {} +- # nameservers: +- # - 192.0.2.1 # this is an example +- # searches: +- # - ns1.svc.cluster-domain.example +- # - my.dns.search.suffix +- # options: +- # - name: ndots +- # value: "2" +- # - name: edns0 ++ # nameservers: ++ # - 192.0.2.1 # this is an example ++ # searches: ++ # - ns1.svc.cluster-domain.example ++ # - my.dns.search.suffix ++ # options: ++ # - name: ndots ++ # value: "2" ++ # - name: edns0 + # -- Additional imagePullSecrets + imagePullSecrets: [] +- # - name: myRegistryKeySecretName ++ # - name: myRegistryKeySecretName + # -- Pod lifecycle actions + lifecycle: {} +- # preStop: +- # exec: +- # command: ["/bin/sh", "-c", "sleep 40"] +- # postStart: +- # httpGet: +- # path: /ping +- # port: 9000 +- # host: localhost +- # scheme: HTTP ++ # preStop: ++ # exec: ++ # command: ["/bin/sh", "-c", "sleep 40"] ++ # postStart: ++ # httpGet: ++ # path: /ping ++ # port: 9000 ++ # host: localhost ++ # scheme: HTTP + + # -- Pod disruption budget + podDisruptionBudget: +@@ -116,9 +116,9 @@ ingressClass: + + # Traefik experimental features + experimental: +- #This value is no longer used, set the image.tag to a semver higher than 3.0, e.g. "v3.0.0-beta3" +- #v3: +- # -- Enable traefik version 3 ++ # This value is no longer used, set the image.tag to a semver higher than 3.0, e.g. "v3.0.0-beta3" ++ # v3: ++ # -- Enable traefik version 3 + # enabled: false + plugins: + # -- Enable traefik experimental plugins +@@ -126,9 +126,9 @@ experimental: + kubernetesGateway: + # -- Enable traefik experimental GatewayClass CRD + enabled: false +- gateway: +- # -- Enable traefik regular kubernetes gateway +- enabled: true ++ ## Routes are restricted to namespace of the gateway by default. ++ ## https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.FromNamespaces ++ # namespacePolicy: All + # certificate: + # group: "core" + # kind: "Secret" +@@ -159,6 +159,22 @@ ingressRoute: + middlewares: [] + # -- TLS options (e.g. secret containing certificate) + tls: {} ++ healthcheck: ++ # -- Create an IngressRoute for the healthcheck probe ++ enabled: false ++ # -- Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) ++ annotations: {} ++ # -- Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) ++ labels: {} ++ # -- The router match rule used for the healthcheck ingressRoute ++ matchRule: PathPrefix(`/ping`) ++ # -- Specify the allowed entrypoints to use for the healthcheck ingress route, (e.g. traefik, web, websecure). ++ # By default, it's using traefik entrypoint, which is not exposed. ++ entryPoints: ["traefik"] ++ # -- Additional ingressRoute middlewares (e.g. for authentication) ++ middlewares: [] ++ # -- TLS options (e.g. secret containing certificate) ++ tls: {} + + updateStrategy: + # -- Customize updateStrategy: RollingUpdate or OnDelete +@@ -204,10 +220,10 @@ providers: + # labelSelector: environment=production,method=traefik + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] +- # - "default" ++ # - "default" + + kubernetesIngress: +- # -- Load Kubernetes IngressRoute provider ++ # -- Load Kubernetes Ingress provider + enabled: true + # -- Allows to reference ExternalName services in Ingress + allowExternalNameServices: false +@@ -217,7 +233,7 @@ providers: + # labelSelector: environment=production,method=traefik + # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] +- # - "default" ++ # - "default" + # IP used for Kubernetes Ingress endpoints + publishedService: + enabled: false +@@ -243,9 +259,9 @@ volumes: [] + + # -- Additional volumeMounts to add to the Traefik container + additionalVolumeMounts: [] +- # -- For instance when using a logshipper for access logs +- # - name: traefik-logs +- # mountPath: /var/log/traefik ++# -- For instance when using a logshipper for access logs ++# - name: traefik-logs ++# mountPath: /var/log/traefik + + logs: + general: +@@ -270,26 +286,26 @@ logs: + ## Filtering + # -- https://docs.traefik.io/observability/access-logs/#filtering + filters: {} +- # statuscodes: "200,300-302" +- # retryattempts: true +- # minduration: 10ms ++ # statuscodes: "200,300-302" ++ # retryattempts: true ++ # minduration: 10ms + fields: + general: + # -- Available modes: keep, drop, redact. + defaultmode: keep + # -- Names of the fields to limit. + names: {} +- ## Examples: +- # ClientUsername: drop ++ ## Examples: ++ # ClientUsername: drop + headers: + # -- Available modes: keep, drop, redact. + defaultmode: drop + # -- Names of the headers to limit. + names: {} +- ## Examples: +- # User-Agent: redact +- # Authorization: drop +- # Content-Type: keep ++ ## Examples: ++ # User-Agent: redact ++ # Authorization: drop ++ # Content-Type: keep + + metrics: + ## -- Prometheus is enabled by default. +@@ -308,118 +324,118 @@ metrics: + ## When manualRouting is true, it disables the default internal router in + ## order to allow creating a custom router for prometheus@internal service. + # manualRouting: true +-# datadog: +-# ## Address instructs exporter to send metrics to datadog-agent at this address. +-# address: "127.0.0.1:8125" +-# ## The interval used by the exporter to push metrics to datadog-agent. Default=10s +-# # pushInterval: 30s +-# ## The prefix to use for metrics collection. Default="traefik" +-# # prefix: traefik +-# ## Enable metrics on entry points. Default=true +-# # addEntryPointsLabels: false +-# ## Enable metrics on routers. Default=false +-# # addRoutersLabels: true +-# ## Enable metrics on services. Default=true +-# # addServicesLabels: false +-# influxdb: +-# ## Address instructs exporter to send metrics to influxdb at this address. +-# address: localhost:8089 +-# ## InfluxDB's address protocol (udp or http). Default="udp" +-# protocol: udp +-# ## InfluxDB database used when protocol is http. Default="" +-# # database: "" +-# ## InfluxDB retention policy used when protocol is http. Default="" +-# # retentionPolicy: "" +-# ## InfluxDB username (only with http). Default="" +-# # username: "" +-# ## InfluxDB password (only with http). Default="" +-# # password: "" +-# ## The interval used by the exporter to push metrics to influxdb. Default=10s +-# # pushInterval: 30s +-# ## Additional labels (influxdb tags) on all metrics. +-# # additionalLabels: +-# # env: production +-# # foo: bar +-# ## Enable metrics on entry points. Default=true +-# # addEntryPointsLabels: false +-# ## Enable metrics on routers. Default=false +-# # addRoutersLabels: true +-# ## Enable metrics on services. Default=true +-# # addServicesLabels: false +-# influxdb2: +-# ## Address instructs exporter to send metrics to influxdb v2 at this address. +-# address: localhost:8086 +-# ## Token with which to connect to InfluxDB v2. +-# token: xxx +-# ## Organisation where metrics will be stored. +-# org: "" +-# ## Bucket where metrics will be stored. +-# bucket: "" +-# ## The interval used by the exporter to push metrics to influxdb. Default=10s +-# # pushInterval: 30s +-# ## Additional labels (influxdb tags) on all metrics. +-# # additionalLabels: +-# # env: production +-# # foo: bar +-# ## Enable metrics on entry points. Default=true +-# # addEntryPointsLabels: false +-# ## Enable metrics on routers. Default=false +-# # addRoutersLabels: true +-# ## Enable metrics on services. Default=true +-# # addServicesLabels: false +-# statsd: +-# ## Address instructs exporter to send metrics to statsd at this address. +-# address: localhost:8125 +-# ## The interval used by the exporter to push metrics to influxdb. Default=10s +-# # pushInterval: 30s +-# ## The prefix to use for metrics collection. Default="traefik" +-# # prefix: traefik +-# ## Enable metrics on entry points. Default=true +-# # addEntryPointsLabels: false +-# ## Enable metrics on routers. Default=false +-# # addRoutersLabels: true +-# ## Enable metrics on services. Default=true +-# # addServicesLabels: false +-# openTelemetry: +-# ## Address of the OpenTelemetry Collector to send metrics to. +-# address: "localhost:4318" +-# ## Enable metrics on entry points. +-# addEntryPointsLabels: true +-# ## Enable metrics on routers. +-# addRoutersLabels: true +-# ## Enable metrics on services. +-# addServicesLabels: true +-# ## Explicit boundaries for Histogram data points. +-# explicitBoundaries: +-# - "0.1" +-# - "0.3" +-# - "1.2" +-# - "5.0" +-# ## Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. +-# headers: +-# foo: bar +-# test: test +-# ## Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. +-# insecure: true +-# ## Interval at which metrics are sent to the OpenTelemetry Collector. +-# pushInterval: 10s +-# ## Allows to override the default URL path used for sending metrics. This option has no effect when using gRPC transport. +-# path: /foo/v1/traces +-# ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. +-# tls: +-# ## The path to the certificate authority, it defaults to the system bundle. +-# ca: path/to/ca.crt +-# ## The path to the public certificate. When using this option, setting the key option is required. +-# cert: path/to/foo.cert +-# ## The path to the private key. When using this option, setting the cert option is required. +-# key: path/to/key.key +-# ## If set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. +-# insecureSkipVerify: true +-# ## This instructs the reporter to send metrics to the OpenTelemetry Collector using gRPC. +-# grpc: true +- +-## -- enable optional CRDs for Prometheus Operator +-## ++ # datadog: ++ # ## Address instructs exporter to send metrics to datadog-agent at this address. ++ # address: "127.0.0.1:8125" ++ # ## The interval used by the exporter to push metrics to datadog-agent. Default=10s ++ # # pushInterval: 30s ++ # ## The prefix to use for metrics collection. Default="traefik" ++ # # prefix: traefik ++ # ## Enable metrics on entry points. Default=true ++ # # addEntryPointsLabels: false ++ # ## Enable metrics on routers. Default=false ++ # # addRoutersLabels: true ++ # ## Enable metrics on services. Default=true ++ # # addServicesLabels: false ++ # influxdb: ++ # ## Address instructs exporter to send metrics to influxdb at this address. ++ # address: localhost:8089 ++ # ## InfluxDB's address protocol (udp or http). Default="udp" ++ # protocol: udp ++ # ## InfluxDB database used when protocol is http. Default="" ++ # # database: "" ++ # ## InfluxDB retention policy used when protocol is http. Default="" ++ # # retentionPolicy: "" ++ # ## InfluxDB username (only with http). Default="" ++ # # username: "" ++ # ## InfluxDB password (only with http). Default="" ++ # # password: "" ++ # ## The interval used by the exporter to push metrics to influxdb. Default=10s ++ # # pushInterval: 30s ++ # ## Additional labels (influxdb tags) on all metrics. ++ # # additionalLabels: ++ # # env: production ++ # # foo: bar ++ # ## Enable metrics on entry points. Default=true ++ # # addEntryPointsLabels: false ++ # ## Enable metrics on routers. Default=false ++ # # addRoutersLabels: true ++ # ## Enable metrics on services. Default=true ++ # # addServicesLabels: false ++ # influxdb2: ++ # ## Address instructs exporter to send metrics to influxdb v2 at this address. ++ # address: localhost:8086 ++ # ## Token with which to connect to InfluxDB v2. ++ # token: xxx ++ # ## Organisation where metrics will be stored. ++ # org: "" ++ # ## Bucket where metrics will be stored. ++ # bucket: "" ++ # ## The interval used by the exporter to push metrics to influxdb. Default=10s ++ # # pushInterval: 30s ++ # ## Additional labels (influxdb tags) on all metrics. ++ # # additionalLabels: ++ # # env: production ++ # # foo: bar ++ # ## Enable metrics on entry points. Default=true ++ # # addEntryPointsLabels: false ++ # ## Enable metrics on routers. Default=false ++ # # addRoutersLabels: true ++ # ## Enable metrics on services. Default=true ++ # # addServicesLabels: false ++ # statsd: ++ # ## Address instructs exporter to send metrics to statsd at this address. ++ # address: localhost:8125 ++ # ## The interval used by the exporter to push metrics to influxdb. Default=10s ++ # # pushInterval: 30s ++ # ## The prefix to use for metrics collection. Default="traefik" ++ # # prefix: traefik ++ # ## Enable metrics on entry points. Default=true ++ # # addEntryPointsLabels: false ++ # ## Enable metrics on routers. Default=false ++ # # addRoutersLabels: true ++ # ## Enable metrics on services. Default=true ++ # # addServicesLabels: false ++ # openTelemetry: ++ # ## Address of the OpenTelemetry Collector to send metrics to. ++ # address: "localhost:4318" ++ # ## Enable metrics on entry points. ++ # addEntryPointsLabels: true ++ # ## Enable metrics on routers. ++ # addRoutersLabels: true ++ # ## Enable metrics on services. ++ # addServicesLabels: true ++ # ## Explicit boundaries for Histogram data points. ++ # explicitBoundaries: ++ # - "0.1" ++ # - "0.3" ++ # - "1.2" ++ # - "5.0" ++ # ## Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. ++ # headers: ++ # foo: bar ++ # test: test ++ # ## Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. ++ # insecure: true ++ # ## Interval at which metrics are sent to the OpenTelemetry Collector. ++ # pushInterval: 10s ++ # ## Allows to override the default URL path used for sending metrics. This option has no effect when using gRPC transport. ++ # path: /foo/v1/traces ++ # ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. ++ # tls: ++ # ## The path to the certificate authority, it defaults to the system bundle. ++ # ca: path/to/ca.crt ++ # ## The path to the public certificate. When using this option, setting the key option is required. ++ # cert: path/to/foo.cert ++ # ## The path to the private key. When using this option, setting the cert option is required. ++ # key: path/to/key.key ++ # ## If set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. ++ # insecureSkipVerify: true ++ # ## This instructs the reporter to send metrics to the OpenTelemetry Collector using gRPC. ++ # grpc: true ++ ++ ## -- enable optional CRDs for Prometheus Operator ++ ## + ## Create a dedicated metrics service for use with ServiceMonitor + # service: + # enabled: false +@@ -470,55 +486,55 @@ metrics: + ## Tracing + # -- https://doc.traefik.io/traefik/observability/tracing/overview/ + tracing: {} +- # openTelemetry: # traefik v3+ only +- # grpc: {} +- # insecure: true +- # address: localhost:4317 +- # instana: +- # localAgentHost: 127.0.0.1 +- # localAgentPort: 42699 +- # logLevel: info +- # enableAutoProfile: true +- # datadog: +- # localAgentHostPort: 127.0.0.1:8126 +- # debug: false +- # globalTag: "" +- # prioritySampling: false +- # jaeger: +- # samplingServerURL: http://localhost:5778/sampling +- # samplingType: const +- # samplingParam: 1.0 +- # localAgentHostPort: 127.0.0.1:6831 +- # gen128Bit: false +- # propagation: jaeger +- # traceContextHeaderName: uber-trace-id +- # disableAttemptReconnecting: true +- # collector: +- # endpoint: "" +- # user: "" +- # password: "" +- # zipkin: +- # httpEndpoint: http://localhost:9411/api/v2/spans +- # sameSpan: false +- # id128Bit: true +- # sampleRate: 1.0 +- # haystack: +- # localAgentHost: 127.0.0.1 +- # localAgentPort: 35000 +- # globalTag: "" +- # traceIDHeaderName: "" +- # parentIDHeaderName: "" +- # spanIDHeaderName: "" +- # baggagePrefixHeaderName: "" +- # elastic: +- # serverURL: http://localhost:8200 +- # secretToken: "" +- # serviceEnvironment: "" ++# openTelemetry: # traefik v3+ only ++# grpc: {} ++# insecure: true ++# address: localhost:4317 ++# instana: ++# localAgentHost: 127.0.0.1 ++# localAgentPort: 42699 ++# logLevel: info ++# enableAutoProfile: true ++# datadog: ++# localAgentHostPort: 127.0.0.1:8126 ++# debug: false ++# globalTag: "" ++# prioritySampling: false ++# jaeger: ++# samplingServerURL: http://localhost:5778/sampling ++# samplingType: const ++# samplingParam: 1.0 ++# localAgentHostPort: 127.0.0.1:6831 ++# gen128Bit: false ++# propagation: jaeger ++# traceContextHeaderName: uber-trace-id ++# disableAttemptReconnecting: true ++# collector: ++# endpoint: "" ++# user: "" ++# password: "" ++# zipkin: ++# httpEndpoint: http://localhost:9411/api/v2/spans ++# sameSpan: false ++# id128Bit: true ++# sampleRate: 1.0 ++# haystack: ++# localAgentHost: 127.0.0.1 ++# localAgentPort: 35000 ++# globalTag: "" ++# traceIDHeaderName: "" ++# parentIDHeaderName: "" ++# spanIDHeaderName: "" ++# baggagePrefixHeaderName: "" ++# elastic: ++# serverURL: http://localhost:8200 ++# secretToken: "" ++# serviceEnvironment: "" + + # -- Global command arguments to be passed to all traefik's pods + globalArguments: +- - "--global.checknewversion" +- - "--global.sendanonymoususage" ++- "--global.checknewversion" ++- "--global.sendanonymoususage" + + # + # Configure Traefik static configuration +@@ -531,14 +547,14 @@ additionalArguments: [] + + # -- Environment variables to be passed to Traefik's binary + env: +- - name: POD_NAME +- valueFrom: +- fieldRef: +- fieldPath: metadata.name +- - name: POD_NAMESPACE +- valueFrom: +- fieldRef: +- fieldPath: metadata.namespace ++- name: POD_NAME ++ valueFrom: ++ fieldRef: ++ fieldPath: metadata.name ++- name: POD_NAMESPACE ++ valueFrom: ++ fieldRef: ++ fieldPath: metadata.namespace + # - name: SOME_VAR + # value: some-var-value + # - name: SOME_VAR_FROM_CONFIG_MAP +@@ -600,7 +616,10 @@ ports: + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection +- # redirectTo: websecure ++ # redirectTo: ++ # port: websecure ++ # (Optional) ++ # priority: 10 + # + # Trust forwarded headers information (X-Forwarded-*). + # forwardedHeaders: +@@ -638,14 +657,14 @@ ports: + # advertisedPort: 4443 + # + ## -- Trust forwarded headers information (X-Forwarded-*). +- #forwardedHeaders: +- # trustedIPs: [] +- # insecure: false ++ # forwardedHeaders: ++ # trustedIPs: [] ++ # insecure: false + # + ## -- Enable the Proxy Protocol header parsing for the entry point +- #proxyProtocol: +- # trustedIPs: [] +- # insecure: false ++ # proxyProtocol: ++ # trustedIPs: [] ++ # insecure: false + # + ## Set TLS at the entrypoint + ## https://doc.traefik.io/traefik/routing/entrypoints/#tls +@@ -728,16 +747,16 @@ service: + # -- Additional entries here will be added to the service spec. + # -- Cannot contain type, selector or ports entries. + spec: {} +- # externalTrafficPolicy: Cluster +- # loadBalancerIP: "1.2.3.4" +- # clusterIP: "2.3.4.5" ++ # externalTrafficPolicy: Cluster ++ # loadBalancerIP: "1.2.3.4" ++ # clusterIP: "2.3.4.5" + loadBalancerSourceRanges: [] +- # - 192.168.0.1/32 +- # - 172.16.0.0/16 ++ # - 192.168.0.1/32 ++ # - 172.16.0.0/16 + ## -- Class of the load balancer implementation + # loadBalancerClass: service.k8s.aws/nlb + externalIPs: [] +- # - 1.2.3.4 ++ # - 1.2.3.4 + ## One of SingleStack, PreferDualStack, or RequireDualStack. + # ipFamilyPolicy: SingleStack + ## List of IP families (e.g. IPv4 and/or IPv6). +@@ -789,7 +808,7 @@ persistence: + # It can be used to store TLS certificates, see `storage` in certResolvers + enabled: false + name: data +-# existingClaim: "" ++ # existingClaim: "" + accessMode: ReadWriteOnce + size: 128Mi + # storageClass: "" +@@ -852,12 +871,12 @@ serviceAccountAnnotations: {} + + # -- The resources parameter defines CPU and memory requirements and limits for Traefik's containers. + resources: {} +- # requests: +- # cpu: "100m" +- # memory: "50Mi" +- # limits: +- # cpu: "300m" +- # memory: "150Mi" ++# requests: ++# cpu: "100m" ++# memory: "50Mi" ++# limits: ++# cpu: "300m" ++# memory: "150Mi" + + # -- This example pod anti-affinity forces the scheduler to put traefik pods + # -- on nodes where no other traefik pods are scheduled. +``` + +## 24.0.0 ![AppVersion: v2.10.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.4&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-08-10 + +* fix: 💥 BREAKING CHANGE on healthchecks and traefik port +* fix: tracing.opentelemetry.tls is optional for all values +* fix: http3 support broken when advertisedPort set +* feat: multi namespace RBAC manifests +* chore(tests): 🔧 fix typo on tracing test +* chore(release): 🚀 publish v24.0.0 +* chore(deps): update docker.io/helmunittest/helm-unittest docker tag to v3.12.2 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 947ba56..aeec85c 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -28,6 +28,13 @@ deployment: + terminationGracePeriodSeconds: 60 + # -- The minimum number of seconds Traefik needs to be up and running before the DaemonSet/Deployment controller considers it available + minReadySeconds: 0 ++ ## Override the liveness/readiness port. This is useful to integrate traefik ++ ## with an external Load Balancer that performs healthchecks. ++ ## Default: ports.traefik.port ++ # healthchecksPort: 9000 ++ ## Override the liveness/readiness scheme. Useful for getting ping to ++ ## respond on websecure entryPoint. ++ # healthchecksScheme: HTTPS + # -- Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} + # -- Additional deployment labels (e.g. for filtering deployment by custom labels) +@@ -112,7 +119,7 @@ experimental: + #This value is no longer used, set the image.tag to a semver higher than 3.0, e.g. "v3.0.0-beta3" + #v3: + # -- Enable traefik version 3 +- # enabled: false ++ # enabled: false + plugins: + # -- Enable traefik experimental plugins + enabled: false +@@ -564,15 +571,6 @@ ports: + # only. + # hostIP: 192.168.100.10 + +- # Override the liveness/readiness port. This is useful to integrate traefik +- # with an external Load Balancer that performs healthchecks. +- # Default: ports.traefik.port +- # healthchecksPort: 9000 +- +- # Override the liveness/readiness scheme. Useful for getting ping to +- # respond on websecure entryPoint. +- # healthchecksScheme: HTTPS +- + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # +@@ -877,7 +875,7 @@ affinity: {} + nodeSelector: {} + # -- Tolerations allow the scheduler to schedule pods with matching taints. + tolerations: [] +-# -- You can use topology spread constraints to control ++# -- You can use topology spread constraints to control + # how Pods are spread across your cluster among failure-domains. + topologySpreadConstraints: [] + # This example topologySpreadConstraints forces the scheduler to put traefik pods +``` + +## 23.2.0 ![AppVersion: v2.10.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.4&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-07-27 + +* ⬆️ Upgrade traefik Docker tag to v2.10.3 +* release: :rocket: publish v23.2.0 +* fix: 🐛 update traefik.containo.us CRDs to v2.10 +* fix: 🐛 traefik or metrics port can be disabled +* fix: ingressclass name should be customizable (#864) +* feat: ✨ add support for traefik v3.0.0-beta3 and openTelemetry +* feat: disable allowPrivilegeEscalation +* feat: add pod_name as default in values.yaml +* chore(tests): 🔧 use more accurate asserts on refactor'd isNull test +* chore(deps): update traefik docker tag to v2.10.4 +* chore(deps): update docker.io/helmunittest/helm-unittest docker tag to v3.11.3 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 345bbd8..947ba56 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -105,12 +105,14 @@ podDisruptionBudget: + ingressClass: + enabled: true + isDefaultClass: true ++ # name: my-custom-class + + # Traefik experimental features + experimental: +- v3: ++ #This value is no longer used, set the image.tag to a semver higher than 3.0, e.g. "v3.0.0-beta3" ++ #v3: + # -- Enable traefik version 3 +- enabled: false ++ # enabled: false + plugins: + # -- Enable traefik experimental plugins + enabled: false +@@ -461,6 +463,10 @@ metrics: + ## Tracing + # -- https://doc.traefik.io/traefik/observability/tracing/overview/ + tracing: {} ++ # openTelemetry: # traefik v3+ only ++ # grpc: {} ++ # insecure: true ++ # address: localhost:4317 + # instana: + # localAgentHost: 127.0.0.1 + # localAgentPort: 42699 +@@ -517,7 +523,15 @@ additionalArguments: [] + # - "--log.level=DEBUG" + + # -- Environment variables to be passed to Traefik's binary +-env: [] ++env: ++ - name: POD_NAME ++ valueFrom: ++ fieldRef: ++ fieldPath: metadata.name ++ - name: POD_NAMESPACE ++ valueFrom: ++ fieldRef: ++ fieldPath: metadata.namespace + # - name: SOME_VAR + # value: some-var-value + # - name: SOME_VAR_FROM_CONFIG_MAP +@@ -563,7 +577,7 @@ ports: + # NodePort. + # + # -- You SHOULD NOT expose the traefik port on production deployments. +- # If you want to access it from outside of your cluster, ++ # If you want to access it from outside your cluster, + # use `kubectl port-forward` or create a secure ingress + expose: false + # -- The exposed port for this service +@@ -571,7 +585,7 @@ ports: + # -- The port protocol (TCP/UDP) + protocol: TCP + web: +- ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. ++ ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8000 + # hostPort: 8000 +@@ -600,7 +614,7 @@ ports: + # trustedIPs: [] + # insecure: false + websecure: +- ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. ++ ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8443 + # hostPort: 8443 +@@ -666,7 +680,7 @@ ports: + # NodePort. + # + # -- You may not want to expose the metrics port on production deployments. +- # If you want to access it from outside of your cluster, ++ # If you want to access it from outside your cluster, + # use `kubectl port-forward` or create a secure ingress + expose: false + # -- The exposed port for this service +@@ -880,14 +894,15 @@ topologySpreadConstraints: [] + priorityClassName: "" + + # -- Set the container security context +-# -- To run the container with ports below 1024 this will need to be adjust to run as root ++# -- To run the container with ports below 1024 this will need to be adjusted to run as root + securityContext: + capabilities: + drop: [ALL] + readOnlyRootFilesystem: true ++ allowPrivilegeEscalation: false + + podSecurityContext: +- # /!\ When setting fsGroup, Kubernetes will recursively changes ownership and ++ # /!\ When setting fsGroup, Kubernetes will recursively change ownership and + # permissions for the contents of each volume to match the fsGroup. This can + # be an issue when storing sensitive content like TLS Certificates /!\ + # fsGroup: 65532 +``` + +## 23.1.0 ![AppVersion: v2.10.1](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.1&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-06-06 + +* release: 🚀 publish v23.1.0 +* fix: 🐛 use k8s version for hpa api version +* fix: 🐛 http3 support on traefik v3 +* fix: use `targetPort` instead of `port` on ServiceMonitor +* feat: ➖ remove Traefik Hub v1 integration +* feat: ✨ add a warning when labelSelector don't match +* feat: common labels for all resources +* feat: allow specifying service loadBalancerClass +* feat: add optional `appProtocol` field on Service ports +* doc: added values README via helm-docs cli + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 71273cc..345bbd8 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,70 +1,56 @@ + # Default values for Traefik + image: ++ # -- Traefik image host registry + registry: docker.io ++ # -- Traefik image repository + repository: traefik +- # defaults to appVersion ++ # -- defaults to appVersion + tag: "" ++ # -- Traefik image pull policy + pullPolicy: IfNotPresent + +-# +-# Configure integration with Traefik Hub +-# +-hub: +- ## Enabling Hub will: +- # * enable Traefik Hub integration on Traefik +- # * add `traefikhub-tunl` endpoint +- # * enable Prometheus metrics with addRoutersLabels +- # * enable allowExternalNameServices on KubernetesIngress provider +- # * enable allowCrossNamespace on KubernetesCRD provider +- # * add an internal (ClusterIP) Service, dedicated for Traefik Hub +- enabled: false +- ## Default port can be changed +- # tunnelPort: 9901 +- ## TLS is optional. Insecure is mutually exclusive with any other options +- # tls: +- # insecure: false +- # ca: "/path/to/ca.pem" +- # cert: "/path/to/cert.pem" +- # key: "/path/to/key.pem" ++# -- Add additional label to all resources ++commonLabels: {} + + # + # Configure the deployment + # + deployment: ++ # -- Enable deployment + enabled: true +- # Can be either Deployment or DaemonSet ++ # -- Deployment or DaemonSet + kind: Deployment +- # Number of pods of the deployment (only applies when kind == Deployment) ++ # -- Number of pods of the deployment (only applies when kind == Deployment) + replicas: 1 +- # Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) ++ # -- Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) + # revisionHistoryLimit: 1 +- # Amount of time (in seconds) before Kubernetes will send the SIGKILL signal if Traefik does not shut down ++ # -- Amount of time (in seconds) before Kubernetes will send the SIGKILL signal if Traefik does not shut down + terminationGracePeriodSeconds: 60 +- # The minimum number of seconds Traefik needs to be up and running before the DaemonSet/Deployment controller considers it available ++ # -- The minimum number of seconds Traefik needs to be up and running before the DaemonSet/Deployment controller considers it available + minReadySeconds: 0 +- # Additional deployment annotations (e.g. for jaeger-operator sidecar injection) ++ # -- Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} +- # Additional deployment labels (e.g. for filtering deployment by custom labels) ++ # -- Additional deployment labels (e.g. for filtering deployment by custom labels) + labels: {} +- # Additional pod annotations (e.g. for mesh injection or prometheus scraping) ++ # -- Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} +- # Additional Pod labels (e.g. for filtering Pod by custom labels) ++ # -- Additional Pod labels (e.g. for filtering Pod by custom labels) + podLabels: {} +- # Additional containers (e.g. for metric offloading sidecars) ++ # -- Additional containers (e.g. for metric offloading sidecars) + additionalContainers: [] + # https://docs.datadoghq.com/developers/dogstatsd/unix_socket/?tab=host + # - name: socat-proxy +- # image: alpine/socat:1.0.5 +- # args: ["-s", "-u", "udp-recv:8125", "unix-sendto:/socket/socket"] +- # volumeMounts: +- # - name: dsdsocket +- # mountPath: /socket +- # Additional volumes available for use with initContainers and additionalContainers ++ # image: alpine/socat:1.0.5 ++ # args: ["-s", "-u", "udp-recv:8125", "unix-sendto:/socket/socket"] ++ # volumeMounts: ++ # - name: dsdsocket ++ # mountPath: /socket ++ # -- Additional volumes available for use with initContainers and additionalContainers + additionalVolumes: [] + # - name: dsdsocket + # hostPath: + # path: /var/run/statsd-exporter +- # Additional initContainers (e.g. for setting file permission as shown below) ++ # -- Additional initContainers (e.g. for setting file permission as shown below) + initContainers: [] + # The "volume-permissions" init container is required if you run into permission issues. + # Related issue: https://github.com/traefik/traefik-helm-chart/issues/396 +@@ -78,9 +64,9 @@ deployment: + # volumeMounts: + # - name: data + # mountPath: /data +- # Use process namespace sharing ++ # -- Use process namespace sharing + shareProcessNamespace: false +- # Custom pod DNS policy. Apply if `hostNetwork: true` ++ # -- Custom pod DNS policy. Apply if `hostNetwork: true` + # dnsPolicy: ClusterFirstWithHostNet + dnsConfig: {} + # nameservers: +@@ -92,10 +78,10 @@ deployment: + # - name: ndots + # value: "2" + # - name: edns0 +- # Additional imagePullSecrets ++ # -- Additional imagePullSecrets + imagePullSecrets: [] + # - name: myRegistryKeySecretName +- # Pod lifecycle actions ++ # -- Pod lifecycle actions + lifecycle: {} + # preStop: + # exec: +@@ -107,7 +93,7 @@ deployment: + # host: localhost + # scheme: HTTP + +-# Pod disruption budget ++# -- Pod disruption budget + podDisruptionBudget: + enabled: false + # maxUnavailable: 1 +@@ -115,93 +101,112 @@ podDisruptionBudget: + # minAvailable: 0 + # minAvailable: 25% + +-# Create a default IngressClass for Traefik ++# -- Create a default IngressClass for Traefik + ingressClass: + enabled: true + isDefaultClass: true + +-# Enable experimental features ++# Traefik experimental features + experimental: + v3: ++ # -- Enable traefik version 3 + enabled: false + plugins: ++ # -- Enable traefik experimental plugins + enabled: false + kubernetesGateway: ++ # -- Enable traefik experimental GatewayClass CRD + enabled: false + gateway: ++ # -- Enable traefik regular kubernetes gateway + enabled: true + # certificate: + # group: "core" + # kind: "Secret" + # name: "mysecret" +- # By default, Gateway would be created to the Namespace you are deploying Traefik to. ++ # -- By default, Gateway would be created to the Namespace you are deploying Traefik to. + # You may create that Gateway in another namespace, setting its name below: + # namespace: default + # Additional gateway annotations (e.g. for cert-manager.io/issuer) + # annotations: + # cert-manager.io/issuer: letsencrypt + +-# Create an IngressRoute for the dashboard ++## Create an IngressRoute for the dashboard + ingressRoute: + dashboard: ++ # -- Create an IngressRoute for the dashboard + enabled: true +- # Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) ++ # -- Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) + annotations: {} +- # Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) ++ # -- Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) + labels: {} +- # The router match rule used for the dashboard ingressRoute ++ # -- The router match rule used for the dashboard ingressRoute + matchRule: PathPrefix(`/dashboard`) || PathPrefix(`/api`) +- # Specify the allowed entrypoints to use for the dashboard ingress route, (e.g. traefik, web, websecure). ++ # -- Specify the allowed entrypoints to use for the dashboard ingress route, (e.g. traefik, web, websecure). + # By default, it's using traefik entrypoint, which is not exposed. + # /!\ Do not expose your dashboard without any protection over the internet /!\ + entryPoints: ["traefik"] +- # Additional ingressRoute middlewares (e.g. for authentication) ++ # -- Additional ingressRoute middlewares (e.g. for authentication) + middlewares: [] +- # TLS options (e.g. secret containing certificate) ++ # -- TLS options (e.g. secret containing certificate) + tls: {} + +-# Customize updateStrategy of traefik pods + updateStrategy: ++ # -- Customize updateStrategy: RollingUpdate or OnDelete + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + +-# Customize liveness and readiness probe values. + readinessProbe: ++ # -- The number of consecutive failures allowed before considering the probe as failed. + failureThreshold: 1 ++ # -- The number of seconds to wait before starting the first probe. + initialDelaySeconds: 2 ++ # -- The number of seconds to wait between consecutive probes. + periodSeconds: 10 ++ # -- The minimum consecutive successes required to consider the probe successful. + successThreshold: 1 ++ # -- The number of seconds to wait for a probe response before considering it as failed. + timeoutSeconds: 2 +- + livenessProbe: ++ # -- The number of consecutive failures allowed before considering the probe as failed. + failureThreshold: 3 ++ # -- The number of seconds to wait before starting the first probe. + initialDelaySeconds: 2 ++ # -- The number of seconds to wait between consecutive probes. + periodSeconds: 10 ++ # -- The minimum consecutive successes required to consider the probe successful. + successThreshold: 1 ++ # -- The number of seconds to wait for a probe response before considering it as failed. + timeoutSeconds: 2 + +-# +-# Configure providers +-# + providers: + kubernetesCRD: ++ # -- Load Kubernetes IngressRoute provider + enabled: true ++ # -- Allows IngressRoute to reference resources in namespace other than theirs + allowCrossNamespace: false ++ # -- Allows to reference ExternalName services in IngressRoute + allowExternalNameServices: false ++ # -- Allows to return 503 when there is no endpoints available + allowEmptyServices: false + # ingressClass: traefik-internal + # labelSelector: environment=production,method=traefik ++ # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] + # - "default" + + kubernetesIngress: ++ # -- Load Kubernetes IngressRoute provider + enabled: true ++ # -- Allows to reference ExternalName services in Ingress + allowExternalNameServices: false ++ # -- Allows to return 503 when there is no endpoints available + allowEmptyServices: false + # ingressClass: traefik-internal + # labelSelector: environment=production,method=traefik ++ # -- Array of namespaces to watch. If left empty, Traefik watches all namespaces. + namespaces: [] + # - "default" + # IP used for Kubernetes Ingress endpoints +@@ -212,13 +217,13 @@ providers: + # pathOverride: "" + + # +-# Add volumes to the traefik pod. The volume name will be passed to tpl. ++# -- Add volumes to the traefik pod. The volume name will be passed to tpl. + # This can be used to mount a cert pair or a configmap that holds a config.toml file. + # After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: +-# additionalArguments: ++# `additionalArguments: + # - "--providers.file.filename=/config/dynamic.toml" + # - "--ping" +-# - "--ping.entrypoint=web" ++# - "--ping.entrypoint=web"` + volumes: [] + # - name: public-cert + # mountPath: "/certs" +@@ -227,25 +232,22 @@ volumes: [] + # mountPath: "/config" + # type: configMap + +-# Additional volumeMounts to add to the Traefik container ++# -- Additional volumeMounts to add to the Traefik container + additionalVolumeMounts: [] +- # For instance when using a logshipper for access logs ++ # -- For instance when using a logshipper for access logs + # - name: traefik-logs + # mountPath: /var/log/traefik + +-## Logs +-## https://docs.traefik.io/observability/logs/ + logs: +- ## Traefik logs concern everything that happens to Traefik itself (startup, configuration, events, shutdown, and so on). + general: +- # By default, the logs use a text format (common), but you can ++ # -- By default, the logs use a text format (common), but you can + # also ask for the json format in the format option + # format: json + # By default, the level is set to ERROR. +- # Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. ++ # -- Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. + level: ERROR + access: +- # To enable access logs ++ # -- To enable access logs + enabled: false + ## By default, logs are written using the Common Log Format (CLF) on stdout. + ## To write logs in JSON, use json in the format option. +@@ -256,21 +258,24 @@ logs: + ## This option represents the number of log lines Traefik will keep in memory before writing + ## them to the selected output. In some cases, this option can greatly help performances. + # bufferingSize: 100 +- ## Filtering https://docs.traefik.io/observability/access-logs/#filtering ++ ## Filtering ++ # -- https://docs.traefik.io/observability/access-logs/#filtering + filters: {} + # statuscodes: "200,300-302" + # retryattempts: true + # minduration: 10ms +- ## Fields +- ## https://docs.traefik.io/observability/access-logs/#limiting-the-fieldsincluding-headers + fields: + general: ++ # -- Available modes: keep, drop, redact. + defaultmode: keep ++ # -- Names of the fields to limit. + names: {} + ## Examples: + # ClientUsername: drop + headers: ++ # -- Available modes: keep, drop, redact. + defaultmode: drop ++ # -- Names of the headers to limit. + names: {} + ## Examples: + # User-Agent: redact +@@ -278,10 +283,10 @@ logs: + # Content-Type: keep + + metrics: +- ## Prometheus is enabled by default. +- ## It can be disabled by setting "prometheus: null" ++ ## -- Prometheus is enabled by default. ++ ## -- It can be disabled by setting "prometheus: null" + prometheus: +- ## Entry point used to expose metrics. ++ # -- Entry point used to expose metrics. + entryPoint: metrics + ## Enable metrics on entry points. Default=true + # addEntryPointsLabels: false +@@ -404,11 +409,9 @@ metrics: + # ## This instructs the reporter to send metrics to the OpenTelemetry Collector using gRPC. + # grpc: true + +-## +-## enable optional CRDs for Prometheus Operator ++## -- enable optional CRDs for Prometheus Operator + ## + ## Create a dedicated metrics service for use with ServiceMonitor +- ## When hub.enabled is set to true, it's not needed: it will use hub service. + # service: + # enabled: false + # labels: {} +@@ -455,6 +458,8 @@ metrics: + # summary: "Traefik Down" + # description: "{{ $labels.pod }} on {{ $labels.nodename }} is down" + ++## Tracing ++# -- https://doc.traefik.io/traefik/observability/tracing/overview/ + tracing: {} + # instana: + # localAgentHost: 127.0.0.1 +@@ -497,20 +502,21 @@ tracing: {} + # secretToken: "" + # serviceEnvironment: "" + ++# -- Global command arguments to be passed to all traefik's pods + globalArguments: + - "--global.checknewversion" + - "--global.sendanonymoususage" + + # + # Configure Traefik static configuration +-# Additional arguments to be passed at Traefik's binary ++# -- Additional arguments to be passed at Traefik's binary + # All available options available on https://docs.traefik.io/reference/static-configuration/cli/ + ## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}"` + additionalArguments: [] + # - "--providers.kubernetesingress.ingressclass=traefik-internal" + # - "--log.level=DEBUG" + +-# Environment variables to be passed to Traefik's binary ++# -- Environment variables to be passed to Traefik's binary + env: [] + # - name: SOME_VAR + # value: some-var-value +@@ -525,22 +531,20 @@ env: [] + # name: secret-name + # key: secret-key + ++# -- Environment variables to be passed to Traefik's binary from configMaps or secrets + envFrom: [] + # - configMapRef: + # name: config-map-name + # - secretRef: + # name: secret-name + +-# Configure ports + ports: +- # The name of this one can't be changed as it is used for the readiness and +- # liveness probes, but you can adjust its config to your liking + traefik: + port: 9000 +- # Use hostPort if set. ++ # -- Use hostPort if set. + # hostPort: 9000 + # +- # Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which ++ # -- Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which + # means it's listening on all your interfaces and all your IPs. You may want + # to set this value if you need traefik to listen on specific interface + # only. +@@ -558,27 +562,27 @@ ports: + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # +- # You SHOULD NOT expose the traefik port on production deployments. ++ # -- You SHOULD NOT expose the traefik port on production deployments. + # If you want to access it from outside of your cluster, + # use `kubectl port-forward` or create a secure ingress + expose: false +- # The exposed port for this service ++ # -- The exposed port for this service + exposedPort: 9000 +- # The port protocol (TCP/UDP) ++ # -- The port protocol (TCP/UDP) + protocol: TCP + web: +- ## Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. ++ ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8000 + # hostPort: 8000 + # containerPort: 8000 + expose: true + exposedPort: 80 +- ## Different target traefik port on the cluster, useful for IP type LB ++ ## -- Different target traefik port on the cluster, useful for IP type LB + # targetPort: 80 + # The port protocol (TCP/UDP) + protocol: TCP +- # Use nodeport if set. This is useful if you have configured Traefik in a ++ # -- Use nodeport if set. This is useful if you have configured Traefik in a + # LoadBalancer. + # nodePort: 32080 + # Port Redirections +@@ -596,20 +600,22 @@ ports: + # trustedIPs: [] + # insecure: false + websecure: +- ## Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. ++ ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8443 + # hostPort: 8443 + # containerPort: 8443 + expose: true + exposedPort: 443 +- ## Different target traefik port on the cluster, useful for IP type LB ++ ## -- Different target traefik port on the cluster, useful for IP type LB + # targetPort: 80 +- ## The port protocol (TCP/UDP) ++ ## -- The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 ++ ## -- Specify an application protocol. This may be used as a hint for a Layer 7 load balancer. ++ # appProtocol: https + # +- ## Enable HTTP/3 on the entrypoint ++ ## -- Enable HTTP/3 on the entrypoint + ## Enabling it will also enable http3 experimental feature + ## https://doc.traefik.io/traefik/routing/entrypoints/#http3 + ## There are known limitations when trying to listen on same ports for +@@ -619,12 +625,12 @@ ports: + enabled: false + # advertisedPort: 4443 + # +- ## Trust forwarded headers information (X-Forwarded-*). ++ ## -- Trust forwarded headers information (X-Forwarded-*). + #forwardedHeaders: + # trustedIPs: [] + # insecure: false + # +- ## Enable the Proxy Protocol header parsing for the entry point ++ ## -- Enable the Proxy Protocol header parsing for the entry point + #proxyProtocol: + # trustedIPs: [] + # insecure: false +@@ -642,33 +648,33 @@ ports: + # - foo.example.com + # - bar.example.com + # +- # One can apply Middlewares on an entrypoint ++ # -- One can apply Middlewares on an entrypoint + # https://doc.traefik.io/traefik/middlewares/overview/ + # https://doc.traefik.io/traefik/routing/entrypoints/#middlewares +- # /!\ It introduces here a link between your static configuration and your dynamic configuration /!\ ++ # -- /!\ It introduces here a link between your static configuration and your dynamic configuration /!\ + # It follows the provider naming convention: https://doc.traefik.io/traefik/providers/overview/#provider-namespace + # middlewares: + # - namespace-name1@kubernetescrd + # - namespace-name2@kubernetescrd + middlewares: [] + metrics: +- # When using hostNetwork, use another port to avoid conflict with node exporter: ++ # -- When using hostNetwork, use another port to avoid conflict with node exporter: + # https://github.com/prometheus/prometheus/wiki/Default-port-allocations + port: 9100 + # hostPort: 9100 + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # +- # You may not want to expose the metrics port on production deployments. ++ # -- You may not want to expose the metrics port on production deployments. + # If you want to access it from outside of your cluster, + # use `kubectl port-forward` or create a secure ingress + expose: false +- # The exposed port for this service ++ # -- The exposed port for this service + exposedPort: 9100 +- # The port protocol (TCP/UDP) ++ # -- The port protocol (TCP/UDP) + protocol: TCP + +-# TLS Options are created as TLSOption CRDs ++# -- TLS Options are created as TLSOption CRDs + # https://doc.traefik.io/traefik/https/tls/#tls-options + # When using `labelSelector`, you'll need to set labels on tlsOption accordingly. + # Example: +@@ -684,7 +690,7 @@ ports: + # - CurveP384 + tlsOptions: {} + +-# TLS Store are created as TLSStore CRDs. This is useful if you want to set a default certificate ++# -- TLS Store are created as TLSStore CRDs. This is useful if you want to set a default certificate + # https://doc.traefik.io/traefik/https/tls/#default-certificate + # Example: + # tlsStore: +@@ -693,24 +699,22 @@ tlsOptions: {} + # secretName: tls-cert + tlsStore: {} + +-# Options for the main traefik service, where the entrypoints traffic comes +-# from. + service: + enabled: true +- ## Single service is using `MixedProtocolLBService` feature gate. +- ## When set to false, it will create two Service, one for TCP and one for UDP. ++ ## -- Single service is using `MixedProtocolLBService` feature gate. ++ ## -- When set to false, it will create two Service, one for TCP and one for UDP. + single: true + type: LoadBalancer +- # Additional annotations applied to both TCP and UDP services (e.g. for cloud provider specific config) ++ # -- Additional annotations applied to both TCP and UDP services (e.g. for cloud provider specific config) + annotations: {} +- # Additional annotations for TCP service only ++ # -- Additional annotations for TCP service only + annotationsTCP: {} +- # Additional annotations for UDP service only ++ # -- Additional annotations for UDP service only + annotationsUDP: {} +- # Additional service labels (e.g. for filtering Service by custom labels) ++ # -- Additional service labels (e.g. for filtering Service by custom labels) + labels: {} +- # Additional entries here will be added to the service spec. +- # Cannot contain type, selector or ports entries. ++ # -- Additional entries here will be added to the service spec. ++ # -- Cannot contain type, selector or ports entries. + spec: {} + # externalTrafficPolicy: Cluster + # loadBalancerIP: "1.2.3.4" +@@ -718,6 +722,8 @@ service: + loadBalancerSourceRanges: [] + # - 192.168.0.1/32 + # - 172.16.0.0/16 ++ ## -- Class of the load balancer implementation ++ # loadBalancerClass: service.k8s.aws/nlb + externalIPs: [] + # - 1.2.3.4 + ## One of SingleStack, PreferDualStack, or RequireDualStack. +@@ -728,7 +734,7 @@ service: + # - IPv4 + # - IPv6 + ## +- ## An additionnal and optional internal Service. ++ ## -- An additionnal and optional internal Service. + ## Same parameters as external Service + # internal: + # type: ClusterIP +@@ -739,9 +745,8 @@ service: + # # externalIPs: [] + # # ipFamilies: [ "IPv4","IPv6" ] + +-## Create HorizontalPodAutoscaler object. +-## + autoscaling: ++ # -- Create HorizontalPodAutoscaler object. + enabled: false + # minReplicas: 1 + # maxReplicas: 10 +@@ -766,10 +771,10 @@ autoscaling: + # value: 1 + # periodSeconds: 60 + +-# Enable persistence using Persistent Volume Claims +-# ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +-# It can be used to store TLS certificates, see `storage` in certResolvers + persistence: ++ # -- Enable persistence using Persistent Volume Claims ++ # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ ++ # It can be used to store TLS certificates, see `storage` in certResolvers + enabled: false + name: data + # existingClaim: "" +@@ -779,8 +784,10 @@ persistence: + # volumeName: "" + path: /data + annotations: {} +- # subPath: "" # only mount a subpath of the Volume into the pod ++ # -- Only mount a subpath of the Volume into the pod ++ # subPath: "" + ++# -- Certificates resolvers configuration + certResolvers: {} + # letsencrypt: + # # for challenge options cf. https://doc.traefik.io/traefik/https/acme/ +@@ -802,13 +809,13 @@ certResolvers: {} + # # It has to match the path with a persistent volume + # storage: /data/acme.json + +-# If hostNetwork is true, runs traefik in the host network namespace ++# -- If hostNetwork is true, runs traefik in the host network namespace + # To prevent unschedulabel pods due to port collisions, if hostNetwork=true + # and replicas>1, a pod anti-affinity is recommended and will be set if the + # affinity is left as default. + hostNetwork: false + +-# Whether Role Based Access Control objects like roles and rolebindings should be created ++# -- Whether Role Based Access Control objects like roles and rolebindings should be created + rbac: + enabled: true + # If set to false, installs ClusterRole and ClusterRoleBinding so Traefik can be used across namespaces. +@@ -818,19 +825,20 @@ rbac: + # https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + # aggregateTo: [ "admin" ] + +-# Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding ++# -- Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding + podSecurityPolicy: + enabled: false + +-# The service account the pods will use to interact with the Kubernetes API ++# -- The service account the pods will use to interact with the Kubernetes API + serviceAccount: + # If set, an existing service account is used + # If not set, a service account is created automatically using the fullname template + name: "" + +-# Additional serviceAccount annotations (e.g. for oidc authentication) ++# -- Additional serviceAccount annotations (e.g. for oidc authentication) + serviceAccountAnnotations: {} + ++# -- The resources parameter defines CPU and memory requirements and limits for Traefik's containers. + resources: {} + # requests: + # cpu: "100m" +@@ -839,8 +847,8 @@ resources: {} + # cpu: "300m" + # memory: "150Mi" + +-# This example pod anti-affinity forces the scheduler to put traefik pods +-# on nodes where no other traefik pods are scheduled. ++# -- This example pod anti-affinity forces the scheduler to put traefik pods ++# -- on nodes where no other traefik pods are scheduled. + # It should be used when hostNetwork: true to prevent port conflicts + affinity: {} + # podAntiAffinity: +@@ -851,11 +859,15 @@ affinity: {} + # app.kubernetes.io/instance: '{{ .Release.Name }}-{{ .Release.Namespace }}' + # topologyKey: kubernetes.io/hostname + ++# -- nodeSelector is the simplest recommended form of node selection constraint. + nodeSelector: {} ++# -- Tolerations allow the scheduler to schedule pods with matching taints. + tolerations: [] ++# -- You can use topology spread constraints to control ++# how Pods are spread across your cluster among failure-domains. + topologySpreadConstraints: [] +-# # This example topologySpreadConstraints forces the scheduler to put traefik pods +-# # on nodes where no other traefik pods are scheduled. ++# This example topologySpreadConstraints forces the scheduler to put traefik pods ++# on nodes where no other traefik pods are scheduled. + # - labelSelector: + # matchLabels: + # app: '{{ template "traefik.name" . }}' +@@ -863,29 +875,33 @@ topologySpreadConstraints: [] + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: DoNotSchedule + +-# Pods can have priority. +-# Priority indicates the importance of a Pod relative to other Pods. ++# -- Pods can have priority. ++# -- Priority indicates the importance of a Pod relative to other Pods. + priorityClassName: "" + +-# Set the container security context +-# To run the container with ports below 1024 this will need to be adjust to run as root ++# -- Set the container security context ++# -- To run the container with ports below 1024 this will need to be adjust to run as root + securityContext: + capabilities: + drop: [ALL] + readOnlyRootFilesystem: true + + podSecurityContext: +-# # /!\ When setting fsGroup, Kubernetes will recursively changes ownership and +-# # permissions for the contents of each volume to match the fsGroup. This can +-# # be an issue when storing sensitive content like TLS Certificates /!\ +-# fsGroup: 65532 ++ # /!\ When setting fsGroup, Kubernetes will recursively changes ownership and ++ # permissions for the contents of each volume to match the fsGroup. This can ++ # be an issue when storing sensitive content like TLS Certificates /!\ ++ # fsGroup: 65532 ++ # -- Specifies the policy for changing ownership and permissions of volume contents to match the fsGroup. + fsGroupChangePolicy: "OnRootMismatch" ++ # -- The ID of the group for all containers in the pod to run as. + runAsGroup: 65532 ++ # -- Specifies whether the containers should run as a non-root user. + runAsNonRoot: true ++ # -- The ID of the user for all containers in the pod to run as. + runAsUser: 65532 + + # +-# Extra objects to deploy (value evaluated as a template) ++# -- Extra objects to deploy (value evaluated as a template) + # + # In some cases, it can avoid the need for additional, extended or adhoc deployments. + # See #595 for more details and traefik/tests/values/extra.yaml for example. +@@ -895,5 +911,5 @@ extraObjects: [] + # It will not affect optional CRDs such as `ServiceMonitor` and `PrometheusRules` + # namespaceOverride: traefik + # +-## This will override the default app.kubernetes.io/instance label for all Objects. ++## -- This will override the default app.kubernetes.io/instance label for all Objects. + # instanceLabelOverride: traefik +``` + +## 23.0.1 ![AppVersion: v2.10.1](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.1&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-04-28 + +* fix: ⬆️ Upgrade traefik Docker tag to v2.10.1 + + +## 23.0.0 ![AppVersion: v2.10.0](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.0&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-04-26 + +* BREAKING CHANGE: Traefik 2.10 comes with CRDs update on API Group + + +## 22.3.0 ![AppVersion: v2.10.0](https://img.shields.io/static/v1?label=AppVersion&message=v2.10.0&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-04-25 + +* ⬆️ Upgrade traefik Docker tag to v2.10.0 +* fix: 🐛 update rbac for both traefik.io and containo.us apigroups (#836) +* breaking: 💥 update CRDs needed for Traefik v2.10 + + +## 22.2.0 ![AppVersion: v2.9.10](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.10&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-04-24 + +* test: 👷 Update unit tests tooling +* fix: 🐛 annotations leaking between aliased subcharts +* fix: indentation on `TLSOption` +* feat: override container port +* feat: allow to set dnsConfig on pod template +* chore: 🔧 new release +* added targetPort support + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 9ece303..71273cc 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -82,6 +82,16 @@ deployment: + shareProcessNamespace: false + # Custom pod DNS policy. Apply if `hostNetwork: true` + # dnsPolicy: ClusterFirstWithHostNet ++ dnsConfig: {} ++ # nameservers: ++ # - 192.0.2.1 # this is an example ++ # searches: ++ # - ns1.svc.cluster-domain.example ++ # - my.dns.search.suffix ++ # options: ++ # - name: ndots ++ # value: "2" ++ # - name: edns0 + # Additional imagePullSecrets + imagePullSecrets: [] + # - name: myRegistryKeySecretName +@@ -561,8 +571,11 @@ ports: + # asDefault: true + port: 8000 + # hostPort: 8000 ++ # containerPort: 8000 + expose: true + exposedPort: 80 ++ ## Different target traefik port on the cluster, useful for IP type LB ++ # targetPort: 80 + # The port protocol (TCP/UDP) + protocol: TCP + # Use nodeport if set. This is useful if you have configured Traefik in a +@@ -587,8 +600,11 @@ ports: + # asDefault: true + port: 8443 + # hostPort: 8443 ++ # containerPort: 8443 + expose: true + exposedPort: 443 ++ ## Different target traefik port on the cluster, useful for IP type LB ++ # targetPort: 80 + ## The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 +``` + +## 22.1.0 ![AppVersion: v2.9.10](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.10&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-04-07 + +* ⬆️ Upgrade traefik Docker tag to v2.9.10 +* feat: add additional labels to tlsoption + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 4762b77..9ece303 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -654,12 +654,15 @@ ports: + + # TLS Options are created as TLSOption CRDs + # https://doc.traefik.io/traefik/https/tls/#tls-options ++# When using `labelSelector`, you'll need to set labels on tlsOption accordingly. + # Example: + # tlsOptions: + # default: ++# labels: {} + # sniStrict: true + # preferServerCipherSuites: true +-# foobar: ++# customOptions: ++# labels: {} + # curvePreferences: + # - CurveP521 + # - CurveP384 +``` + +## 22.0.0 ![AppVersion: v2.9.9](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.9&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-03-29 + +* BREAKING CHANGE: `image.repository` introduction may break during the upgrade. See PR #802. + + +## 21.2.1 ![AppVersion: v2.9.9](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.9&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-03-28 + +* 🎨 Introduce `image.registry` and add explicit default (it may impact custom `image.repository`) +* ⬆️ Upgrade traefik Docker tag to v2.9.9 +* :memo: Clarify the need of an initContainer when enabling persistence for TLS Certificates + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index cadc7a6..4762b77 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,5 +1,6 @@ + # Default values for Traefik + image: ++ registry: docker.io + repository: traefik + # defaults to appVersion + tag: "" +@@ -66,10 +67,14 @@ deployment: + # Additional initContainers (e.g. for setting file permission as shown below) + initContainers: [] + # The "volume-permissions" init container is required if you run into permission issues. +- # Related issue: https://github.com/traefik/traefik/issues/6825 ++ # Related issue: https://github.com/traefik/traefik-helm-chart/issues/396 + # - name: volume-permissions +- # image: busybox:1.35 +- # command: ["sh", "-c", "touch /data/acme.json && chmod -Rv 600 /data/* && chown 65532:65532 /data/acme.json"] ++ # image: busybox:latest ++ # command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"] ++ # securityContext: ++ # runAsNonRoot: true ++ # runAsGroup: 65532 ++ # runAsUser: 65532 + # volumeMounts: + # - name: data + # mountPath: /data +@@ -849,13 +854,17 @@ securityContext: + capabilities: + drop: [ALL] + readOnlyRootFilesystem: true ++ ++podSecurityContext: ++# # /!\ When setting fsGroup, Kubernetes will recursively changes ownership and ++# # permissions for the contents of each volume to match the fsGroup. This can ++# # be an issue when storing sensitive content like TLS Certificates /!\ ++# fsGroup: 65532 ++ fsGroupChangePolicy: "OnRootMismatch" + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + +-podSecurityContext: +- fsGroup: 65532 +- + # + # Extra objects to deploy (value evaluated as a template) + # +``` + +## 21.2.0 ![AppVersion: v2.9.8](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.8&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-03-08 + +* 🚨 Fail when enabling PSP on Kubernetes v1.25+ (#801) +* ⬆️ Upgrade traefik Docker tag to v2.9.8 +* Separate UDP hostPort for HTTP/3 +* :sparkles: release 21.2.0 (#805) + + +## 21.1.0 ![AppVersion: v2.9.7](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.7&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-02-15 + +* ⬆️ Upgrade traefik Docker tag to v2.9.7 +* ✨ release 21.1.0 +* fix: traefik image name for renovate +* feat: Add volumeName to PersistentVolumeClaim (#792) +* Allow setting TLS options on dashboard IngressRoute + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 780b04b..cadc7a6 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -142,6 +142,8 @@ ingressRoute: + entryPoints: ["traefik"] + # Additional ingressRoute middlewares (e.g. for authentication) + middlewares: [] ++ # TLS options (e.g. secret containing certificate) ++ tls: {} + + # Customize updateStrategy of traefik pods + updateStrategy: +@@ -750,6 +752,7 @@ persistence: + accessMode: ReadWriteOnce + size: 128Mi + # storageClass: "" ++ # volumeName: "" + path: /data + annotations: {} + # subPath: "" # only mount a subpath of the Volume into the pod +``` + +## 21.0.0 ![AppVersion: v2.9.6](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.6&color=success&logo=) ![Kubernetes: >=1.16.0-0](https://img.shields.io/static/v1?label=Kubernetes&message=%3E%3D1.16.0-0&color=informational&logo=kubernetes) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2023-02-10 + +* 🙈 Add a setting disable API check on Prometheus Operator (#769) +* 📝 Improve documentation on entrypoint options +* 💥 New release with BREAKING changes (#786) +* ✨ Chart.yaml - add kubeVersion: ">=1.16.0-0" +* fix: allowExternalNameServices for kubernetes ingress when hub enabled (#772) +* fix(service-metrics): invert prometheus svc & fullname length checking +* Configure Renovate (#783) +* :necktie: Improve labels settings behavior on metrics providers (#774) +* :bug: Disabling dashboard ingressroute should delete it (#785) +* :boom: Rename image.name => image.repository (#784) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 42a27f9..780b04b 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,6 +1,6 @@ + # Default values for Traefik + image: +- name: traefik ++ repository: traefik + # defaults to appVersion + tag: "" + pullPolicy: IfNotPresent +@@ -396,6 +396,8 @@ metrics: + # enabled: false + # labels: {} + # annotations: {} ++ ## When set to true, it won't check if Prometheus Operator CRDs are deployed ++ # disableAPICheck: false + # serviceMonitor: + # metricRelabelings: [] + # - sourceLabels: [__name__] +@@ -580,7 +582,7 @@ ports: + # hostPort: 8443 + expose: true + exposedPort: 443 +- # The port protocol (TCP/UDP) ++ ## The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 + # +@@ -594,6 +596,16 @@ ports: + enabled: false + # advertisedPort: 4443 + # ++ ## Trust forwarded headers information (X-Forwarded-*). ++ #forwardedHeaders: ++ # trustedIPs: [] ++ # insecure: false ++ # ++ ## Enable the Proxy Protocol header parsing for the entry point ++ #proxyProtocol: ++ # trustedIPs: [] ++ # insecure: false ++ # + ## Set TLS at the entrypoint + ## https://doc.traefik.io/traefik/routing/entrypoints/#tls + tls: +@@ -607,16 +619,6 @@ ports: + # - foo.example.com + # - bar.example.com + # +- # Trust forwarded headers information (X-Forwarded-*). +- # forwardedHeaders: +- # trustedIPs: [] +- # insecure: false +- # +- # Enable the Proxy Protocol header parsing for the entry point +- # proxyProtocol: +- # trustedIPs: [] +- # insecure: false +- # + # One can apply Middlewares on an entrypoint + # https://doc.traefik.io/traefik/middlewares/overview/ + # https://doc.traefik.io/traefik/routing/entrypoints/#middlewares +``` + +## 20.8.0 ![AppVersion: v2.9.6](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-12-09 + +* ✨ update chart to version 20.8.0 +* ✨ add support for default entrypoints +* ✨ add support for OpenTelemetry and Traefik v3 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index b77539d..42a27f9 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -107,6 +107,8 @@ ingressClass: + + # Enable experimental features + experimental: ++ v3: ++ enabled: false + plugins: + enabled: false + kubernetesGateway: +@@ -347,7 +349,43 @@ metrics: + # # addRoutersLabels: true + # ## Enable metrics on services. Default=true + # # addServicesLabels: false +- ++# openTelemetry: ++# ## Address of the OpenTelemetry Collector to send metrics to. ++# address: "localhost:4318" ++# ## Enable metrics on entry points. ++# addEntryPointsLabels: true ++# ## Enable metrics on routers. ++# addRoutersLabels: true ++# ## Enable metrics on services. ++# addServicesLabels: true ++# ## Explicit boundaries for Histogram data points. ++# explicitBoundaries: ++# - "0.1" ++# - "0.3" ++# - "1.2" ++# - "5.0" ++# ## Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. ++# headers: ++# foo: bar ++# test: test ++# ## Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. ++# insecure: true ++# ## Interval at which metrics are sent to the OpenTelemetry Collector. ++# pushInterval: 10s ++# ## Allows to override the default URL path used for sending metrics. This option has no effect when using gRPC transport. ++# path: /foo/v1/traces ++# ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. ++# tls: ++# ## The path to the certificate authority, it defaults to the system bundle. ++# ca: path/to/ca.crt ++# ## The path to the public certificate. When using this option, setting the key option is required. ++# cert: path/to/foo.cert ++# ## The path to the private key. When using this option, setting the cert option is required. ++# key: path/to/key.key ++# ## If set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. ++# insecureSkipVerify: true ++# ## This instructs the reporter to send metrics to the OpenTelemetry Collector using gRPC. ++# grpc: true + + ## + ## enable optional CRDs for Prometheus Operator +@@ -510,6 +548,8 @@ ports: + # The port protocol (TCP/UDP) + protocol: TCP + web: ++ ## Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. ++ # asDefault: true + port: 8000 + # hostPort: 8000 + expose: true +@@ -534,6 +574,8 @@ ports: + # trustedIPs: [] + # insecure: false + websecure: ++ ## Enable this entrypoint as a default entrypoint. When a service doesn't explicity set an entrypoint it will only use this entrypoint. ++ # asDefault: true + port: 8443 + # hostPort: 8443 + expose: true +``` + +## 20.7.0 ![AppVersion: v2.9.6](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-12-08 + +* 🐛 Don't fail when prometheus is disabled (#756) +* ⬆️ Update default Traefik release to v2.9.6 (#758) +* ✨ support for Gateway annotations +* add keywords [networking], for artifacthub category quering +* :bug: Fix typo on bufferingSize for access logs (#753) +* :adhesive_bandage: Add quotes for artifacthub changelog parsing (#748) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 4f2fb2a..b77539d 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -120,6 +120,9 @@ experimental: + # By default, Gateway would be created to the Namespace you are deploying Traefik to. + # You may create that Gateway in another namespace, setting its name below: + # namespace: default ++ # Additional gateway annotations (e.g. for cert-manager.io/issuer) ++ # annotations: ++ # cert-manager.io/issuer: letsencrypt + + # Create an IngressRoute for the dashboard + ingressRoute: +@@ -219,7 +222,8 @@ logs: + # By default, the logs use a text format (common), but you can + # also ask for the json format in the format option + # format: json +- # By default, the level is set to ERROR. Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. ++ # By default, the level is set to ERROR. ++ # Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. + level: ERROR + access: + # To enable access logs +``` + +## 20.6.0 ![AppVersion: v2.9.5](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.5&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-30 + +* 🔍️ Add filePath support on access logs (#747) +* :memo: Improve documentation on using PVC with TLS certificates +* :bug: Add missing scheme in help on Traefik Hub integration (#746) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 15f1682..4f2fb2a 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -211,10 +211,10 @@ additionalVolumeMounts: [] + # - name: traefik-logs + # mountPath: /var/log/traefik + +-# Logs +-# https://docs.traefik.io/observability/logs/ ++## Logs ++## https://docs.traefik.io/observability/logs/ + logs: +- # Traefik logs concern everything that happens to Traefik itself (startup, configuration, events, shutdown, and so on). ++ ## Traefik logs concern everything that happens to Traefik itself (startup, configuration, events, shutdown, and so on). + general: + # By default, the logs use a text format (common), but you can + # also ask for the json format in the format option +@@ -224,31 +224,32 @@ logs: + access: + # To enable access logs + enabled: false +- # By default, logs are written using the Common Log Format (CLF). +- # To write logs in JSON, use json in the format option. +- # If the given format is unsupported, the default (CLF) is used instead. ++ ## By default, logs are written using the Common Log Format (CLF) on stdout. ++ ## To write logs in JSON, use json in the format option. ++ ## If the given format is unsupported, the default (CLF) is used instead. + # format: json +- # To write the logs in an asynchronous fashion, specify a bufferingSize option. +- # This option represents the number of log lines Traefik will keep in memory before writing +- # them to the selected output. In some cases, this option can greatly help performances. ++ # filePath: "/var/log/traefik/access.log ++ ## To write the logs in an asynchronous fashion, specify a bufferingSize option. ++ ## This option represents the number of log lines Traefik will keep in memory before writing ++ ## them to the selected output. In some cases, this option can greatly help performances. + # bufferingSize: 100 +- # Filtering https://docs.traefik.io/observability/access-logs/#filtering ++ ## Filtering https://docs.traefik.io/observability/access-logs/#filtering + filters: {} + # statuscodes: "200,300-302" + # retryattempts: true + # minduration: 10ms +- # Fields +- # https://docs.traefik.io/observability/access-logs/#limiting-the-fieldsincluding-headers ++ ## Fields ++ ## https://docs.traefik.io/observability/access-logs/#limiting-the-fieldsincluding-headers + fields: + general: + defaultmode: keep + names: {} +- # Examples: ++ ## Examples: + # ClientUsername: drop + headers: + defaultmode: drop + names: {} +- # Examples: ++ ## Examples: + # User-Agent: redact + # Authorization: drop + # Content-Type: keep +@@ -693,10 +694,7 @@ autoscaling: + + # Enable persistence using Persistent Volume Claims + # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +-# After the pvc has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: +-# additionalArguments: +-# - "--certificatesresolvers.le.acme.storage=/data/acme.json" +-# It will persist TLS certificates. ++# It can be used to store TLS certificates, see `storage` in certResolvers + persistence: + enabled: false + name: data +@@ -726,7 +724,7 @@ certResolvers: {} + # tlsChallenge: true + # httpChallenge: + # entryPoint: "web" +-# # match the path to persistence ++# # It has to match the path with a persistent volume + # storage: /data/acme.json + + # If hostNetwork is true, runs traefik in the host network namespace +``` + +## 20.5.3 ![AppVersion: v2.9.5](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.5&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-25 + +* 🐛 Fix template issue with obsolete helm version + add helm version requirement (#743) + + +## 20.5.2 ![AppVersion: v2.9.5](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.5&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-24 + +* ⬆️Update Traefik to v2.9.5 (#740) + + +## 20.5.1 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-23 + +* 🐛 Fix namespaceSelector on ServiceMonitor (#737) + + +## 20.5.0 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-23 + +* 🚀 Add complete support on metrics options (#735) +* 🐛 make tests use fixed version + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e49d02d..15f1682 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -12,7 +12,7 @@ hub: + ## Enabling Hub will: + # * enable Traefik Hub integration on Traefik + # * add `traefikhub-tunl` endpoint +- # * enable addRoutersLabels on prometheus metrics ++ # * enable Prometheus metrics with addRoutersLabels + # * enable allowExternalNameServices on KubernetesIngress provider + # * enable allowCrossNamespace on KubernetesCRD provider + # * add an internal (ClusterIP) Service, dedicated for Traefik Hub +@@ -254,16 +254,96 @@ logs: + # Content-Type: keep + + metrics: +- # datadog: +- # address: 127.0.0.1:8125 +- # influxdb: +- # address: localhost:8089 +- # protocol: udp ++ ## Prometheus is enabled by default. ++ ## It can be disabled by setting "prometheus: null" + prometheus: ++ ## Entry point used to expose metrics. + entryPoint: metrics +- # addRoutersLabels: true +- # statsd: +- # address: localhost:8125 ++ ## Enable metrics on entry points. Default=true ++ # addEntryPointsLabels: false ++ ## Enable metrics on routers. Default=false ++ # addRoutersLabels: true ++ ## Enable metrics on services. Default=true ++ # addServicesLabels: false ++ ## Buckets for latency metrics. Default="0.1,0.3,1.2,5.0" ++ # buckets: "0.5,1.0,2.5" ++ ## When manualRouting is true, it disables the default internal router in ++ ## order to allow creating a custom router for prometheus@internal service. ++ # manualRouting: true ++# datadog: ++# ## Address instructs exporter to send metrics to datadog-agent at this address. ++# address: "127.0.0.1:8125" ++# ## The interval used by the exporter to push metrics to datadog-agent. Default=10s ++# # pushInterval: 30s ++# ## The prefix to use for metrics collection. Default="traefik" ++# # prefix: traefik ++# ## Enable metrics on entry points. Default=true ++# # addEntryPointsLabels: false ++# ## Enable metrics on routers. Default=false ++# # addRoutersLabels: true ++# ## Enable metrics on services. Default=true ++# # addServicesLabels: false ++# influxdb: ++# ## Address instructs exporter to send metrics to influxdb at this address. ++# address: localhost:8089 ++# ## InfluxDB's address protocol (udp or http). Default="udp" ++# protocol: udp ++# ## InfluxDB database used when protocol is http. Default="" ++# # database: "" ++# ## InfluxDB retention policy used when protocol is http. Default="" ++# # retentionPolicy: "" ++# ## InfluxDB username (only with http). Default="" ++# # username: "" ++# ## InfluxDB password (only with http). Default="" ++# # password: "" ++# ## The interval used by the exporter to push metrics to influxdb. Default=10s ++# # pushInterval: 30s ++# ## Additional labels (influxdb tags) on all metrics. ++# # additionalLabels: ++# # env: production ++# # foo: bar ++# ## Enable metrics on entry points. Default=true ++# # addEntryPointsLabels: false ++# ## Enable metrics on routers. Default=false ++# # addRoutersLabels: true ++# ## Enable metrics on services. Default=true ++# # addServicesLabels: false ++# influxdb2: ++# ## Address instructs exporter to send metrics to influxdb v2 at this address. ++# address: localhost:8086 ++# ## Token with which to connect to InfluxDB v2. ++# token: xxx ++# ## Organisation where metrics will be stored. ++# org: "" ++# ## Bucket where metrics will be stored. ++# bucket: "" ++# ## The interval used by the exporter to push metrics to influxdb. Default=10s ++# # pushInterval: 30s ++# ## Additional labels (influxdb tags) on all metrics. ++# # additionalLabels: ++# # env: production ++# # foo: bar ++# ## Enable metrics on entry points. Default=true ++# # addEntryPointsLabels: false ++# ## Enable metrics on routers. Default=false ++# # addRoutersLabels: true ++# ## Enable metrics on services. Default=true ++# # addServicesLabels: false ++# statsd: ++# ## Address instructs exporter to send metrics to statsd at this address. ++# address: localhost:8125 ++# ## The interval used by the exporter to push metrics to influxdb. Default=10s ++# # pushInterval: 30s ++# ## The prefix to use for metrics collection. Default="traefik" ++# # prefix: traefik ++# ## Enable metrics on entry points. Default=true ++# # addEntryPointsLabels: false ++# ## Enable metrics on routers. Default=false ++# # addRoutersLabels: true ++# ## Enable metrics on services. Default=true ++# # addServicesLabels: false ++ ++ + ## + ## enable optional CRDs for Prometheus Operator + ## +``` + +## 20.4.1 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-21 + +* 🐛 fix namespace references to support namespaceOverride + + +## 20.4.0 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-21 + +* Add (optional) dedicated metrics service (#727) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ca15f6a..e49d02d 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -267,6 +267,12 @@ metrics: + ## + ## enable optional CRDs for Prometheus Operator + ## ++ ## Create a dedicated metrics service for use with ServiceMonitor ++ ## When hub.enabled is set to true, it's not needed: it will use hub service. ++ # service: ++ # enabled: false ++ # labels: {} ++ # annotations: {} + # serviceMonitor: + # metricRelabelings: [] + # - sourceLabels: [__name__] +``` + +## 20.3.1 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-21 + +* 🐛 Fix namespace override which was missing on `ServiceAccount` (#731) + + +## 20.3.0 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-17 + +* Add overwrite option for instance label value (#725) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index c7f84a7..ca15f6a 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -731,3 +731,6 @@ extraObjects: [] + # This will override the default Release Namespace for Helm. + # It will not affect optional CRDs such as `ServiceMonitor` and `PrometheusRules` + # namespaceOverride: traefik ++# ++## This will override the default app.kubernetes.io/instance label for all Objects. ++# instanceLabelOverride: traefik +``` + +## 20.2.1 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-17 + +* 🙈 do not namespace ingress class (#723) +* ✨ copy LICENSE and README.md on release + + +## 20.2.0 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-15 + +* ✨ add support for namespace overrides (#718) +* Document recent changes in the README (#717) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 97a1b71..c7f84a7 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -725,5 +725,9 @@ podSecurityContext: + # Extra objects to deploy (value evaluated as a template) + # + # In some cases, it can avoid the need for additional, extended or adhoc deployments. +-# See #595 for more details and traefik/tests/extra.yaml for example. ++# See #595 for more details and traefik/tests/values/extra.yaml for example. + extraObjects: [] ++ ++# This will override the default Release Namespace for Helm. ++# It will not affect optional CRDs such as `ServiceMonitor` and `PrometheusRules` ++# namespaceOverride: traefik +``` + +## 20.1.1 ![AppVersion: v2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=v2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-10 + +* fix: use consistent appVersion with Traefik Proxy + + +## 20.1.0 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-09 + +* 🔧 Adds more settings for dashboard ingressRoute (#710) +* 🐛 fix chart releases + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 2ec3736..97a1b71 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -129,10 +129,14 @@ ingressRoute: + annotations: {} + # Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) + labels: {} ++ # The router match rule used for the dashboard ingressRoute ++ matchRule: PathPrefix(`/dashboard`) || PathPrefix(`/api`) + # Specify the allowed entrypoints to use for the dashboard ingress route, (e.g. traefik, web, websecure). + # By default, it's using traefik entrypoint, which is not exposed. + # /!\ Do not expose your dashboard without any protection over the internet /!\ + entryPoints: ["traefik"] ++ # Additional ingressRoute middlewares (e.g. for authentication) ++ middlewares: [] + + # Customize updateStrategy of traefik pods + updateStrategy: +``` + +## 20.0.0 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-08 + +* 🐛 remove old deployment workflow +* ✨ migrate to centralised helm repository +* Allow updateStrategy to be configurable + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 413aa88..2ec3736 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -134,9 +134,12 @@ ingressRoute: + # /!\ Do not expose your dashboard without any protection over the internet /!\ + entryPoints: ["traefik"] + +-rollingUpdate: +- maxUnavailable: 0 +- maxSurge: 1 ++# Customize updateStrategy of traefik pods ++updateStrategy: ++ type: RollingUpdate ++ rollingUpdate: ++ maxUnavailable: 0 ++ maxSurge: 1 + + # Customize liveness and readiness probe values. + readinessProbe: +``` + +## 19.0.4 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-08 + +* 🔧 Adds more settings & rename (wrong) scrapeInterval to (valid) interval on ServiceMonitor (#703) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index b24c1cb..413aa88 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -261,10 +261,6 @@ metrics: + ## enable optional CRDs for Prometheus Operator + ## + # serviceMonitor: +- # additionalLabels: +- # foo: bar +- # namespace: "another-namespace" +- # namespaceSelector: {} + # metricRelabelings: [] + # - sourceLabels: [__name__] + # separator: ; +@@ -279,9 +275,17 @@ metrics: + # replacement: $1 + # action: replace + # jobLabel: traefik +- # scrapeInterval: 30s +- # scrapeTimeout: 5s ++ # interval: 30s + # honorLabels: true ++ # # (Optional) ++ # # scrapeTimeout: 5s ++ # # honorTimestamps: true ++ # # enableHttp2: true ++ # # followRedirects: true ++ # # additionalLabels: ++ # # foo: bar ++ # # namespace: "another-namespace" ++ # # namespaceSelector: {} + # prometheusRule: + # additionalLabels: {} + # namespace: "another-namespace" +``` + +## 19.0.3 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-03 + +* 🎨 Don't require exposed Ports when enabling Hub (#700) + + +## 19.0.2 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-03 + +* :speech_balloon: Support volume secrets with '.' in name (#695) + + +## 19.0.1 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-03 + +* 🐛 Fix IngressClass install on EKS (#699) + + +## 19.0.0 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-11-02 + +* ✨ Provides Default IngressClass for Traefik by default (#693) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 69190f1..b24c1cb 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -100,11 +100,10 @@ podDisruptionBudget: + # minAvailable: 0 + # minAvailable: 25% + +-# Use ingressClass. Ignored if Traefik version < 2.3 / kubernetes < 1.18.x ++# Create a default IngressClass for Traefik + ingressClass: +- # true is not unit-testable yet, pending https://github.com/rancher/helm-unittest/pull/12 +- enabled: false +- isDefaultClass: false ++ enabled: true ++ isDefaultClass: true + + # Enable experimental features + experimental: +``` + +## 18.3.0 ![AppVersion: 2.9.4](https://img.shields.io/static/v1?label=AppVersion&message=2.9.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-31 + +* ⬆️ Update Traefik appVersion to 2.9.4 (#696) + + +## 18.2.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-31 + +* 🚩 Add an optional "internal" service (#683) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 8033a87..69190f1 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -416,7 +416,7 @@ ports: + # The port protocol (TCP/UDP) + protocol: TCP + # Use nodeport if set. This is useful if you have configured Traefik in a +- # LoadBalancer ++ # LoadBalancer. + # nodePort: 32080 + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. +@@ -549,13 +549,24 @@ service: + # - 172.16.0.0/16 + externalIPs: [] + # - 1.2.3.4 +- # One of SingleStack, PreferDualStack, or RequireDualStack. ++ ## One of SingleStack, PreferDualStack, or RequireDualStack. + # ipFamilyPolicy: SingleStack +- # List of IP families (e.g. IPv4 and/or IPv6). +- # ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services ++ ## List of IP families (e.g. IPv4 and/or IPv6). ++ ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + # ipFamilies: + # - IPv4 + # - IPv6 ++ ## ++ ## An additionnal and optional internal Service. ++ ## Same parameters as external Service ++ # internal: ++ # type: ClusterIP ++ # # labels: {} ++ # # annotations: {} ++ # # spec: {} ++ # # loadBalancerSourceRanges: [] ++ # # externalIPs: [] ++ # # ipFamilies: [ "IPv4","IPv6" ] + + ## Create HorizontalPodAutoscaler object. + ## +``` + +## 18.1.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-27 + +* 🚀 Add native support for Traefik Hub (#676) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index acce704..8033a87 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -5,6 +5,27 @@ image: + tag: "" + pullPolicy: IfNotPresent + ++# ++# Configure integration with Traefik Hub ++# ++hub: ++ ## Enabling Hub will: ++ # * enable Traefik Hub integration on Traefik ++ # * add `traefikhub-tunl` endpoint ++ # * enable addRoutersLabels on prometheus metrics ++ # * enable allowExternalNameServices on KubernetesIngress provider ++ # * enable allowCrossNamespace on KubernetesCRD provider ++ # * add an internal (ClusterIP) Service, dedicated for Traefik Hub ++ enabled: false ++ ## Default port can be changed ++ # tunnelPort: 9901 ++ ## TLS is optional. Insecure is mutually exclusive with any other options ++ # tls: ++ # insecure: false ++ # ca: "/path/to/ca.pem" ++ # cert: "/path/to/cert.pem" ++ # key: "/path/to/key.pem" ++ + # + # Configure the deployment + # +@@ -505,6 +526,8 @@ tlsStore: {} + # from. + service: + enabled: true ++ ## Single service is using `MixedProtocolLBService` feature gate. ++ ## When set to false, it will create two Service, one for TCP and one for UDP. + single: true + type: LoadBalancer + # Additional annotations applied to both TCP and UDP services (e.g. for cloud provider specific config) +``` + +## 18.0.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-26 + +* Refactor http3 and merge TCP with UDP ports into a single service (#656) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 807bd09..acce704 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -87,8 +87,6 @@ ingressClass: + + # Enable experimental features + experimental: +- http3: +- enabled: false + plugins: + enabled: false + kubernetesGateway: +@@ -421,12 +419,19 @@ ports: + # The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 +- # Enable HTTP/3. +- # Requires enabling experimental http3 feature and tls. +- # Note that you cannot have a UDP entrypoint with the same port. +- # http3: true +- # Set TLS at the entrypoint +- # https://doc.traefik.io/traefik/routing/entrypoints/#tls ++ # ++ ## Enable HTTP/3 on the entrypoint ++ ## Enabling it will also enable http3 experimental feature ++ ## https://doc.traefik.io/traefik/routing/entrypoints/#http3 ++ ## There are known limitations when trying to listen on same ports for ++ ## TCP & UDP (Http3). There is a workaround in this chart using dual Service. ++ ## https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741 ++ http3: ++ enabled: false ++ # advertisedPort: 4443 ++ # ++ ## Set TLS at the entrypoint ++ ## https://doc.traefik.io/traefik/routing/entrypoints/#tls + tls: + enabled: true + # this is the name of a TLSOption definition +@@ -500,6 +505,7 @@ tlsStore: {} + # from. + service: + enabled: true ++ single: true + type: LoadBalancer + # Additional annotations applied to both TCP and UDP services (e.g. for cloud provider specific config) + annotations: {} +``` + +## 17.0.5 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-21 + +* 📝 Add annotations changelog for artifacthub.io & update Maintainers + + +## 17.0.4 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-21 + +* :art: Add helper function for label selector + + +## 17.0.3 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-20 + +* 🐛 fix changing label selectors + + +## 17.0.2 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-20 + +* fix: setting ports.web.proxyProtocol.insecure=true + + +## 17.0.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-20 + +* :bug: Unify all labels selector with traefik chart labels (#681) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 6a90bc6..807bd09 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -639,7 +639,7 @@ affinity: {} + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: '{{ template "traefik.name" . }}' +-# app.kubernetes.io/instance: '{{ .Release.Name }}' ++# app.kubernetes.io/instance: '{{ .Release.Name }}-{{ .Release.Namespace }}' + # topologyKey: kubernetes.io/hostname + + nodeSelector: {} +``` + +## 17.0.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-20 + +* :bug: Fix `ClusterRole`, `ClusterRoleBinding` names and `app.kubernetes.io/instance` label (#662) + + +## 16.2.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-20 + +* Add forwardedHeaders and proxyProtocol config (#673) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 9b5afc4..6a90bc6 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -403,6 +403,16 @@ ports: + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection + # redirectTo: websecure ++ # ++ # Trust forwarded headers information (X-Forwarded-*). ++ # forwardedHeaders: ++ # trustedIPs: [] ++ # insecure: false ++ # ++ # Enable the Proxy Protocol header parsing for the entry point ++ # proxyProtocol: ++ # trustedIPs: [] ++ # insecure: false + websecure: + port: 8443 + # hostPort: 8443 +@@ -428,6 +438,16 @@ ports: + # - foo.example.com + # - bar.example.com + # ++ # Trust forwarded headers information (X-Forwarded-*). ++ # forwardedHeaders: ++ # trustedIPs: [] ++ # insecure: false ++ # ++ # Enable the Proxy Protocol header parsing for the entry point ++ # proxyProtocol: ++ # trustedIPs: [] ++ # insecure: false ++ # + # One can apply Middlewares on an entrypoint + # https://doc.traefik.io/traefik/middlewares/overview/ + # https://doc.traefik.io/traefik/routing/entrypoints/#middlewares +``` + +## 16.1.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-19 + +* ✨ add optional ServiceMonitor & PrometheusRules CRDs (#425) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7e335b5..9b5afc4 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -237,8 +237,46 @@ metrics: + prometheus: + entryPoint: metrics + # addRoutersLabels: true +- # statsd: +- # address: localhost:8125 ++ # statsd: ++ # address: localhost:8125 ++## ++## enable optional CRDs for Prometheus Operator ++## ++ # serviceMonitor: ++ # additionalLabels: ++ # foo: bar ++ # namespace: "another-namespace" ++ # namespaceSelector: {} ++ # metricRelabelings: [] ++ # - sourceLabels: [__name__] ++ # separator: ; ++ # regex: ^fluentd_output_status_buffer_(oldest|newest)_.+ ++ # replacement: $1 ++ # action: drop ++ # relabelings: [] ++ # - sourceLabels: [__meta_kubernetes_pod_node_name] ++ # separator: ; ++ # regex: ^(.*)$ ++ # targetLabel: nodename ++ # replacement: $1 ++ # action: replace ++ # jobLabel: traefik ++ # scrapeInterval: 30s ++ # scrapeTimeout: 5s ++ # honorLabels: true ++ # prometheusRule: ++ # additionalLabels: {} ++ # namespace: "another-namespace" ++ # rules: ++ # - alert: TraefikDown ++ # expr: up{job="traefik"} == 0 ++ # for: 5m ++ # labels: ++ # context: traefik ++ # severity: warning ++ # annotations: ++ # summary: "Traefik Down" ++ # description: "{{ $labels.pod }} on {{ $labels.nodename }} is down" + + tracing: {} + # instana: +``` + +## 16.0.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-19 + +* :fire: Remove `Pilot` and `fallbackApiVersion` (#665) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 03fdaed..7e335b5 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -84,15 +84,6 @@ ingressClass: + # true is not unit-testable yet, pending https://github.com/rancher/helm-unittest/pull/12 + enabled: false + isDefaultClass: false +- # Use to force a networking.k8s.io API Version for certain CI/CD applications. E.g. "v1beta1" +- fallbackApiVersion: "" +- +-# Activate Pilot integration +-pilot: +- enabled: false +- token: "" +- # Toggle Pilot Dashboard +- # dashboard: false + + # Enable experimental features + experimental: +``` + +## 15.3.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-18 + +* :art: Improve `IngressRoute` structure (#674) + + +## 15.3.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-18 + +* 📌 Add capacity to enable User-facing role + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 76aac93..03fdaed 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -553,10 +553,12 @@ hostNetwork: false + # Whether Role Based Access Control objects like roles and rolebindings should be created + rbac: + enabled: true +- + # If set to false, installs ClusterRole and ClusterRoleBinding so Traefik can be used across namespaces. + # If set to true, installs Role and RoleBinding. Providers will only watch target namespace. + namespaced: false ++ # Enable user-facing roles ++ # https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles ++ # aggregateTo: [ "admin" ] + + # Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding + podSecurityPolicy: +``` + +## 15.2.2 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-17 + +* Fix provider namespace changes + + +## 15.2.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-17 + +* 🐛 fix provider namespace changes + + +## 15.2.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-17 + +* :bug: Allow to watch on specific namespaces without using rbac.namespaced (#666) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 781ac15..76aac93 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -555,7 +555,7 @@ rbac: + enabled: true + + # If set to false, installs ClusterRole and ClusterRoleBinding so Traefik can be used across namespaces. +- # If set to true, installs namespace-specific Role and RoleBinding and requires provider configuration be set to that same namespace ++ # If set to true, installs Role and RoleBinding. Providers will only watch target namespace. + namespaced: false + + # Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding +``` + +## 15.1.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-17 + +* :goal_net: Fail gracefully when http3 is not enabled correctly (#667) + + +## 15.1.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-14 + +* :sparkles: add optional topologySpreadConstraints (#663) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index fc2c371..781ac15 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -593,6 +593,15 @@ affinity: {} + + nodeSelector: {} + tolerations: [] ++topologySpreadConstraints: [] ++# # This example topologySpreadConstraints forces the scheduler to put traefik pods ++# # on nodes where no other traefik pods are scheduled. ++# - labelSelector: ++# matchLabels: ++# app: '{{ template "traefik.name" . }}' ++# maxSkew: 1 ++# topologyKey: kubernetes.io/hostname ++# whenUnsatisfiable: DoNotSchedule + + # Pods can have priority. + # Priority indicates the importance of a Pod relative to other Pods. +``` + +## 15.0.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-13 + +* :rocket: Enable TLS by default on `websecure` port (#657) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 400a29a..fc2c371 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -389,7 +389,7 @@ ports: + # Set TLS at the entrypoint + # https://doc.traefik.io/traefik/routing/entrypoints/#tls + tls: +- enabled: false ++ enabled: true + # this is the name of a TLSOption definition + options: "" + certResolver: "" +``` + +## 14.0.2 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-13 + +* :memo: Add Changelog (#661) + + +## 14.0.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-11 + +* :memo: Update workaround for permissions 660 on acme.json + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index a4e4ff2..400a29a 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -45,10 +45,10 @@ deployment: + # Additional initContainers (e.g. for setting file permission as shown below) + initContainers: [] + # The "volume-permissions" init container is required if you run into permission issues. +- # Related issue: https://github.com/traefik/traefik/issues/6972 ++ # Related issue: https://github.com/traefik/traefik/issues/6825 + # - name: volume-permissions +- # image: busybox:1.31.1 +- # command: ["sh", "-c", "chmod -Rv 600 /data/*"] ++ # image: busybox:1.35 ++ # command: ["sh", "-c", "touch /data/acme.json && chmod -Rv 600 /data/* && chown 65532:65532 /data/acme.json"] + # volumeMounts: + # - name: data + # mountPath: /data +``` + +## 14.0.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-11 + +* Limit rbac to only required resources for Ingress and CRD providers + + +## 13.0.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-11 + +* Add helper function for common labels + + +## 13.0.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-11 + +* Moved list object to individual objects + + +## 12.0.7 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-10 + +* :lipstick: Affinity templating and example (#557) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 4431c36..a4e4ff2 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -578,19 +578,19 @@ resources: {} + # limits: + # cpu: "300m" + # memory: "150Mi" ++ ++# This example pod anti-affinity forces the scheduler to put traefik pods ++# on nodes where no other traefik pods are scheduled. ++# It should be used when hostNetwork: true to prevent port conflicts + affinity: {} +-# # This example pod anti-affinity forces the scheduler to put traefik pods +-# # on nodes where no other traefik pods are scheduled. +-# # It should be used when hostNetwork: true to prevent port conflicts +-# podAntiAffinity: +-# requiredDuringSchedulingIgnoredDuringExecution: +-# - labelSelector: +-# matchExpressions: +-# - key: app.kubernetes.io/name +-# operator: In +-# values: +-# - {{ template "traefik.name" . }} +-# topologyKey: kubernetes.io/hostname ++# podAntiAffinity: ++# requiredDuringSchedulingIgnoredDuringExecution: ++# - labelSelector: ++# matchLabels: ++# app.kubernetes.io/name: '{{ template "traefik.name" . }}' ++# app.kubernetes.io/instance: '{{ .Release.Name }}' ++# topologyKey: kubernetes.io/hostname ++ + nodeSelector: {} + tolerations: [] + +``` + +## 12.0.6 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-10 + +* :bug: Ignore kustomization file used for CRDs update (#653) + + +## 12.0.5 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-10 + +* :memo: Establish Traefik & CRD update process + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 3526729..4431c36 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -342,6 +342,7 @@ ports: + + # Override the liveness/readiness port. This is useful to integrate traefik + # with an external Load Balancer that performs healthchecks. ++ # Default: ports.traefik.port + # healthchecksPort: 9000 + + # Override the liveness/readiness scheme. Useful for getting ping to +``` + +## 12.0.4 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-10 + +* Allows ingressClass to be used without semver-compatible image tag + + +## 12.0.3 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-10 + +* :bug: Should check hostNetwork when hostPort != containerPort + + +## 12.0.2 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-07 + +* :goal_net: Fail gracefully when hostNetwork is enabled and hostPort != containerPort + + +## 12.0.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-07 + +* :bug: Fix a typo on `behavior` for HPA v2 + + +## 12.0.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-06 + +* Update default HPA API Version to `v2` and add support for behavior (#518) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 2bd51f8..3526729 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -488,11 +488,22 @@ autoscaling: + # - type: Resource + # resource: + # name: cpu +-# targetAverageUtilization: 60 ++# target: ++# type: Utilization ++# averageUtilization: 60 + # - type: Resource + # resource: + # name: memory +-# targetAverageUtilization: 60 ++# target: ++# type: Utilization ++# averageUtilization: 60 ++# behavior: ++# scaleDown: ++# stabilizationWindowSeconds: 300 ++# policies: ++# - type: Pods ++# value: 1 ++# periodSeconds: 60 + + # Enable persistence using Persistent Volume Claims + # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +``` + +## 11.1.1 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-05 + +* 🔊 add failure message when using maxUnavailable 0 and hostNetwork + + +## 11.1.0 ![AppVersion: 2.9.1](https://img.shields.io/static/v1?label=AppVersion&message=2.9.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-04 + +* Update Traefik to v2.9.1 + + +## 11.0.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-04 + +* tweak default values to avoid downtime when updating + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 844cadc..2bd51f8 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -126,20 +126,20 @@ ingressRoute: + entryPoints: ["traefik"] + + rollingUpdate: +- maxUnavailable: 1 ++ maxUnavailable: 0 + maxSurge: 1 + + # Customize liveness and readiness probe values. + readinessProbe: + failureThreshold: 1 +- initialDelaySeconds: 10 ++ initialDelaySeconds: 2 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + + livenessProbe: + failureThreshold: 3 +- initialDelaySeconds: 10 ++ initialDelaySeconds: 2 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 +``` + +## 10.33.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-04 + +* :rocket: Add `extraObjects` value that allows creating adhoc resources + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index c926bd9..844cadc 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -598,3 +598,10 @@ securityContext: + + podSecurityContext: + fsGroup: 65532 ++ ++# ++# Extra objects to deploy (value evaluated as a template) ++# ++# In some cases, it can avoid the need for additional, extended or adhoc deployments. ++# See #595 for more details and traefik/tests/extra.yaml for example. ++extraObjects: [] +``` + +## 10.32.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-03 + +* Add support setting middleware on entrypoint + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 3957448..c926bd9 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -397,6 +397,16 @@ ports: + # sans: + # - foo.example.com + # - bar.example.com ++ # ++ # One can apply Middlewares on an entrypoint ++ # https://doc.traefik.io/traefik/middlewares/overview/ ++ # https://doc.traefik.io/traefik/routing/entrypoints/#middlewares ++ # /!\ It introduces here a link between your static configuration and your dynamic configuration /!\ ++ # It follows the provider naming convention: https://doc.traefik.io/traefik/providers/overview/#provider-namespace ++ # middlewares: ++ # - namespace-name1@kubernetescrd ++ # - namespace-name2@kubernetescrd ++ middlewares: [] + metrics: + # When using hostNetwork, use another port to avoid conflict with node exporter: + # https://github.com/prometheus/prometheus/wiki/Default-port-allocations +``` + +## 10.31.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-03 + +* Support setting dashboard entryPoints for ingressRoute resource + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index c9feb76..3957448 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -120,6 +120,10 @@ ingressRoute: + annotations: {} + # Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) + labels: {} ++ # Specify the allowed entrypoints to use for the dashboard ingress route, (e.g. traefik, web, websecure). ++ # By default, it's using traefik entrypoint, which is not exposed. ++ # /!\ Do not expose your dashboard without any protection over the internet /!\ ++ entryPoints: ["traefik"] + + rollingUpdate: + maxUnavailable: 1 +``` + +## 10.30.2 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-10-03 + +* :test_tube: Fail gracefully when asked to provide a service without ports + + +## 10.30.1 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-30 + +* :arrow_up: Upgrade helm, ct & unittest (#638) + + +## 10.30.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-30 + +* Add support HTTPS scheme for healthcheks + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index fed4a8a..c9feb76 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -340,6 +340,10 @@ ports: + # with an external Load Balancer that performs healthchecks. + # healthchecksPort: 9000 + ++ # Override the liveness/readiness scheme. Useful for getting ping to ++ # respond on websecure entryPoint. ++ # healthchecksScheme: HTTPS ++ + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # +``` + +## 10.29.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-29 + +* Add missing tracing options + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d1708cc..fed4a8a 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -247,12 +247,45 @@ metrics: + + tracing: {} + # instana: +- # enabled: true ++ # localAgentHost: 127.0.0.1 ++ # localAgentPort: 42699 ++ # logLevel: info ++ # enableAutoProfile: true + # datadog: + # localAgentHostPort: 127.0.0.1:8126 + # debug: false + # globalTag: "" + # prioritySampling: false ++ # jaeger: ++ # samplingServerURL: http://localhost:5778/sampling ++ # samplingType: const ++ # samplingParam: 1.0 ++ # localAgentHostPort: 127.0.0.1:6831 ++ # gen128Bit: false ++ # propagation: jaeger ++ # traceContextHeaderName: uber-trace-id ++ # disableAttemptReconnecting: true ++ # collector: ++ # endpoint: "" ++ # user: "" ++ # password: "" ++ # zipkin: ++ # httpEndpoint: http://localhost:9411/api/v2/spans ++ # sameSpan: false ++ # id128Bit: true ++ # sampleRate: 1.0 ++ # haystack: ++ # localAgentHost: 127.0.0.1 ++ # localAgentPort: 35000 ++ # globalTag: "" ++ # traceIDHeaderName: "" ++ # parentIDHeaderName: "" ++ # spanIDHeaderName: "" ++ # baggagePrefixHeaderName: "" ++ # elastic: ++ # serverURL: http://localhost:8200 ++ # secretToken: "" ++ # serviceEnvironment: "" + + globalArguments: + - "--global.checknewversion" +``` + +## 10.28.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-29 + +* feat: add lifecycle for prestop and poststart + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 19a133c..d1708cc 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -59,6 +59,17 @@ deployment: + # Additional imagePullSecrets + imagePullSecrets: [] + # - name: myRegistryKeySecretName ++ # Pod lifecycle actions ++ lifecycle: {} ++ # preStop: ++ # exec: ++ # command: ["/bin/sh", "-c", "sleep 40"] ++ # postStart: ++ # httpGet: ++ # path: /ping ++ # port: 9000 ++ # host: localhost ++ # scheme: HTTP + + # Pod disruption budget + podDisruptionBudget: +``` + +## 10.27.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-29 + +* feat: add create gateway option + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d9c745e..19a133c 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -91,6 +91,8 @@ experimental: + enabled: false + kubernetesGateway: + enabled: false ++ gateway: ++ enabled: true + # certificate: + # group: "core" + # kind: "Secret" +``` + +## 10.26.1 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-28 + +* 🐛 fix rbac templating (#636) + + +## 10.26.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-28 + +* :bug: Fix ingressClass support when rbac.namespaced=true (#499) + + +## 10.25.1 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-28 + +* Add ingressclasses to traefik role + + +## 10.25.0 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-27 + +* Add TLSStore resource to chart + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d4011c3..d9c745e 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -373,6 +373,15 @@ ports: + # - CurveP384 + tlsOptions: {} + ++# TLS Store are created as TLSStore CRDs. This is useful if you want to set a default certificate ++# https://doc.traefik.io/traefik/https/tls/#default-certificate ++# Example: ++# tlsStore: ++# default: ++# defaultCertificate: ++# secretName: tls-cert ++tlsStore: {} ++ + # Options for the main traefik service, where the entrypoints traffic comes + # from. + service: +``` + +## 10.24.5 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-27 + +* Suggest an alternative port for metrics + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 81f2e85..d4011c3 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -344,6 +344,8 @@ ports: + # - foo.example.com + # - bar.example.com + metrics: ++ # When using hostNetwork, use another port to avoid conflict with node exporter: ++ # https://github.com/prometheus/prometheus/wiki/Default-port-allocations + port: 9100 + # hostPort: 9100 + # Defines whether the port is exposed if service.type is LoadBalancer or +``` + +## 10.24.4 ![AppVersion: 2.8.7](https://img.shields.io/static/v1?label=AppVersion&message=2.8.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-26 + +* Update Traefik to v2.8.7 + + +## 10.24.3 ![AppVersion: 2.8.5](https://img.shields.io/static/v1?label=AppVersion&message=2.8.5&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-14 + +* Update Traefik version to v2.8.5 + + +## 10.24.2 ![AppVersion: 2.8.4](https://img.shields.io/static/v1?label=AppVersion&message=2.8.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-09-05 + +* Update Traefik version to v2.8.4 + + +## 10.24.1 ![AppVersion: 2.8.0](https://img.shields.io/static/v1?label=AppVersion&message=2.8.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-08-29 + +* Update PodDisruptionBudget apiVersion to policy/v1 + + +## 10.24.0 ![AppVersion: 2.8.0](https://img.shields.io/static/v1?label=AppVersion&message=2.8.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-06-30 + +* Update Traefik version to v2.8.0 + + +## 10.23.0 ![AppVersion: 2.7.1](https://img.shields.io/static/v1?label=AppVersion&message=2.7.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-06-27 + +* Support environment variable usage for Datadog + + +## 10.22.0 ![AppVersion: 2.7.1](https://img.shields.io/static/v1?label=AppVersion&message=2.7.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-06-22 + +* Allow setting revisionHistoryLimit for Deployment and DaemonSet + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d5785ab..81f2e85 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -14,6 +14,8 @@ deployment: + kind: Deployment + # Number of pods of the deployment (only applies when kind == Deployment) + replicas: 1 ++ # Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) ++ # revisionHistoryLimit: 1 + # Amount of time (in seconds) before Kubernetes will send the SIGKILL signal if Traefik does not shut down + terminationGracePeriodSeconds: 60 + # The minimum number of seconds Traefik needs to be up and running before the DaemonSet/Deployment controller considers it available +``` + +## 10.21.1 ![AppVersion: 2.7.1](https://img.shields.io/static/v1?label=AppVersion&message=2.7.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-06-15 + +* Update Traefik version to 2.7.1 + + +## 10.21.0 ![AppVersion: 2.7.0](https://img.shields.io/static/v1?label=AppVersion&message=2.7.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-06-15 + +* Support allowEmptyServices config for KubernetesCRD + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e141e29..d5785ab 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -133,6 +133,7 @@ providers: + enabled: true + allowCrossNamespace: false + allowExternalNameServices: false ++ allowEmptyServices: false + # ingressClass: traefik-internal + # labelSelector: environment=production,method=traefik + namespaces: [] +``` + +## 10.20.1 ![AppVersion: 2.7.0](https://img.shields.io/static/v1?label=AppVersion&message=2.7.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-06-01 + +* Add Acme certificate resolver configuration + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index a16b107..e141e29 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -433,6 +433,27 @@ persistence: + annotations: {} + # subPath: "" # only mount a subpath of the Volume into the pod + ++certResolvers: {} ++# letsencrypt: ++# # for challenge options cf. https://doc.traefik.io/traefik/https/acme/ ++# email: email@example.com ++# dnsChallenge: ++# # also add the provider's required configuration under env ++# # or expand then from secrets/configmaps with envfrom ++# # cf. https://doc.traefik.io/traefik/https/acme/#providers ++# provider: digitalocean ++# # add futher options for the dns challenge as needed ++# # cf. https://doc.traefik.io/traefik/https/acme/#dnschallenge ++# delayBeforeCheck: 30 ++# resolvers: ++# - 1.1.1.1 ++# - 8.8.8.8 ++# tlsChallenge: true ++# httpChallenge: ++# entryPoint: "web" ++# # match the path to persistence ++# storage: /data/acme.json ++ + # If hostNetwork is true, runs traefik in the host network namespace + # To prevent unschedulabel pods due to port collisions, if hostNetwork=true + # and replicas>1, a pod anti-affinity is recommended and will be set if the +``` + +## 10.20.0 ![AppVersion: 2.7.0](https://img.shields.io/static/v1?label=AppVersion&message=2.7.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-05-25 + +* Update Traefik Proxy to v2.7.0 + + +## 10.19.5 ![AppVersion: 2.6.6](https://img.shields.io/static/v1?label=AppVersion&message=2.6.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-05-04 + +* Upgrade Traefik to 2.6.6 + + +## 10.19.4 ![AppVersion: 2.6.3](https://img.shields.io/static/v1?label=AppVersion&message=2.6.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-31 + +* Update Traefik dependency version to 2.6.3 + + +## 10.19.3 ![AppVersion: 2.6.2](https://img.shields.io/static/v1?label=AppVersion&message=2.6.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-30 + +* Update CRDs to match the ones defined in the reference documentation + + +## 10.19.2 ![AppVersion: 2.6.2](https://img.shields.io/static/v1?label=AppVersion&message=2.6.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-30 + +* Revert Traefik version to 2.6.2 + + +## 10.19.1 ![AppVersion: 2.6.3](https://img.shields.io/static/v1?label=AppVersion&message=2.6.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-30 + +* Update Traefik version to 2.6.3 + + +## 10.19.0 ![AppVersion: 2.6.2](https://img.shields.io/static/v1?label=AppVersion&message=2.6.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-28 + +* Support ingressClass option for KubernetesIngress provider + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 02ab704..a16b107 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -142,6 +142,7 @@ providers: + enabled: true + allowExternalNameServices: false + allowEmptyServices: false ++ # ingressClass: traefik-internal + # labelSelector: environment=production,method=traefik + namespaces: [] + # - "default" +``` + +## 10.18.0 ![AppVersion: 2.6.2](https://img.shields.io/static/v1?label=AppVersion&message=2.6.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-28 + +* Support liveness and readyness probes customization + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 15f1103..02ab704 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -110,6 +110,20 @@ rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + ++# Customize liveness and readiness probe values. ++readinessProbe: ++ failureThreshold: 1 ++ initialDelaySeconds: 10 ++ periodSeconds: 10 ++ successThreshold: 1 ++ timeoutSeconds: 2 ++ ++livenessProbe: ++ failureThreshold: 3 ++ initialDelaySeconds: 10 ++ periodSeconds: 10 ++ successThreshold: 1 ++ timeoutSeconds: 2 + + # + # Configure providers +``` + +## 10.17.0 ![AppVersion: 2.6.2](https://img.shields.io/static/v1?label=AppVersion&message=2.6.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-28 + +* Support Datadog tracing + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 4dccd1a..15f1103 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -217,6 +217,11 @@ metrics: + tracing: {} + # instana: + # enabled: true ++ # datadog: ++ # localAgentHostPort: 127.0.0.1:8126 ++ # debug: false ++ # globalTag: "" ++ # prioritySampling: false + + globalArguments: + - "--global.checknewversion" +``` + +## 10.16.1 ![AppVersion: 2.6.2](https://img.shields.io/static/v1?label=AppVersion&message=2.6.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-28 + +* Update Traefik version to 2.6.2 + + +## 10.16.0 ![AppVersion: 2.6.1](https://img.shields.io/static/v1?label=AppVersion&message=2.6.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-28 + +* Support allowEmptyServices for KubernetesIngress provider + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 1f9dbbe..4dccd1a 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -127,6 +127,7 @@ providers: + kubernetesIngress: + enabled: true + allowExternalNameServices: false ++ allowEmptyServices: false + # labelSelector: environment=production,method=traefik + namespaces: [] + # - "default" +``` + +## 10.15.0 ![AppVersion: 2.6.1](https://img.shields.io/static/v1?label=AppVersion&message=2.6.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-03-08 + +* Add metrics.prometheus.addRoutersLabels option + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index cd4d49b..1f9dbbe 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -209,6 +209,7 @@ metrics: + # protocol: udp + prometheus: + entryPoint: metrics ++ # addRoutersLabels: true + # statsd: + # address: localhost:8125 + +``` + +## 10.14.2 ![AppVersion: 2.6.1](https://img.shields.io/static/v1?label=AppVersion&message=2.6.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-02-18 + +* Update Traefik to v2.6.1 + + +## 10.14.1 ![AppVersion: 2.6.0](https://img.shields.io/static/v1?label=AppVersion&message=2.6.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-02-09 + +* Add missing inFlightConn TCP middleware CRD + + +## 10.14.0 ![AppVersion: 2.6.0](https://img.shields.io/static/v1?label=AppVersion&message=2.6.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-02-03 + +* Add experimental HTTP/3 support + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d49122f..cd4d49b 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -83,6 +83,8 @@ pilot: + + # Enable experimental features + experimental: ++ http3: ++ enabled: false + plugins: + enabled: false + kubernetesGateway: +@@ -300,6 +302,10 @@ ports: + # The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 ++ # Enable HTTP/3. ++ # Requires enabling experimental http3 feature and tls. ++ # Note that you cannot have a UDP entrypoint with the same port. ++ # http3: true + # Set TLS at the entrypoint + # https://doc.traefik.io/traefik/routing/entrypoints/#tls + tls: +``` + +## 10.13.0 ![AppVersion: 2.6.0](https://img.shields.io/static/v1?label=AppVersion&message=2.6.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-02-01 + +* Add support for ipFamilies + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 32fce6f..d49122f 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -366,6 +366,11 @@ service: + # - 1.2.3.4 + # One of SingleStack, PreferDualStack, or RequireDualStack. + # ipFamilyPolicy: SingleStack ++ # List of IP families (e.g. IPv4 and/or IPv6). ++ # ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services ++ # ipFamilies: ++ # - IPv4 ++ # - IPv6 + + ## Create HorizontalPodAutoscaler object. + ## +``` + +## 10.12.0 ![AppVersion: 2.6.0](https://img.shields.io/static/v1?label=AppVersion&message=2.6.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-02-01 + +* Add shareProcessNamespace option to podtemplate + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ab25456..32fce6f 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -50,6 +50,8 @@ deployment: + # volumeMounts: + # - name: data + # mountPath: /data ++ # Use process namespace sharing ++ shareProcessNamespace: false + # Custom pod DNS policy. Apply if `hostNetwork: true` + # dnsPolicy: ClusterFirstWithHostNet + # Additional imagePullSecrets +``` + +## 10.11.1 ![AppVersion: 2.6.0](https://img.shields.io/static/v1?label=AppVersion&message=2.6.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-01-31 + +* Fix anti-affinity example + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 8c72905..ab25456 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -438,13 +438,13 @@ affinity: {} + # # It should be used when hostNetwork: true to prevent port conflicts + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: +-# - labelSelector: +-# matchExpressions: +-# - key: app +-# operator: In +-# values: +-# - {{ template "traefik.name" . }} +-# topologyKey: failure-domain.beta.kubernetes.io/zone ++# - labelSelector: ++# matchExpressions: ++# - key: app.kubernetes.io/name ++# operator: In ++# values: ++# - {{ template "traefik.name" . }} ++# topologyKey: kubernetes.io/hostname + nodeSelector: {} + tolerations: [] + +``` + +## 10.11.0 ![AppVersion: 2.6.0](https://img.shields.io/static/v1?label=AppVersion&message=2.6.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-01-31 + +* Add setting to enable Instana tracing + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7fe4a2c..8c72905 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -208,6 +208,10 @@ metrics: + # statsd: + # address: localhost:8125 + ++tracing: {} ++ # instana: ++ # enabled: true ++ + globalArguments: + - "--global.checknewversion" + - "--global.sendanonymoususage" +``` + +## 10.10.0 ![AppVersion: 2.6.0](https://img.shields.io/static/v1?label=AppVersion&message=2.6.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2022-01-31 + +* Update Traefik to v2.6 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 8ae4bd8..7fe4a2c 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -85,9 +85,8 @@ experimental: + enabled: false + kubernetesGateway: + enabled: false +- appLabelSelector: "traefik" +- certificates: [] +- # - group: "core" ++ # certificate: ++ # group: "core" + # kind: "Secret" + # name: "mysecret" + # By default, Gateway would be created to the Namespace you are deploying Traefik to. +``` + +## 10.9.1 ![AppVersion: 2.5.6](https://img.shields.io/static/v1?label=AppVersion&message=2.5.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-12-24 + +* Bump traefik version to 2.5.6 + + +## 10.9.0 ![AppVersion: 2.5.4](https://img.shields.io/static/v1?label=AppVersion&message=2.5.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-12-20 + +* feat: add allowExternalNameServices to KubernetesIngress provider + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 79df205..8ae4bd8 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -123,6 +123,7 @@ providers: + + kubernetesIngress: + enabled: true ++ allowExternalNameServices: false + # labelSelector: environment=production,method=traefik + namespaces: [] + # - "default" +``` + +## 10.8.0 ![AppVersion: 2.5.4](https://img.shields.io/static/v1?label=AppVersion&message=2.5.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-12-20 + +* Add support to specify minReadySeconds on Deployment/DaemonSet + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7e9186b..79df205 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -16,6 +16,8 @@ deployment: + replicas: 1 + # Amount of time (in seconds) before Kubernetes will send the SIGKILL signal if Traefik does not shut down + terminationGracePeriodSeconds: 60 ++ # The minimum number of seconds Traefik needs to be up and running before the DaemonSet/Deployment controller considers it available ++ minReadySeconds: 0 + # Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} + # Additional deployment labels (e.g. for filtering deployment by custom labels) +``` + +## 10.7.1 ![AppVersion: 2.5.4](https://img.shields.io/static/v1?label=AppVersion&message=2.5.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-12-06 + +* Fix pod disruption when using percentages + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e0655c8..7e9186b 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -52,13 +52,15 @@ deployment: + # dnsPolicy: ClusterFirstWithHostNet + # Additional imagePullSecrets + imagePullSecrets: [] +- # - name: myRegistryKeySecretName ++ # - name: myRegistryKeySecretName + + # Pod disruption budget + podDisruptionBudget: + enabled: false + # maxUnavailable: 1 ++ # maxUnavailable: 33% + # minAvailable: 0 ++ # minAvailable: 25% + + # Use ingressClass. Ignored if Traefik version < 2.3 / kubernetes < 1.18.x + ingressClass: +``` + +## 10.7.0 ![AppVersion: 2.5.4](https://img.shields.io/static/v1?label=AppVersion&message=2.5.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-12-06 + +* Add support for ipFamilyPolicy + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 3ec7105..e0655c8 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -343,8 +343,8 @@ service: + annotationsUDP: {} + # Additional service labels (e.g. for filtering Service by custom labels) + labels: {} +- # Additional entries here will be added to the service spec. Cannot contains +- # type, selector or ports entries. ++ # Additional entries here will be added to the service spec. ++ # Cannot contain type, selector or ports entries. + spec: {} + # externalTrafficPolicy: Cluster + # loadBalancerIP: "1.2.3.4" +@@ -354,6 +354,8 @@ service: + # - 172.16.0.0/16 + externalIPs: [] + # - 1.2.3.4 ++ # One of SingleStack, PreferDualStack, or RequireDualStack. ++ # ipFamilyPolicy: SingleStack + + ## Create HorizontalPodAutoscaler object. + ## +``` + +## 10.6.2 ![AppVersion: 2.5.4](https://img.shields.io/static/v1?label=AppVersion&message=2.5.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-11-15 + +* Bump Traefik version to 2.5.4 + + +## 10.6.1 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-11-05 + +* Add missing Gateway API resources to ClusterRole + + +## 10.6.0 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-10-13 + +* feat: allow termination grace period to be configurable + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index f06ebc6..3ec7105 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -14,6 +14,8 @@ deployment: + kind: Deployment + # Number of pods of the deployment (only applies when kind == Deployment) + replicas: 1 ++ # Amount of time (in seconds) before Kubernetes will send the SIGKILL signal if Traefik does not shut down ++ terminationGracePeriodSeconds: 60 + # Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} + # Additional deployment labels (e.g. for filtering deployment by custom labels) +``` + +## 10.5.0 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-10-13 + +* feat: add allowExternalNameServices to Kubernetes CRD provider + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 3bcb350..f06ebc6 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -109,6 +109,7 @@ providers: + kubernetesCRD: + enabled: true + allowCrossNamespace: false ++ allowExternalNameServices: false + # ingressClass: traefik-internal + # labelSelector: environment=production,method=traefik + namespaces: [] +``` + +## 10.4.2 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-10-13 + +* fix(crd): add permissionsPolicy to headers middleware + + +## 10.4.1 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-10-13 + +* fix(crd): add peerCertURI option to ServersTransport + + +## 10.4.0 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-10-12 + +* Add Kubernetes CRD labelSelector and ingressClass options + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index f54f5fe..3bcb350 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -109,8 +109,11 @@ providers: + kubernetesCRD: + enabled: true + allowCrossNamespace: false ++ # ingressClass: traefik-internal ++ # labelSelector: environment=production,method=traefik + namespaces: [] + # - "default" ++ + kubernetesIngress: + enabled: true + # labelSelector: environment=production,method=traefik +``` + +## 10.3.6 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-09-24 + +* Fix missing RequireAnyClientCert value to TLSOption CRD + + +## 10.3.5 ![AppVersion: 2.5.3](https://img.shields.io/static/v1?label=AppVersion&message=2.5.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-09-23 + +* Bump Traefik version to 2.5.3 + + +## 10.3.4 ![AppVersion: 2.5.1](https://img.shields.io/static/v1?label=AppVersion&message=2.5.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-09-17 + +* Add allowCrossNamespace option on kubernetesCRD provider + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7e3a579..f54f5fe 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -108,6 +108,7 @@ rollingUpdate: + providers: + kubernetesCRD: + enabled: true ++ allowCrossNamespace: false + namespaces: [] + # - "default" + kubernetesIngress: +``` + +## 10.3.3 ![AppVersion: 2.5.1](https://img.shields.io/static/v1?label=AppVersion&message=2.5.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-09-17 + +* fix(crd): missing alpnProtocols in TLSOption + + +## 10.3.2 ![AppVersion: 2.5.1](https://img.shields.io/static/v1?label=AppVersion&message=2.5.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-23 + +* Releasing 2.5.1 + + +## 10.3.1 ![AppVersion: 2.5.0](https://img.shields.io/static/v1?label=AppVersion&message=2.5.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-20 + +* Fix Ingress RBAC for namespaced scoped deployment + + +## 10.3.0 ![AppVersion: 2.5.0](https://img.shields.io/static/v1?label=AppVersion&message=2.5.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-18 + +* Releasing Traefik 2.5.0 + + +## 10.2.0 ![AppVersion: 2.4.13](https://img.shields.io/static/v1?label=AppVersion&message=2.4.13&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-18 + +* Allow setting TCP and UDP service annotations separately + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 72a01ea..7e3a579 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -328,8 +328,12 @@ tlsOptions: {} + service: + enabled: true + type: LoadBalancer +- # Additional annotations (e.g. for cloud provider specific config) ++ # Additional annotations applied to both TCP and UDP services (e.g. for cloud provider specific config) + annotations: {} ++ # Additional annotations for TCP service only ++ annotationsTCP: {} ++ # Additional annotations for UDP service only ++ annotationsUDP: {} + # Additional service labels (e.g. for filtering Service by custom labels) + labels: {} + # Additional entries here will be added to the service spec. Cannot contains +``` + +## 10.1.6 ![AppVersion: 2.4.13](https://img.shields.io/static/v1?label=AppVersion&message=2.4.13&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-17 + +* fix: missing service labels + + +## 10.1.5 ![AppVersion: 2.4.13](https://img.shields.io/static/v1?label=AppVersion&message=2.4.13&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-17 + +* fix(pvc-annotaions): see traefik/traefik-helm-chart#471 + + +## 10.1.4 ![AppVersion: 2.4.13](https://img.shields.io/static/v1?label=AppVersion&message=2.4.13&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-17 + +* fix(ingressclass): fallbackApiVersion default shouldn't be `nil` + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 04d336c..72a01ea 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -64,7 +64,7 @@ ingressClass: + enabled: false + isDefaultClass: false + # Use to force a networking.k8s.io API Version for certain CI/CD applications. E.g. "v1beta1" +- fallbackApiVersion: ++ fallbackApiVersion: "" + + # Activate Pilot integration + pilot: +``` + +## 10.1.3 ![AppVersion: 2.4.13](https://img.shields.io/static/v1?label=AppVersion&message=2.4.13&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-16 + +* Move Prometheus annotations to Pods + + +## 10.1.2 ![AppVersion: 2.4.13](https://img.shields.io/static/v1?label=AppVersion&message=2.4.13&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-08-10 + +* Version bumped 2.4.13 + + +## 10.1.1 ![AppVersion: 2.4.9](https://img.shields.io/static/v1?label=AppVersion&message=2.4.9&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-07-20 + +* Fixing Prometheus.io/port annotation + + +## 10.1.0 ![AppVersion: 2.4.9](https://img.shields.io/static/v1?label=AppVersion&message=2.4.9&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-07-20 + +* Add metrics framework, and prom annotations + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index f6e370a..04d336c 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -186,6 +186,17 @@ logs: + # Authorization: drop + # Content-Type: keep + ++metrics: ++ # datadog: ++ # address: 127.0.0.1:8125 ++ # influxdb: ++ # address: localhost:8089 ++ # protocol: udp ++ prometheus: ++ entryPoint: metrics ++ # statsd: ++ # address: localhost:8125 ++ + globalArguments: + - "--global.checknewversion" + - "--global.sendanonymoususage" +@@ -284,6 +295,20 @@ ports: + # sans: + # - foo.example.com + # - bar.example.com ++ metrics: ++ port: 9100 ++ # hostPort: 9100 ++ # Defines whether the port is exposed if service.type is LoadBalancer or ++ # NodePort. ++ # ++ # You may not want to expose the metrics port on production deployments. ++ # If you want to access it from outside of your cluster, ++ # use `kubectl port-forward` or create a secure ingress ++ expose: false ++ # The exposed port for this service ++ exposedPort: 9100 ++ # The port protocol (TCP/UDP) ++ protocol: TCP + + # TLS Options are created as TLSOption CRDs + # https://doc.traefik.io/traefik/https/tls/#tls-options +``` + +## 10.0.2 ![AppVersion: 2.4.9](https://img.shields.io/static/v1?label=AppVersion&message=2.4.9&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-07-14 + +* feat(gateway): introduces param / pick Namespace installing Gateway + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 9bf90ea..f6e370a 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -84,6 +84,9 @@ experimental: + # - group: "core" + # kind: "Secret" + # name: "mysecret" ++ # By default, Gateway would be created to the Namespace you are deploying Traefik to. ++ # You may create that Gateway in another namespace, setting its name below: ++ # namespace: default + + # Create an IngressRoute for the dashboard + ingressRoute: +``` + +## 10.0.1 ![AppVersion: 2.4.9](https://img.shields.io/static/v1?label=AppVersion&message=2.4.9&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-07-14 + +* Add RBAC for middlewaretcps + + +## 10.0.0 ![AppVersion: 2.4.9](https://img.shields.io/static/v1?label=AppVersion&message=2.4.9&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-07-07 + +* Update CRD versions + + +## 9.20.1 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-07-05 + +* Revert CRD templating + + +## 9.20.0 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-07-05 + +* Add support for apiextensions v1 CRDs + + +## 9.19.2 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-06-16 + +* Add name-metadata for service "List" object + + +## 9.19.1 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-05-13 + +* fix simple typo + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index b30afac..9bf90ea 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -363,7 +363,7 @@ rbac: + # If set to true, installs namespace-specific Role and RoleBinding and requires provider configuration be set to that same namespace + namespaced: false + +-# Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBindin or ClusterRoleBinding ++# Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding + podSecurityPolicy: + enabled: false + +``` + +## 9.19.0 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-04-29 + +* Fix IngressClass api version + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 0aa2d6b..b30afac 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -63,6 +63,8 @@ ingressClass: + # true is not unit-testable yet, pending https://github.com/rancher/helm-unittest/pull/12 + enabled: false + isDefaultClass: false ++ # Use to force a networking.k8s.io API Version for certain CI/CD applications. E.g. "v1beta1" ++ fallbackApiVersion: + + # Activate Pilot integration + pilot: +``` + +## 9.18.3 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-04-26 + +* Fix: ignore provider namespace args on disabled + + +## 9.18.2 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-04-02 + +* Fix pilot dashboard deactivation + + +## 9.18.1 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-29 + +* Do not disable Traefik Pilot in the dashboard by default + + +## 9.18.0 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-24 + +* Add an option to toggle the pilot dashboard + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 017f771..0aa2d6b 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -68,6 +68,8 @@ ingressClass: + pilot: + enabled: false + token: "" ++ # Toggle Pilot Dashboard ++ # dashboard: false + + # Enable experimental features + experimental: +``` + +## 9.17.6 ![AppVersion: 2.4.8](https://img.shields.io/static/v1?label=AppVersion&message=2.4.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-24 + +* Bump Traefik to 2.4.8 + + +## 9.17.5 ![AppVersion: 2.4.7](https://img.shields.io/static/v1?label=AppVersion&message=2.4.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-17 + +* feat(labelSelector): option matching Ingresses based on labelSelectors + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 868a985..017f771 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -105,6 +105,7 @@ providers: + # - "default" + kubernetesIngress: + enabled: true ++ # labelSelector: environment=production,method=traefik + namespaces: [] + # - "default" + # IP used for Kubernetes Ingress endpoints +``` + +## 9.17.4 ![AppVersion: 2.4.7](https://img.shields.io/static/v1?label=AppVersion&message=2.4.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-17 + +* Add helm resource-policy annotation on PVC + + +## 9.17.3 ![AppVersion: 2.4.7](https://img.shields.io/static/v1?label=AppVersion&message=2.4.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-17 + +* Throw error with explicit latest tag + + +## 9.17.2 ![AppVersion: 2.4.7](https://img.shields.io/static/v1?label=AppVersion&message=2.4.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-10 + +* fix(keywords): removed by mistake + + +## 9.17.1 ![AppVersion: 2.4.7](https://img.shields.io/static/v1?label=AppVersion&message=2.4.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-10 + +* feat(healthchecksPort): Support for overriding the liveness/readiness probes port + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 56abb93..868a985 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -120,6 +120,8 @@ providers: + # After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: + # additionalArguments: + # - "--providers.file.filename=/config/dynamic.toml" ++# - "--ping" ++# - "--ping.entrypoint=web" + volumes: [] + # - name: public-cert + # mountPath: "/certs" +@@ -225,6 +227,10 @@ ports: + # only. + # hostIP: 192.168.100.10 + ++ # Override the liveness/readiness port. This is useful to integrate traefik ++ # with an external Load Balancer that performs healthchecks. ++ # healthchecksPort: 9000 ++ + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # +``` + +## 9.16.2 ![AppVersion: 2.4.7](https://img.shields.io/static/v1?label=AppVersion&message=2.4.7&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-09 + +* Bump Traefik to 2.4.7 + + +## 9.16.1 ![AppVersion: 2.4.6](https://img.shields.io/static/v1?label=AppVersion&message=2.4.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-09 + +* Adding custom labels to deployment + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ba24be7..56abb93 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -16,6 +16,8 @@ deployment: + replicas: 1 + # Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} ++ # Additional deployment labels (e.g. for filtering deployment by custom labels) ++ labels: {} + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} + # Additional Pod labels (e.g. for filtering Pod by custom labels) +``` + +## 9.15.2 ![AppVersion: 2.4.6](https://img.shields.io/static/v1?label=AppVersion&message=2.4.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-02 + +* Upgrade Traefik to 2.4.6 + + +## 9.15.1 ![AppVersion: 2.4.5](https://img.shields.io/static/v1?label=AppVersion&message=2.4.5&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-02 + +* Configurable PVC name + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 1e0e5a9..ba24be7 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -327,6 +327,7 @@ autoscaling: + # It will persist TLS certificates. + persistence: + enabled: false ++ name: data + # existingClaim: "" + accessMode: ReadWriteOnce + size: 128Mi +``` + +## 9.14.4 ![AppVersion: 2.4.5](https://img.shields.io/static/v1?label=AppVersion&message=2.4.5&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-03-02 + +* fix typo + + +## 9.14.3 ![AppVersion: 2.4.5](https://img.shields.io/static/v1?label=AppVersion&message=2.4.5&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-02-19 + +* Bump Traefik to 2.4.5 + + +## 9.14.2 ![AppVersion: 2.4.2](https://img.shields.io/static/v1?label=AppVersion&message=2.4.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-02-03 + +* docs: indent nit for dsdsocket example + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 56485ad..1e0e5a9 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -33,7 +33,7 @@ deployment: + additionalVolumes: [] + # - name: dsdsocket + # hostPath: +- # path: /var/run/statsd-exporter ++ # path: /var/run/statsd-exporter + # Additional initContainers (e.g. for setting file permission as shown below) + initContainers: [] + # The "volume-permissions" init container is required if you run into permission issues. +``` + +## 9.14.1 ![AppVersion: 2.4.2](https://img.shields.io/static/v1?label=AppVersion&message=2.4.2&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-02-03 + +* Update Traefik to 2.4.2 + + +## 9.14.0 ![AppVersion: 2.4.0](https://img.shields.io/static/v1?label=AppVersion&message=2.4.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-02-01 + +* Enable Kubernetes Gateway provider with an experimental flag + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 50cab94..56485ad 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -71,6 +71,13 @@ pilot: + experimental: + plugins: + enabled: false ++ kubernetesGateway: ++ enabled: false ++ appLabelSelector: "traefik" ++ certificates: [] ++ # - group: "core" ++ # kind: "Secret" ++ # name: "mysecret" + + # Create an IngressRoute for the dashboard + ingressRoute: +``` + +## 9.13.0 ![AppVersion: 2.4.0](https://img.shields.io/static/v1?label=AppVersion&message=2.4.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2021-01-22 + +* Update Traefik to 2.4 and add resources + + +## 9.12.3 ![AppVersion: 2.3.6](https://img.shields.io/static/v1?label=AppVersion&message=2.3.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-12-31 + +* Revert API Upgrade + + +## 9.12.2 ![AppVersion: 2.3.6](https://img.shields.io/static/v1?label=AppVersion&message=2.3.6&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-12-31 + +* Bump Traefik to 2.3.6 + + +## 9.12.1 ![AppVersion: 2.3.3](https://img.shields.io/static/v1?label=AppVersion&message=2.3.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-12-30 + +* Resolve #303, change CRD version from v1beta1 to v1 + + +## 9.12.0 ![AppVersion: 2.3.3](https://img.shields.io/static/v1?label=AppVersion&message=2.3.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-12-30 + +* Implement support for DaemonSet + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 60a721d..50cab94 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -10,7 +10,9 @@ image: + # + deployment: + enabled: true +- # Number of pods of the deployment ++ # Can be either Deployment or DaemonSet ++ kind: Deployment ++ # Number of pods of the deployment (only applies when kind == Deployment) + replicas: 1 + # Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} +``` + +## 9.11.0 ![AppVersion: 2.3.3](https://img.shields.io/static/v1?label=AppVersion&message=2.3.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-11-20 + +* add podLabels - custom labels + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index a187df7..60a721d 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -16,6 +16,8 @@ deployment: + annotations: {} + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} ++ # Additional Pod labels (e.g. for filtering Pod by custom labels) ++ podLabels: {} + # Additional containers (e.g. for metric offloading sidecars) + additionalContainers: [] + # https://docs.datadoghq.com/developers/dogstatsd/unix_socket/?tab=host +``` + +## 9.10.2 ![AppVersion: 2.3.3](https://img.shields.io/static/v1?label=AppVersion&message=2.3.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-11-20 + +* Bump Traefik to 2.3.3 + + +## 9.10.1 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-11-04 + +* Specify IngressClass resource when checking for cluster capability + + +## 9.10.0 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-11-03 + +* Add list of watched provider namespaces + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e6b85ca..a187df7 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -88,8 +88,12 @@ rollingUpdate: + providers: + kubernetesCRD: + enabled: true ++ namespaces: [] ++ # - "default" + kubernetesIngress: + enabled: true ++ namespaces: [] ++ # - "default" + # IP used for Kubernetes Ingress endpoints + publishedService: + enabled: false +``` + +## 9.9.0 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-11-03 + +* Add additionalVolumeMounts for traefik container + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 37dd151..e6b85ca 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -111,6 +111,12 @@ volumes: [] + # mountPath: "/config" + # type: configMap + ++# Additional volumeMounts to add to the Traefik container ++additionalVolumeMounts: [] ++ # For instance when using a logshipper for access logs ++ # - name: traefik-logs ++ # mountPath: /var/log/traefik ++ + # Logs + # https://docs.traefik.io/observability/logs/ + logs: +``` + +## 9.8.4 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-11-03 + +* fix: multiple ImagePullSecrets + + +## 9.8.3 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-30 + +* Add imagePullSecrets + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 87f60c0..37dd151 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -42,6 +42,9 @@ deployment: + # mountPath: /data + # Custom pod DNS policy. Apply if `hostNetwork: true` + # dnsPolicy: ClusterFirstWithHostNet ++ # Additional imagePullSecrets ++ imagePullSecrets: [] ++ # - name: myRegistryKeySecretName + + # Pod disruption budget + podDisruptionBudget: +``` + +## 9.8.2 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-28 + +* Add chart repo to source + + +## 9.8.1 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-23 + +* fix semver compare + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 4ca1f8f..87f60c0 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,8 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.3.1 ++ # defaults to appVersion ++ tag: "" + pullPolicy: IfNotPresent + + # +``` + +## 9.8.0 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-20 + +* feat: Enable entrypoint tls config + TLSOption + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index eee3622..4ca1f8f 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -231,6 +231,31 @@ ports: + # The port protocol (TCP/UDP) + protocol: TCP + # nodePort: 32443 ++ # Set TLS at the entrypoint ++ # https://doc.traefik.io/traefik/routing/entrypoints/#tls ++ tls: ++ enabled: false ++ # this is the name of a TLSOption definition ++ options: "" ++ certResolver: "" ++ domains: [] ++ # - main: example.com ++ # sans: ++ # - foo.example.com ++ # - bar.example.com ++ ++# TLS Options are created as TLSOption CRDs ++# https://doc.traefik.io/traefik/https/tls/#tls-options ++# Example: ++# tlsOptions: ++# default: ++# sniStrict: true ++# preferServerCipherSuites: true ++# foobar: ++# curvePreferences: ++# - CurveP521 ++# - CurveP384 ++tlsOptions: {} + + # Options for the main traefik service, where the entrypoints traffic comes + # from. +``` + +## 9.7.0 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-15 + +* Add a configuration option for an emptyDir as plugin storage + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index b7153a1..eee3622 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -54,10 +54,16 @@ ingressClass: + enabled: false + isDefaultClass: false + ++# Activate Pilot integration + pilot: + enabled: false + token: "" + ++# Enable experimental features ++experimental: ++ plugins: ++ enabled: false ++ + # Create an IngressRoute for the dashboard + ingressRoute: + dashboard: +``` + +## 9.6.0 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-15 + +* Add additional volumes for init and additional containers + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 9bac45e..b7153a1 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -17,6 +17,18 @@ deployment: + podAnnotations: {} + # Additional containers (e.g. for metric offloading sidecars) + additionalContainers: [] ++ # https://docs.datadoghq.com/developers/dogstatsd/unix_socket/?tab=host ++ # - name: socat-proxy ++ # image: alpine/socat:1.0.5 ++ # args: ["-s", "-u", "udp-recv:8125", "unix-sendto:/socket/socket"] ++ # volumeMounts: ++ # - name: dsdsocket ++ # mountPath: /socket ++ # Additional volumes available for use with initContainers and additionalContainers ++ additionalVolumes: [] ++ # - name: dsdsocket ++ # hostPath: ++ # path: /var/run/statsd-exporter + # Additional initContainers (e.g. for setting file permission as shown below) + initContainers: [] + # The "volume-permissions" init container is required if you run into permission issues. +``` + +## 9.5.2 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-15 + +* Replace extensions with policy because of deprecation + + +## 9.5.1 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-14 + +* Template custom volume name + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 5a8d8ea..9bac45e 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -76,7 +76,7 @@ providers: + # pathOverride: "" + + # +-# Add volumes to the traefik pod. ++# Add volumes to the traefik pod. The volume name will be passed to tpl. + # This can be used to mount a cert pair or a configmap that holds a config.toml file. + # After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: + # additionalArguments: +@@ -85,7 +85,7 @@ volumes: [] + # - name: public-cert + # mountPath: "/certs" + # type: secret +-# - name: configs ++# - name: '{{ printf "%s-configs" .Release.Name }}' + # mountPath: "/config" + # type: configMap + +``` + +## 9.5.0 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-02 + +* Create PodSecurityPolicy and RBAC when needed. + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 8c4d866..5a8d8ea 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -281,6 +281,10 @@ rbac: + # If set to true, installs namespace-specific Role and RoleBinding and requires provider configuration be set to that same namespace + namespaced: false + ++# Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBindin or ClusterRoleBinding ++podSecurityPolicy: ++ enabled: false ++ + # The service account the pods will use to interact with the Kubernetes API + serviceAccount: + # If set, an existing service account is used +``` + +## 9.4.3 ![AppVersion: 2.3.1](https://img.shields.io/static/v1?label=AppVersion&message=2.3.1&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-02 + +* Update traefik to v2.3.1 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 3df75a4..8c4d866 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.3.0 ++ tag: 2.3.1 + pullPolicy: IfNotPresent + + # +``` + +## 9.4.2 ![AppVersion: 2.3.0](https://img.shields.io/static/v1?label=AppVersion&message=2.3.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-02 + +* Add Artifact Hub repository metadata file + + +## 9.4.1 ![AppVersion: 2.3.0](https://img.shields.io/static/v1?label=AppVersion&message=2.3.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-01 + +* Fix broken chart icon url + + +## 9.4.0 ![AppVersion: 2.3.0](https://img.shields.io/static/v1?label=AppVersion&message=2.3.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-10-01 + +* Allow to specify custom labels on Service + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index a6175ff..3df75a4 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -221,6 +221,8 @@ service: + type: LoadBalancer + # Additional annotations (e.g. for cloud provider specific config) + annotations: {} ++ # Additional service labels (e.g. for filtering Service by custom labels) ++ labels: {} + # Additional entries here will be added to the service spec. Cannot contains + # type, selector or ports entries. + spec: {} +``` + +## 9.3.0 ![AppVersion: 2.3.0](https://img.shields.io/static/v1?label=AppVersion&message=2.3.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-09-24 + +* Release Traefik 2.3 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index fba955d..a6175ff 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.2.8 ++ tag: 2.3.0 + pullPolicy: IfNotPresent + + # +@@ -36,6 +36,16 @@ podDisruptionBudget: + # maxUnavailable: 1 + # minAvailable: 0 + ++# Use ingressClass. Ignored if Traefik version < 2.3 / kubernetes < 1.18.x ++ingressClass: ++ # true is not unit-testable yet, pending https://github.com/rancher/helm-unittest/pull/12 ++ enabled: false ++ isDefaultClass: false ++ ++pilot: ++ enabled: false ++ token: "" ++ + # Create an IngressRoute for the dashboard + ingressRoute: + dashboard: +``` + +## 9.2.1 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-09-18 + +* Add new helm url + + +## 9.2.0 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-09-16 + +* chore: move to new organization. + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 9f52c39..fba955d 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -20,7 +20,7 @@ deployment: + # Additional initContainers (e.g. for setting file permission as shown below) + initContainers: [] + # The "volume-permissions" init container is required if you run into permission issues. +- # Related issue: https://github.com/containous/traefik/issues/6972 ++ # Related issue: https://github.com/traefik/traefik/issues/6972 + # - name: volume-permissions + # image: busybox:1.31.1 + # command: ["sh", "-c", "chmod -Rv 600 /data/*"] +``` + +## 9.1.1 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-09-04 + +* Update reference to using kubectl proxy to kubectl port-forward + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7b74a39..9f52c39 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -175,7 +175,7 @@ ports: + # + # You SHOULD NOT expose the traefik port on production deployments. + # If you want to access it from outside of your cluster, +- # use `kubectl proxy` or create a secure ingress ++ # use `kubectl port-forward` or create a secure ingress + expose: false + # The exposed port for this service + exposedPort: 9000 +``` + +## 9.1.0 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-24 + +* PublishedService option + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e161a14..7b74a39 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -58,6 +58,12 @@ providers: + enabled: true + kubernetesIngress: + enabled: true ++ # IP used for Kubernetes Ingress endpoints ++ publishedService: ++ enabled: false ++ # Published Kubernetes Service to copy status from. Format: namespace/servicename ++ # By default this Traefik service ++ # pathOverride: "" + + # + # Add volumes to the traefik pod. +``` + +## 9.0.0 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-21 + +* feat: Move Chart apiVersion: v2 + + +## 8.13.3 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-21 + +* bug: Check for port config + + +## 8.13.2 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-19 + +* Fix log level configuration + + +## 8.13.1 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-18 + +* Dont redirect to websecure by default + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 67276f7..e161a14 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -188,7 +188,7 @@ ports: + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection +- redirectTo: websecure ++ # redirectTo: websecure + websecure: + port: 8443 + # hostPort: 8443 +``` + +## 8.13.0 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-18 + +* Add logging, and http redirect config + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 6f79580..67276f7 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -73,6 +73,48 @@ volumes: [] + # mountPath: "/config" + # type: configMap + ++# Logs ++# https://docs.traefik.io/observability/logs/ ++logs: ++ # Traefik logs concern everything that happens to Traefik itself (startup, configuration, events, shutdown, and so on). ++ general: ++ # By default, the logs use a text format (common), but you can ++ # also ask for the json format in the format option ++ # format: json ++ # By default, the level is set to ERROR. Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO. ++ level: ERROR ++ access: ++ # To enable access logs ++ enabled: false ++ # By default, logs are written using the Common Log Format (CLF). ++ # To write logs in JSON, use json in the format option. ++ # If the given format is unsupported, the default (CLF) is used instead. ++ # format: json ++ # To write the logs in an asynchronous fashion, specify a bufferingSize option. ++ # This option represents the number of log lines Traefik will keep in memory before writing ++ # them to the selected output. In some cases, this option can greatly help performances. ++ # bufferingSize: 100 ++ # Filtering https://docs.traefik.io/observability/access-logs/#filtering ++ filters: {} ++ # statuscodes: "200,300-302" ++ # retryattempts: true ++ # minduration: 10ms ++ # Fields ++ # https://docs.traefik.io/observability/access-logs/#limiting-the-fieldsincluding-headers ++ fields: ++ general: ++ defaultmode: keep ++ names: {} ++ # Examples: ++ # ClientUsername: drop ++ headers: ++ defaultmode: drop ++ names: {} ++ # Examples: ++ # User-Agent: redact ++ # Authorization: drop ++ # Content-Type: keep ++ + globalArguments: + - "--global.checknewversion" + - "--global.sendanonymoususage" +@@ -143,6 +185,10 @@ ports: + # Use nodeport if set. This is useful if you have configured Traefik in a + # LoadBalancer + # nodePort: 32080 ++ # Port Redirections ++ # Added in 2.2, you can make permanent redirects via entrypoints. ++ # https://docs.traefik.io/routing/entrypoints/#redirection ++ redirectTo: websecure + websecure: + port: 8443 + # hostPort: 8443 +``` + +## 8.12.0 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-14 + +* Add image pull policy + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 10b3949..6f79580 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -2,6 +2,7 @@ + image: + name: traefik + tag: 2.2.8 ++ pullPolicy: IfNotPresent + + # + # Configure the deployment +``` + +## 8.11.0 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-12 + +* Add dns policy option + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 80ddaaa..10b3949 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -26,6 +26,8 @@ deployment: + # volumeMounts: + # - name: data + # mountPath: /data ++ # Custom pod DNS policy. Apply if `hostNetwork: true` ++ # dnsPolicy: ClusterFirstWithHostNet + + # Pod disruption budget + podDisruptionBudget: +``` + +## 8.10.0 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-11 + +* Add hostIp to port configuration + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 936ab92..80ddaaa 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -112,6 +112,12 @@ ports: + port: 9000 + # Use hostPort if set. + # hostPort: 9000 ++ # ++ # Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which ++ # means it's listening on all your interfaces and all your IPs. You may want ++ # to set this value if you need traefik to listen on specific interface ++ # only. ++ # hostIP: 192.168.100.10 + + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. +``` + +## 8.9.2 ![AppVersion: 2.2.8](https://img.shields.io/static/v1?label=AppVersion&message=2.2.8&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-08-10 + +* Bump Traefik to 2.2.8 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 42ee893..936ab92 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.2.5 ++ tag: 2.2.8 + + # + # Configure the deployment +``` + +## 8.9.1 ![AppVersion: 2.2.5](https://img.shields.io/static/v1?label=AppVersion&message=2.2.5&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-07-15 + +* Upgrade traefik version + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index a7fb668..42ee893 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.2.1 ++ tag: 2.2.5 + + # + # Configure the deployment +``` + +## 8.9.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-07-08 + +* run init container to set proper permissions on volume + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 62e3a77..a7fb668 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -16,6 +16,16 @@ deployment: + podAnnotations: {} + # Additional containers (e.g. for metric offloading sidecars) + additionalContainers: [] ++ # Additional initContainers (e.g. for setting file permission as shown below) ++ initContainers: [] ++ # The "volume-permissions" init container is required if you run into permission issues. ++ # Related issue: https://github.com/containous/traefik/issues/6972 ++ # - name: volume-permissions ++ # image: busybox:1.31.1 ++ # command: ["sh", "-c", "chmod -Rv 600 /data/*"] ++ # volumeMounts: ++ # - name: data ++ # mountPath: /data + + # Pod disruption budget + podDisruptionBudget: +``` + +## 8.8.1 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-07-02 + +* Additional container fix + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 85df29c..62e3a77 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -15,7 +15,7 @@ deployment: + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} + # Additional containers (e.g. for metric offloading sidecars) +- additionalContainers: {} ++ additionalContainers: [] + + # Pod disruption budget + podDisruptionBudget: +``` + +## 8.8.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-07-01 + +* added additionalContainers option to chart + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 6a9dfd8..85df29c 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -14,6 +14,8 @@ deployment: + annotations: {} + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} ++ # Additional containers (e.g. for metric offloading sidecars) ++ additionalContainers: {} + + # Pod disruption budget + podDisruptionBudget: +``` + +## 8.7.2 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-30 + +* Update image + + +## 8.7.1 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-26 + +* Update values.yaml + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 05f9eab..6a9dfd8 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -196,7 +196,7 @@ rbac: + # If set to true, installs namespace-specific Role and RoleBinding and requires provider configuration be set to that same namespace + namespaced: false + +-# The service account the pods will use to interact with the Kubernates API ++# The service account the pods will use to interact with the Kubernetes API + serviceAccount: + # If set, an existing service account is used + # If not set, a service account is created automatically using the fullname template +``` + +## 8.7.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-23 + +* Add option to disable providers + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 102ae00..05f9eab 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -34,6 +34,16 @@ rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + ++ ++# ++# Configure providers ++# ++providers: ++ kubernetesCRD: ++ enabled: true ++ kubernetesIngress: ++ enabled: true ++ + # + # Add volumes to the traefik pod. + # This can be used to mount a cert pair or a configmap that holds a config.toml file. +``` + +## 8.6.1 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-18 + +* Fix read-only /tmp + + +## 8.6.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-17 + +* Add existing PVC support(#158) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index b2f4fc3..102ae00 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -164,6 +164,7 @@ autoscaling: + # It will persist TLS certificates. + persistence: + enabled: false ++# existingClaim: "" + accessMode: ReadWriteOnce + size: 128Mi + # storageClass: "" +``` + +## 8.5.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-16 + +* UDP support + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 9a9b668..b2f4fc3 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -100,11 +100,15 @@ ports: + expose: false + # The exposed port for this service + exposedPort: 9000 ++ # The port protocol (TCP/UDP) ++ protocol: TCP + web: + port: 8000 + # hostPort: 8000 + expose: true + exposedPort: 80 ++ # The port protocol (TCP/UDP) ++ protocol: TCP + # Use nodeport if set. This is useful if you have configured Traefik in a + # LoadBalancer + # nodePort: 32080 +@@ -113,6 +117,8 @@ ports: + # hostPort: 8443 + expose: true + exposedPort: 443 ++ # The port protocol (TCP/UDP) ++ protocol: TCP + # nodePort: 32443 + + # Options for the main traefik service, where the entrypoints traffic comes +``` + +## 8.4.1 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-10 + +* Fix PDB with minAvailable set + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e812b98..9a9b668 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -18,7 +18,7 @@ deployment: + # Pod disruption budget + podDisruptionBudget: + enabled: false +- maxUnavailable: 1 ++ # maxUnavailable: 1 + # minAvailable: 0 + + # Create an IngressRoute for the dashboard +``` + +## 8.4.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-09 + +* Add pod disruption budget (#192) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 5f44e5c..e812b98 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -15,6 +15,12 @@ deployment: + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} + ++# Pod disruption budget ++podDisruptionBudget: ++ enabled: false ++ maxUnavailable: 1 ++ # minAvailable: 0 ++ + # Create an IngressRoute for the dashboard + ingressRoute: + dashboard: +``` + +## 8.3.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-06-08 + +* Add option to disable RBAC and ServiceAccount + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 96bba18..5f44e5c 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -165,6 +165,20 @@ persistence: + # affinity is left as default. + hostNetwork: false + ++# Whether Role Based Access Control objects like roles and rolebindings should be created ++rbac: ++ enabled: true ++ ++ # If set to false, installs ClusterRole and ClusterRoleBinding so Traefik can be used across namespaces. ++ # If set to true, installs namespace-specific Role and RoleBinding and requires provider configuration be set to that same namespace ++ namespaced: false ++ ++# The service account the pods will use to interact with the Kubernates API ++serviceAccount: ++ # If set, an existing service account is used ++ # If not set, a service account is created automatically using the fullname template ++ name: "" ++ + # Additional serviceAccount annotations (e.g. for oidc authentication) + serviceAccountAnnotations: {} + +``` + +## 8.2.1 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-05-25 + +* Remove suggested providers.kubernetesingress value + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e35bdf9..96bba18 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -50,9 +50,9 @@ globalArguments: + # Configure Traefik static configuration + # Additional arguments to be passed at Traefik's binary + # All available options available on https://docs.traefik.io/reference/static-configuration/cli/ +-## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress,--log.level=DEBUG}"` ++## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}"` + additionalArguments: [] +-# - "--providers.kubernetesingress" ++# - "--providers.kubernetesingress.ingressclass=traefik-internal" + # - "--log.level=DEBUG" + + # Environment variables to be passed to Traefik's binary +``` + +## 8.2.0 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-05-18 + +* Add kubernetes ingress by default + + +## 8.1.5 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-05-18 + +* Fix example log params in values.yml + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index abe2334..e35bdf9 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -50,10 +50,10 @@ globalArguments: + # Configure Traefik static configuration + # Additional arguments to be passed at Traefik's binary + # All available options available on https://docs.traefik.io/reference/static-configuration/cli/ +-## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress,--logs.level=DEBUG}"` ++## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress,--log.level=DEBUG}"` + additionalArguments: [] + # - "--providers.kubernetesingress" +-# - "--logs.level=DEBUG" ++# - "--log.level=DEBUG" + + # Environment variables to be passed to Traefik's binary + env: [] +``` + +## 8.1.4 ![AppVersion: 2.2.1](https://img.shields.io/static/v1?label=AppVersion&message=2.2.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-30 + +* Update Traefik to v2.2.1 + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 57cc7e1..abe2334 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.2.0 ++ tag: 2.2.1 + + # + # Configure the deployment +``` + +## 8.1.3 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-29 + +* Clarify additionnal arguments log + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d639f72..57cc7e1 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -50,9 +50,10 @@ globalArguments: + # Configure Traefik static configuration + # Additional arguments to be passed at Traefik's binary + # All available options available on https://docs.traefik.io/reference/static-configuration/cli/ +-## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress,--global.checknewversion=true}"` ++## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress,--logs.level=DEBUG}"` + additionalArguments: [] + # - "--providers.kubernetesingress" ++# - "--logs.level=DEBUG" + + # Environment variables to be passed to Traefik's binary + env: [] +``` + +## 8.1.2 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-23 + +* Remove invalid flags. (#161) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 0e7aaef..d639f72 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -34,8 +34,6 @@ rollingUpdate: + # After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: + # additionalArguments: + # - "--providers.file.filename=/config/dynamic.toml" +-# - "--tls.certificates.certFile=/certs/tls.crt" +-# - "--tls.certificates.keyFile=/certs/tls.key" + volumes: [] + # - name: public-cert + # mountPath: "/certs" +``` + +## 8.1.1 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-23 + +* clarify project philosophy and guidelines + + +## 8.1.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-22 + +* Add priorityClassName & securityContext + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index d55a40a..0e7aaef 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -191,3 +191,20 @@ affinity: {} + # topologyKey: failure-domain.beta.kubernetes.io/zone + nodeSelector: {} + tolerations: [] ++ ++# Pods can have priority. ++# Priority indicates the importance of a Pod relative to other Pods. ++priorityClassName: "" ++ ++# Set the container security context ++# To run the container with ports below 1024 this will need to be adjust to run as root ++securityContext: ++ capabilities: ++ drop: [ALL] ++ readOnlyRootFilesystem: true ++ runAsGroup: 65532 ++ runAsNonRoot: true ++ runAsUser: 65532 ++ ++podSecurityContext: ++ fsGroup: 65532 +``` + +## 8.0.4 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-20 + +* Possibility to bind environment variables via envFrom + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7f8092e..d55a40a 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -71,6 +71,12 @@ env: [] + # name: secret-name + # key: secret-key + ++envFrom: [] ++# - configMapRef: ++# name: config-map-name ++# - secretRef: ++# name: secret-name ++ + # Configure ports + ports: + # The name of this one can't be changed as it is used for the readiness and +``` + +## 8.0.3 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-15 + +* Add support for data volume subPath. (#147) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 152339b..7f8092e 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -152,6 +152,7 @@ persistence: + # storageClass: "" + path: /data + annotations: {} ++ # subPath: "" # only mount a subpath of the Volume into the pod + + # If hostNetwork is true, runs traefik in the host network namespace + # To prevent unschedulabel pods due to port collisions, if hostNetwork=true +``` + +## 8.0.2 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-10 + +* Ability to add custom labels to dashboard's IngressRoute + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 5d294b7..152339b 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -21,6 +21,8 @@ ingressRoute: + enabled: true + # Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) + annotations: {} ++ # Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) ++ labels: {} + + rollingUpdate: + maxUnavailable: 1 +``` + +## 8.0.1 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-10 + +* rbac does not need "pods" per documentation + + +## 8.0.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-07 + +* follow helm best practices + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index e61a9fd..5d294b7 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -10,7 +10,7 @@ deployment: + enabled: true + # Number of pods of the deployment + replicas: 1 +- # Addtional deployment annotations (e.g. for jaeger-operator sidecar injection) ++ # Additional deployment annotations (e.g. for jaeger-operator sidecar injection) + annotations: {} + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} +@@ -19,7 +19,7 @@ deployment: + ingressRoute: + dashboard: + enabled: true +- # Addtional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) ++ # Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) + annotations: {} + + rollingUpdate: +``` + +## 7.2.1 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-07 + +* add annotations to ingressRoute + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 15d1c25..e61a9fd 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -19,6 +19,8 @@ deployment: + ingressRoute: + dashboard: + enabled: true ++ # Addtional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) ++ annotations: {} + + rollingUpdate: + maxUnavailable: 1 +``` + +## 7.2.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-04-03 + +* Add support for helm 2 + + +## 7.1.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-31 + +* Add support for externalIPs + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 6d6d13f..15d1c25 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -116,6 +116,8 @@ service: + loadBalancerSourceRanges: [] + # - 192.168.0.1/32 + # - 172.16.0.0/16 ++ externalIPs: [] ++ # - 1.2.3.4 + + ## Create HorizontalPodAutoscaler object. + ## +``` + +## 7.0.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-27 + +* Remove secretsEnv value key + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 1ac720d..6d6d13f 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -52,18 +52,20 @@ globalArguments: + additionalArguments: [] + # - "--providers.kubernetesingress" + +-# Secret to be set as environment variables to be passed to Traefik's binary +-secretEnv: [] +- # - name: SOME_VAR +- # secretName: my-secret-name +- # secretKey: my-secret-key +- + # Environment variables to be passed to Traefik's binary + env: [] +- # - name: SOME_VAR +- # value: some-var-value +- # - name: SOME_OTHER_VAR +- # value: some-other-var-value ++# - name: SOME_VAR ++# value: some-var-value ++# - name: SOME_VAR_FROM_CONFIG_MAP ++# valueFrom: ++# configMapRef: ++# name: configmap-name ++# key: config-key ++# - name: SOME_SECRET ++# valueFrom: ++# secretKeyRef: ++# name: secret-name ++# key: secret-key + + # Configure ports + ports: +``` + +## 6.4.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-27 + +* Add ability to set serviceAccount annotations + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 85abe42..1ac720d 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -151,6 +151,9 @@ persistence: + # affinity is left as default. + hostNetwork: false + ++# Additional serviceAccount annotations (e.g. for oidc authentication) ++serviceAccountAnnotations: {} ++ + resources: {} + # requests: + # cpu: "100m" +``` + +## 6.3.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-27 + +* hpa + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 2f5d132..85abe42 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -115,6 +115,22 @@ service: + # - 192.168.0.1/32 + # - 172.16.0.0/16 + ++## Create HorizontalPodAutoscaler object. ++## ++autoscaling: ++ enabled: false ++# minReplicas: 1 ++# maxReplicas: 10 ++# metrics: ++# - type: Resource ++# resource: ++# name: cpu ++# targetAverageUtilization: 60 ++# - type: Resource ++# resource: ++# name: memory ++# targetAverageUtilization: 60 ++ + # Enable persistence using Persistent Volume Claims + # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + # After the pvc has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: +``` + +## 6.2.0 ![AppVersion: 2.2.0](https://img.shields.io/static/v1?label=AppVersion&message=2.2.0&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-26 + +* Update to v2.2 (#96) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ebd2fde..2f5d132 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.1.8 ++ tag: 2.2.0 + + # + # Configure the deployment +``` + +## 6.1.2 ![AppVersion: 2.1.8](https://img.shields.io/static/v1?label=AppVersion&message=2.1.8&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-20 + +* Upgrade traefik version + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 65c7665..ebd2fde 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.1.4 ++ tag: 2.1.8 + + # + # Configure the deployment +``` + +## 6.1.1 ![AppVersion: 2.1.4](https://img.shields.io/static/v1?label=AppVersion&message=2.1.4&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-20 + +* Upgrade traefik version + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 89c7ac1..65c7665 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.1.3 ++ tag: 2.1.4 + + # + # Configure the deployment +``` + +## 6.1.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-20 + +* Add ability to add annotations to deployment + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 8d66111..89c7ac1 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -10,6 +10,8 @@ deployment: + enabled: true + # Number of pods of the deployment + replicas: 1 ++ # Addtional deployment annotations (e.g. for jaeger-operator sidecar injection) ++ annotations: {} + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} + +``` + +## 6.0.2 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-16 + +* Correct storage class key name + + +## 6.0.1 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-16 + +* Change default values of arrays from objects to actual arrays + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 490b2b6..8d66111 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -51,13 +51,13 @@ additionalArguments: [] + # - "--providers.kubernetesingress" + + # Secret to be set as environment variables to be passed to Traefik's binary +-secretEnv: {} ++secretEnv: [] + # - name: SOME_VAR + # secretName: my-secret-name + # secretKey: my-secret-key + + # Environment variables to be passed to Traefik's binary +-env: {} ++env: [] + # - name: SOME_VAR + # value: some-var-value + # - name: SOME_OTHER_VAR +@@ -109,7 +109,7 @@ service: + # externalTrafficPolicy: Cluster + # loadBalancerIP: "1.2.3.4" + # clusterIP: "2.3.4.5" +- loadBalancerSourceRanges: {} ++ loadBalancerSourceRanges: [] + # - 192.168.0.1/32 + # - 172.16.0.0/16 + +``` + +## 6.0.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-15 + +* Cleanup + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7aebefe..490b2b6 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -18,15 +18,10 @@ ingressRoute: + dashboard: + enabled: true + +-additional: +- checkNewVersion: true +- sendAnonymousUsage: true +- + rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + +- + # + # Add volumes to the traefik pod. + # This can be used to mount a cert pair or a configmap that holds a config.toml file. +@@ -43,9 +38,14 @@ volumes: [] + # mountPath: "/config" + # type: configMap + ++globalArguments: ++ - "--global.checknewversion" ++ - "--global.sendanonymoususage" ++ + # +-# Configure Traefik entry points ++# Configure Traefik static configuration + # Additional arguments to be passed at Traefik's binary ++# All available options available on https://docs.traefik.io/reference/static-configuration/cli/ + ## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress,--global.checknewversion=true}"` + additionalArguments: [] + # - "--providers.kubernetesingress" +@@ -63,7 +63,7 @@ env: {} + # - name: SOME_OTHER_VAR + # value: some-other-var-value + +-# ++# Configure ports + ports: + # The name of this one can't be changed as it is used for the readiness and + # liveness probes, but you can adjust its config to your liking +@@ -94,7 +94,7 @@ ports: + # hostPort: 8443 + expose: true + exposedPort: 443 +- # nodePort: 32443 ++ # nodePort: 32443 + + # Options for the main traefik service, where the entrypoints traffic comes + # from. +@@ -113,9 +113,6 @@ service: + # - 192.168.0.1/32 + # - 172.16.0.0/16 + +-logs: +- loglevel: WARN +- + # Enable persistence using Persistent Volume Claims + # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + # After the pvc has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: +``` + +## 5.6.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-12 + +* Add field enabled for resources + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 38bb263..7aebefe 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -7,11 +7,17 @@ image: + # Configure the deployment + # + deployment: ++ enabled: true + # Number of pods of the deployment + replicas: 1 + # Additional pod annotations (e.g. for mesh injection or prometheus scraping) + podAnnotations: {} + ++# Create an IngressRoute for the dashboard ++ingressRoute: ++ dashboard: ++ enabled: true ++ + additional: + checkNewVersion: true + sendAnonymousUsage: true +@@ -93,6 +99,7 @@ ports: + # Options for the main traefik service, where the entrypoints traffic comes + # from. + service: ++ enabled: true + type: LoadBalancer + # Additional annotations (e.g. for cloud provider specific config) + annotations: {} +``` + +## 5.5.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-12 + +* expose hostnetwork option + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ecb2833..38bb263 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -123,6 +123,12 @@ persistence: + path: /data + annotations: {} + ++# If hostNetwork is true, runs traefik in the host network namespace ++# To prevent unschedulabel pods due to port collisions, if hostNetwork=true ++# and replicas>1, a pod anti-affinity is recommended and will be set if the ++# affinity is left as default. ++hostNetwork: false ++ + resources: {} + # requests: + # cpu: "100m" +@@ -131,5 +137,17 @@ resources: {} + # cpu: "300m" + # memory: "150Mi" + affinity: {} ++# # This example pod anti-affinity forces the scheduler to put traefik pods ++# # on nodes where no other traefik pods are scheduled. ++# # It should be used when hostNetwork: true to prevent port conflicts ++# podAntiAffinity: ++# requiredDuringSchedulingIgnoredDuringExecution: ++# - labelSelector: ++# matchExpressions: ++# - key: app ++# operator: In ++# values: ++# - {{ template "traefik.name" . }} ++# topologyKey: failure-domain.beta.kubernetes.io/zone + nodeSelector: {} + tolerations: [] +``` + +## 5.4.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-12 + +* Add support for hostport + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ec1d619..ecb2833 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -63,6 +63,9 @@ ports: + # liveness probes, but you can adjust its config to your liking + traefik: + port: 9000 ++ # Use hostPort if set. ++ # hostPort: 9000 ++ + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # +@@ -74,6 +77,7 @@ ports: + exposedPort: 9000 + web: + port: 8000 ++ # hostPort: 8000 + expose: true + exposedPort: 80 + # Use nodeport if set. This is useful if you have configured Traefik in a +@@ -81,6 +85,7 @@ ports: + # nodePort: 32080 + websecure: + port: 8443 ++ # hostPort: 8443 + expose: true + exposedPort: 443 + # nodePort: 32443 +``` + +## 5.3.3 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-12 + +* Fix replica check + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 7f31548..ec1d619 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -40,7 +40,7 @@ volumes: [] + # + # Configure Traefik entry points + # Additional arguments to be passed at Traefik's binary +-## Use curly braces to pass values: `helm install --set="{--providers.kubernetesingress,--global.checknewversion=true}" ." ++## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress,--global.checknewversion=true}"` + additionalArguments: [] + # - "--providers.kubernetesingress" + +``` + +## 5.3.2 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-11 + +* Fixed typo in README + + +## 5.3.1 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-11 + +* Production ready + + +## 5.3.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-11 + +* Not authorise acme if replica > 1 + + +## 5.2.1 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-11 + +* Fix volume mount + + +## 5.2.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-11 + +* Add secret as env var + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index ccea845..7f31548 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -44,12 +44,18 @@ volumes: [] + additionalArguments: [] + # - "--providers.kubernetesingress" + ++# Secret to be set as environment variables to be passed to Traefik's binary ++secretEnv: {} ++ # - name: SOME_VAR ++ # secretName: my-secret-name ++ # secretKey: my-secret-key ++ + # Environment variables to be passed to Traefik's binary + env: {} +-# - name: SOME_VAR +-# value: some-var-value +-# - name: SOME_OTHER_VAR +-# value: some-other-var-value ++ # - name: SOME_VAR ++ # value: some-var-value ++ # - name: SOME_OTHER_VAR ++ # value: some-other-var-value + + # + ports: +``` + +## 5.1.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-10 + +* Enhance security by add loadBalancerSourceRanges to lockdown ip address. + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 78bbee0..ccea845 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -91,6 +91,9 @@ service: + # externalTrafficPolicy: Cluster + # loadBalancerIP: "1.2.3.4" + # clusterIP: "2.3.4.5" ++ loadBalancerSourceRanges: {} ++ # - 192.168.0.1/32 ++ # - 172.16.0.0/16 + + logs: + loglevel: WARN +``` + +## 5.0.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-10 + +* Expose dashboard by default but only on traefik entrypoint + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index a442fca..78bbee0 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -92,15 +92,6 @@ service: + # loadBalancerIP: "1.2.3.4" + # clusterIP: "2.3.4.5" + +-dashboard: +- # Enable the dashboard on Traefik +- enable: true +- +- # Expose the dashboard and api through an ingress route at /dashboard +- # and /api This is not secure and SHOULD NOT be enabled on production +- # deployments +- ingressRoute: false +- + logs: + loglevel: WARN + +``` + +## 4.1.3 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-10 + +* Add annotations for PVC (#98) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 8b2f4db..a442fca 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -116,6 +116,7 @@ persistence: + size: 128Mi + # storageClass: "" + path: /data ++ annotations: {} + + resources: {} + # requests: +``` + +## 4.1.2 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-10 + +* Added persistent volume support. (#86) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 2a2554f..8b2f4db 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -103,7 +103,20 @@ dashboard: + + logs: + loglevel: WARN +-# ++ ++# Enable persistence using Persistent Volume Claims ++# ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ ++# After the pvc has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: ++# additionalArguments: ++# - "--certificatesresolvers.le.acme.storage=/data/acme.json" ++# It will persist TLS certificates. ++persistence: ++ enabled: false ++ accessMode: ReadWriteOnce ++ size: 128Mi ++ # storageClass: "" ++ path: /data ++ + resources: {} + # requests: + # cpu: "100m" +``` + +## 4.1.1 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-10 + +* Add values to mount secrets or configmaps as volumes to the traefik pod (#84) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 5401832..2a2554f 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -20,6 +20,23 @@ rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + ++ ++# ++# Add volumes to the traefik pod. ++# This can be used to mount a cert pair or a configmap that holds a config.toml file. ++# After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: ++# additionalArguments: ++# - "--providers.file.filename=/config/dynamic.toml" ++# - "--tls.certificates.certFile=/certs/tls.crt" ++# - "--tls.certificates.keyFile=/certs/tls.key" ++volumes: [] ++# - name: public-cert ++# mountPath: "/certs" ++# type: secret ++# - name: configs ++# mountPath: "/config" ++# type: configMap ++ + # + # Configure Traefik entry points + # Additional arguments to be passed at Traefik's binary +``` + +## 4.1.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-10 + +* Add podAnnotations to the deployment (#83) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 5eab74b..5401832 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -9,6 +9,8 @@ image: + deployment: + # Number of pods of the deployment + replicas: 1 ++ # Additional pod annotations (e.g. for mesh injection or prometheus scraping) ++ podAnnotations: {} + + additional: + checkNewVersion: true +``` + +## 4.0.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-03-06 + +* Migrate to helm v3 (#94) + + +## 3.5.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-02-18 + +* Publish helm chart (#81) + + +## 3.4.0 ![AppVersion: 2.1.3](https://img.shields.io/static/v1?label=AppVersion&message=2.1.3&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-02-13 + +* fix: tests. +* feat: bump traefik to v2.1.3 +* Enable configuration of global checknewversion and sendanonymoususage (#80) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index bcc42f8..5eab74b 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -1,7 +1,7 @@ + # Default values for Traefik + image: + name: traefik +- tag: 2.1.1 ++ tag: 2.1.3 + + # + # Configure the deployment +@@ -10,6 +10,10 @@ deployment: + # Number of pods of the deployment + replicas: 1 + ++additional: ++ checkNewVersion: true ++ sendAnonymousUsage: true ++ + rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 +``` + +## 3.3.3 ![AppVersion: 2.1.1](https://img.shields.io/static/v1?label=AppVersion&message=2.1.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-02-05 + +* fix: deployment environment variables. +* fix: chart version. + + +## 3.3.2 ![AppVersion: 2.1.1](https://img.shields.io/static/v1?label=AppVersion&message=2.1.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-02-03 + +* ix: deployment environment variables. + + +## 3.3.1 ![AppVersion: 2.1.1](https://img.shields.io/static/v1?label=AppVersion&message=2.1.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-01-27 + +* fix: deployment environment variables. + + +## 3.3.0 ![AppVersion: 2.1.1](https://img.shields.io/static/v1?label=AppVersion&message=2.1.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-01-24 + +* Enable configuration of environment variables in traefik deployment (#71) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index 4462359..bcc42f8 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -21,6 +21,13 @@ rollingUpdate: + additionalArguments: [] + # - "--providers.kubernetesingress" + ++# Environment variables to be passed to Traefik's binary ++env: {} ++# - name: SOME_VAR ++# value: some-var-value ++# - name: SOME_OTHER_VAR ++# value: some-other-var-value ++ + # + ports: + # The name of this one can't be changed as it is used for the readiness and +``` + +## 3.2.1 ![AppVersion: 2.1.1](https://img.shields.io/static/v1?label=AppVersion&message=2.1.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-01-22 + +* Add Unit Tests for the chart (#60) + + +## 3.2.0 ![AppVersion: 2.1.1](https://img.shields.io/static/v1?label=AppVersion&message=2.1.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-01-22 + +* Make NodePort configurable (#67) + +### Default value changes + +```diff +diff --git a/traefik/values.yaml b/traefik/values.yaml +index b1fe42a..4462359 100644 +--- a/traefik/values.yaml ++++ b/traefik/values.yaml +@@ -40,10 +40,14 @@ ports: + port: 8000 + expose: true + exposedPort: 80 ++ # Use nodeport if set. This is useful if you have configured Traefik in a ++ # LoadBalancer ++ # nodePort: 32080 + websecure: + port: 8443 + expose: true + exposedPort: 443 ++ # nodePort: 32443 + + # Options for the main traefik service, where the entrypoints traffic comes + # from. +``` + +## 3.1.0 ![AppVersion: 2.1.1](https://img.shields.io/static/v1?label=AppVersion&message=2.1.1&color=success&logo=) ![Helm: v2](https://img.shields.io/static/v1?label=Helm&message=v2&color=inactive&logo=helm) ![Helm: v3](https://img.shields.io/static/v1?label=Helm&message=v3&color=informational&logo=helm) + +**Release date:** 2020-01-20 + +* Switch Chart linting to ct (#59) + +### Default value changes + +```diff +# Default values for Traefik +image: + name: traefik + tag: 2.1.1 + +# +# Configure the deployment +# +deployment: + # Number of pods of the deployment + replicas: 1 + +rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + +# +# Configure Traefik entry points +# Additional arguments to be passed at Traefik's binary +## Use curly braces to pass values: `helm install --set="{--providers.kubernetesingress,--global.checknewversion=true}" ." +additionalArguments: [] +# - "--providers.kubernetesingress" + +# +ports: + # The name of this one can't be changed as it is used for the readiness and + # liveness probes, but you can adjust its config to your liking + traefik: + port: 9000 + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # + # You SHOULD NOT expose the traefik port on production deployments. + # If you want to access it from outside of your cluster, + # use `kubectl proxy` or create a secure ingress + expose: false + # The exposed port for this service + exposedPort: 9000 + web: + port: 8000 + expose: true + exposedPort: 80 + websecure: + port: 8443 + expose: true + exposedPort: 443 + +# Options for the main traefik service, where the entrypoints traffic comes +# from. +service: + type: LoadBalancer + # Additional annotations (e.g. for cloud provider specific config) + annotations: {} + # Additional entries here will be added to the service spec. Cannot contains + # type, selector or ports entries. + spec: {} + # externalTrafficPolicy: Cluster + # loadBalancerIP: "1.2.3.4" + # clusterIP: "2.3.4.5" + +dashboard: + # Enable the dashboard on Traefik + enable: true + + # Expose the dashboard and api through an ingress route at /dashboard + # and /api This is not secure and SHOULD NOT be enabled on production + # deployments + ingressRoute: false + +logs: + loglevel: WARN +# +resources: {} + # requests: + # cpu: "100m" + # memory: "50Mi" + # limits: + # cpu: "300m" + # memory: "150Mi" +affinity: {} +nodeSelector: {} +tolerations: [] +``` + +--- +Autogenerated from Helm Chart and git history using [helm-changelog](https://github.com/mogensen/helm-changelog) diff --git a/utils/assets/charts/traefik/Chart.yaml b/utils/assets/charts/traefik/Chart.yaml new file mode 100644 index 0000000..0d1220a --- /dev/null +++ b/utils/assets/charts/traefik/Chart.yaml @@ -0,0 +1,39 @@ +annotations: + artifacthub.io/changes: "- \"fix: \U0001F41B http3 with internal service\"\n- \"fix: + use correct children indentation for logs.access.filters\"\n- \"fix(schema): :bug: + targetPort can also be a string\"\n- \"fix(certificateResolvers)!: :boom: :bug: + use same syntax in Chart and in Traefik\"\n- \"fix(Traefik)!: :boom: set 8080 + as default port for `traefik` entrypoint\"\n- \"fix(Traefik Hub): RBAC for distributedAcme\"\n- + \"fix(Kubernetes Ingress)!: :boom: :sparkles: enable publishedService by default\"\n- + \"fix(Gateway API): :bug: add missing required RBAC for v3.2 with experimental + Channel\"\n- \"fix(Env Variables)!: allow extending env without overwrite\"\n- + \"feat(deps): update traefik docker tag to v3.2.0\"\n- \"feat(deps): update traefik + docker tag to v3.1.6\"\n- \"feat(Traefik): ✨ support Gateway API statusAddress\"\n- + \"feat(Traefik Proxy): CRDs for v3.2+\"\n- \"feat(Gateway API): :sparkles: standard + install CRD v1.2.0\"\n- \"feat(Gateway API): :sparkles: add infrastructure in + the values\"\n- \"chore: allow TRACE log level\"\n- \"chore(release): \U0001F680 + publish v33.0.0\"\n- \"Update topology spread constraints comments\"\n" +apiVersion: v2 +appVersion: v3.2.0 +description: A Traefik based Kubernetes ingress controller +home: https://traefik.io/ +icon: https://raw.githubusercontent.com/traefik/traefik/v2.3/docs/content/assets/img/traefik.logo.png +keywords: +- traefik +- ingress +- networking +kubeVersion: '>=1.22.0-0' +maintainers: +- email: michel.loiseleur@traefik.io + name: mloiseleur +- email: charlie.haley@traefik.io + name: charlie-haley +- email: remi.buisson@traefik.io + name: darkweaver87 +- name: jnoordsij +name: traefik +sources: +- https://github.com/traefik/traefik +- https://github.com/traefik/traefik-helm-chart +type: application +version: 33.0.0 diff --git a/utils/assets/charts/traefik/EXAMPLES.md b/utils/assets/charts/traefik/EXAMPLES.md new file mode 100644 index 0000000..6c70f5a --- /dev/null +++ b/utils/assets/charts/traefik/EXAMPLES.md @@ -0,0 +1,1014 @@ +# Install as a DaemonSet + +Default install is using a `Deployment` but it's possible to use `DaemonSet` + +```yaml +deployment: + kind: DaemonSet +``` + +# Configure traefik Pod parameters + +## Extending /etc/hosts records + +In some specific cases, you'll need to add extra records to the `/etc/hosts` file for the Traefik containers. +You can configure it using [hostAliases](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/): + +```yaml +deployment: + hostAliases: + - ip: "127.0.0.1" # this is an example + hostnames: + - "foo.local" + - "bar.local" +``` +## Extending DNS config + +In order to configure additional DNS servers for your traefik pod, you can use `dnsConfig` option: + +```yaml +deployment: + dnsConfig: + nameservers: + - 192.0.2.1 # this is an example + searches: + - ns1.svc.cluster-domain.example + - my.dns.search.suffix + options: + - name: ndots + value: "2" + - name: edns0 +``` + +# Install in a dedicated namespace, with limited RBAC + +Default install is using Cluster-wide RBAC but it can be restricted to target namespace. + +```yaml +rbac: + namespaced: true +``` + +# Install with auto-scaling + +When enabling [HPA](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) +to adjust replicas count according to CPU Usage, you'll need to set resources and nullify replicas. + +```yaml +deployment: + replicas: null +resources: + requests: + cpu: "100m" + memory: "50Mi" + limits: + cpu: "300m" + memory: "150Mi" +autoscaling: + enabled: true + maxReplicas: 2 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 +``` + +# Access Traefik dashboard without exposing it + +This Chart does not expose the Traefik local dashboard by default. It's explained in upstream [documentation](https://doc.traefik.io/traefik/operations/api/) why: + +> Enabling the API in production is not recommended, because it will expose all configuration elements, including sensitive data. + +It says also: + +> In production, it should be at least secured by authentication and authorizations. + +Thus, there are multiple ways to expose the dashboard. For instance, after enabling the creation of dashboard `IngressRoute` in the values: + +```yaml +ingressRoute: + dashboard: + enabled: true +``` + +The traefik admin port can be forwarded locally: + +```bash +kubectl port-forward $(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name) 8080:8080 +``` + +This command makes the dashboard accessible on the url: http://127.0.0.1:8080/dashboard/ + +# Publish and protect Traefik Dashboard with basic Auth + +To expose the dashboard in a secure way as [recommended](https://doc.traefik.io/traefik/operations/dashboard/#dashboard-router-rule) +in the documentation, it may be useful to override the router rule to specify +a domain to match, or accept requests on the root path (/) in order to redirect +them to /dashboard/. + +```yaml +# Create an IngressRoute for the dashboard +ingressRoute: + dashboard: + enabled: true + # Custom match rule with host domain + matchRule: Host(`traefik-dashboard.example.com`) + entryPoints: ["websecure"] + # Add custom middlewares : authentication and redirection + middlewares: + - name: traefik-dashboard-auth + +# Create the custom middlewares used by the IngressRoute dashboard (can also be created in another way). +# /!\ Yes, you need to replace "changeme" password with a better one. /!\ +extraObjects: + - apiVersion: v1 + kind: Secret + metadata: + name: traefik-dashboard-auth-secret + type: kubernetes.io/basic-auth + stringData: + username: admin + password: changeme + + - apiVersion: traefik.io/v1alpha1 + kind: Middleware + metadata: + name: traefik-dashboard-auth + spec: + basicAuth: + secret: traefik-dashboard-auth-secret +``` + +# Publish and protect Traefik Dashboard with an Ingress + +To expose the dashboard without IngressRoute, it's more complicated and less +secure. You'll need to create an internal Service exposing Traefik API with +special _traefik_ entrypoint. This internal Service can be created from an other tool, with the `extraObjects` section or using [custom services](#add-custom-internal-services). + +You'll need to double check: +1. Service selector with your setup. +2. Middleware annotation on the ingress, _default_ should be replaced with traefik's namespace + +```yaml +ingressRoute: + dashboard: + enabled: false +additionalArguments: +- "--api.insecure=true" +# Create the service, middleware and Ingress used to expose the dashboard (can also be created in another way). +# /!\ Yes, you need to replace "changeme" password with a better one. /!\ +extraObjects: + - apiVersion: v1 + kind: Service + metadata: + name: traefik-api + spec: + type: ClusterIP + selector: + app.kubernetes.io/name: traefik + app.kubernetes.io/instance: traefik-default + ports: + - port: 8080 + name: traefik + targetPort: 8080 + protocol: TCP + + - apiVersion: v1 + kind: Secret + metadata: + name: traefik-dashboard-auth-secret + type: kubernetes.io/basic-auth + stringData: + username: admin + password: changeme + + - apiVersion: traefik.io/v1alpha1 + kind: Middleware + metadata: + name: traefik-dashboard-auth + spec: + basicAuth: + secret: traefik-dashboard-auth-secret + + - apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: traefik-dashboard + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.middlewares: default-traefik-dashboard-auth@kubernetescrd + spec: + rules: + - host: traefik-dashboard.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: traefik-api + port: + name: traefik +``` + + +# Install on AWS + +It can use [native AWS support](https://kubernetes.io/docs/concepts/services-networking/service/#aws-nlb-support) on Kubernetes + +```yaml +service: + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: nlb +``` + +Or if [AWS LB controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/service/annotations/#legacy-cloud-provider) is installed : +```yaml +service: + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip +``` + +# Install on GCP + +A [regional IP with a Service](https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip#use_a_service) can be used +```yaml +service: + spec: + loadBalancerIP: "1.2.3.4" +``` + +Or a [global IP on Ingress](https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip#use_an_ingress) +```yaml +service: + type: NodePort +extraObjects: + - apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: traefik + annotations: + kubernetes.io/ingress.global-static-ip-name: "myGlobalIpName" + spec: + defaultBackend: + service: + name: traefik + port: + number: 80 +``` + +Or a [global IP on a Gateway](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways) with continuous HTTPS encryption. + +```yaml +ports: + websecure: + appProtocol: HTTPS # Hint for Google L7 load balancer +service: + type: ClusterIP +extraObjects: +- apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + metadata: + name: traefik + annotations: + networking.gke.io/certmap: "myCertificateMap" + spec: + gatewayClassName: gke-l7-global-external-managed + addresses: + - type: NamedAddress + value: "myGlobalIPName" + listeners: + - name: https + protocol: HTTPS + port: 443 +- apiVersion: gateway.networking.k8s.io/v1beta1 + kind: HTTPRoute + metadata: + name: traefik + spec: + parentRefs: + - kind: Gateway + name: traefik + rules: + - backendRefs: + - name: traefik + port: 443 +- apiVersion: networking.gke.io/v1 + kind: HealthCheckPolicy + metadata: + name: traefik + spec: + default: + config: + type: HTTP + httpHealthCheck: + port: 8080 + requestPath: /ping + targetRef: + group: "" + kind: Service + name: traefik +``` + +# Install on Azure + +A [static IP on a resource group](https://learn.microsoft.com/en-us/azure/aks/static-ip) can be used: + +```yaml +service: + spec: + loadBalancerIP: "1.2.3.4" + annotations: + service.beta.kubernetes.io/azure-load-balancer-resource-group: myResourceGroup +``` + +Here is a more complete example, using also native Let's encrypt feature of Traefik Proxy with Azure DNS: + +```yaml +persistence: + enabled: true + size: 128Mi +certificatesResolvers: + letsencrypt: + acme: + email: "{{ letsencrypt_email }}" + #caServer: https://acme-v02.api.letsencrypt.org/directory # Production server + caServer: https://acme-staging-v02.api.letsencrypt.org/directory # Staging server + dnsChallenge: + provider: azuredns + storage: /data/acme.json +env: + - name: AZURE_CLIENT_ID + value: "{{ azure_dns_challenge_application_id }}" + - name: AZURE_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: azuredns-secret + key: client-secret + - name: AZURE_SUBSCRIPTION_ID + value: "{{ azure_subscription_id }}" + - name: AZURE_TENANT_ID + value: "{{ azure_tenant_id }}" + - name: AZURE_RESOURCE_GROUP + value: "{{ azure_resource_group }}" +deployment: + initContainers: + - name: volume-permissions + image: busybox:latest + command: ["sh", "-c", "ls -la /; touch /data/acme.json; chmod -v 600 /data/acme.json"] + volumeMounts: + - mountPath: /data + name: data +podSecurityContext: + fsGroup: 65532 + fsGroupChangePolicy: "OnRootMismatch" +service: + spec: + type: LoadBalancer + annotations: + service.beta.kubernetes.io/azure-load-balancer-resource-group: "{{ azure_node_resource_group }}" + service.beta.kubernetes.io/azure-pip-name: "{{ azure_resource_group }}" + service.beta.kubernetes.io/azure-dns-label-name: "{{ azure_resource_group }}" + service.beta.kubernetes.io/azure-allowed-ip-ranges: "{{ ip_range | join(',') }}" +extraObjects: + - apiVersion: v1 + kind: Secret + metadata: + name: azuredns-secret + namespace: traefik + type: Opaque + stringData: + client-secret: "{{ azure_dns_challenge_application_secret }}" +``` + +# Use an IngressClass + +Default install comes with an `IngressClass` resource that can be enabled on providers. + +Here's how one can enable it on CRD & Ingress Kubernetes provider: + +```yaml +ingressClass: + name: traefik +providers: + kubernetesCRD: + ingressClass: traefik + kubernetesIngress: + ingressClass: traefik +``` + +# Use HTTP3 + +By default, it will use a Load balancers with mixed protocols on `websecure` +entrypoint. They are available since v1.20 and in beta as of Kubernetes v1.24. +Availability may depend on your Kubernetes provider. + +When using TCP and UDP with a single service, you may encounter [this issue](https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741) from Kubernetes. +If you want to avoid this issue, you can set `ports.websecure.http3.advertisedPort` +to an other value than 443 + +```yaml +ports: + websecure: + http3: + enabled: true +``` + +You can also create two `Service`, one for TCP and one for UDP: + +```yaml +ports: + websecure: + http3: + enabled: true +service: + single: false +``` + +# Use PROXY protocol on Digital Ocean + +PROXY protocol is a protocol for sending client connection information, such as origin IP addresses and port numbers, to the final backend server, rather than discarding it at the load balancer. + +```yaml +.DOTrustedIPs: &DOTrustedIPs + - 127.0.0.1/32 + - 10.120.0.0/16 + +service: + enabled: true + type: LoadBalancer + annotations: + # This will tell DigitalOcean to enable the proxy protocol. + service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true" + spec: + # This is the default and should stay as cluster to keep the DO health checks working. + externalTrafficPolicy: Cluster + +ports: + web: + forwardedHeaders: + trustedIPs: *DOTrustedIPs + proxyProtocol: + trustedIPs: *DOTrustedIPs + websecure: + forwardedHeaders: + trustedIPs: *DOTrustedIPs + proxyProtocol: + trustedIPs: *DOTrustedIPs +``` + +# Enable plugin storage + +This chart follows common security practices: it runs as non root with a readonly root filesystem. +When enabling a plugin which needs storage, you have to add it to the deployment. + +Here is a simple example with crowdsec. You may want to replace with your plugin or see complete exemple on crowdsec [here](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/kubernetes/README.md). + +```yaml +deployment: + additionalVolumes: + - name: plugins +additionalVolumeMounts: +- name: plugins + mountPath: /plugins-storage +additionalArguments: +- "--experimental.plugins.bouncer.moduleName=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" +- "--experimental.plugins.bouncer.version=v1.1.9" +``` + +# Use Traefik native Let's Encrypt integration, without cert-manager + +In Traefik Proxy, ACME certificates are stored in a JSON file. + +This file needs to have 0600 permissions, meaning, only the owner of the file has full read and write access to it. +By default, Kubernetes recursively changes ownership and permissions for the content of each volume. + +=> An initContainer can be used to avoid an issue on this sensitive file. +See [#396](https://github.com/traefik/traefik-helm-chart/issues/396) for more details. + +Once the provider is ready, it can be used in an `IngressRoute`: + +```yaml +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: [...] +spec: + entryPoints: [...] + routes: [...] + tls: + certResolver: letsencrypt +``` + +:information_source: Change `apiVersion` to `traefik.containo.us/v1alpha1` for charts prior to v28.0.0 + +See [the list of supported providers](https://doc.traefik.io/traefik/https/acme/#providers) for others. + +## Example with CloudFlare + +This example needs a CloudFlare token in a Kubernetes `Secret` and a working `StorageClass`. + +**Step 1**: Create `Secret` with CloudFlare token: + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: cloudflare +type: Opaque +stringData: + token: {{ SET_A_VALID_TOKEN_HERE }} +``` + +**Step 2**: + +```yaml +persistence: + enabled: true + storageClass: xxx +certificatesResolvers: + letsencrypt: + acme: + dnsChallenge: + provider: cloudflare + storage: /data/acme.json +env: + - name: CF_DNS_API_TOKEN + valueFrom: + secretKeyRef: + name: cloudflare + key: token +deployment: + initContainers: + - name: volume-permissions + image: busybox:latest + command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"] + volumeMounts: + - mountPath: /data + name: data +podSecurityContext: + fsGroup: 65532 + fsGroupChangePolicy: "OnRootMismatch" +``` + +>[!NOTE] +> With [Traefik Hub](https://traefik.io/traefik-hub/), certificates can be stored as a `Secret` on Kubernetes with `distributedAcme` resolver. + +# Provide default certificate with cert-manager and CloudFlare DNS + +Setup: + +* cert-manager installed in `cert-manager` namespace +* A cloudflare account on a DNS Zone + +**Step 1**: Create `Secret` and `Issuer` needed by `cert-manager` with your API Token. +See [cert-manager documentation](https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/) +for creating this token with needed rights: + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: cloudflare + namespace: traefik +type: Opaque +stringData: + api-token: XXX +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: cloudflare + namespace: traefik +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: email@example.com + privateKeySecretRef: + name: cloudflare-key + solvers: + - dns01: + cloudflare: + apiTokenSecretRef: + name: cloudflare + key: api-token +``` + +**Step 2**: Create `Certificate` in traefik namespace + +```yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: wildcard-example-com + namespace: traefik +spec: + secretName: wildcard-example-com-tls + dnsNames: + - "example.com" + - "*.example.com" + issuerRef: + name: cloudflare + kind: Issuer +``` + +**Step 3**: Check that it's ready + +```bash +kubectl get certificate -n traefik +``` + +If needed, logs of cert-manager pod can give you more information + +**Step 4**: Use it on the TLS Store in **values.yaml** file for this Helm Chart + +```yaml +tlsStore: + default: + defaultCertificate: + secretName: wildcard-example-com-tls +``` + +**Step 5**: Enjoy. All your `IngressRoute` use this certificate by default now. + +They should use websecure entrypoint like this: + +```yaml +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: example-com-tls +spec: + entryPoints: + - websecure + routes: + - match: Host(`test.example.com`) + kind: Rule + services: + - name: XXXX + port: 80 +``` + +# Add custom (internal) services + +In some cases you might want to have more than one Traefik service within your cluster, +e.g. a default (external) one and a service that is only exposed internally to pods within your cluster. + +The `service.additionalServices` allows you to add an arbitrary amount of services, +provided as a name to service details mapping; for example you can use the following values: + +```yaml +service: + additionalServices: + internal: + type: ClusterIP + labels: + traefik-service-label: internal +``` + +Ports can then be exposed on this service by using the port name to boolean mapping `expose` on the respective port; +e.g. to expose the `traefik` API port on your internal service so pods within your cluster can use it, you can do: + +```yaml +ports: + traefik: + expose: + # Sensitive data should not be exposed on the internet + # => Keep this disabled ! + default: false + internal: true +``` + +This will then provide an additional Service manifest, looking like this: + +```yaml +--- +# Source: traefik/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: traefik-internal + namespace: traefik +[...] +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: traefik + app.kubernetes.io/instance: traefik-traefik + ports: + - port: 8080 + name: "traefik" + targetPort: traefik + protocol: TCP +``` + +# Use this Chart as a dependency of your own chart + + +First, let's create a default Helm Chart, with Traefik as a dependency. +```bash +helm create foo +cd foo +echo " +dependencies: + - name: traefik + version: "24.0.0" + repository: "https://traefik.github.io/charts" +" >> Chart.yaml +``` + +Second, let's tune some values like enabling HPA: + +```bash +cat <<-EOF >> values.yaml +traefik: + autoscaling: + enabled: true + maxReplicas: 3 +EOF +``` + +Third, one can see if it works as expected: +```bash +helm dependency update +helm dependency build +helm template . | grep -A 14 -B 3 Horizontal +``` + +It should produce this output: + +```yaml +--- +# Source: foo/charts/traefik/templates/hpa.yaml +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: release-name-traefik + namespace: flux-system + labels: + app.kubernetes.io/name: traefik + app.kubernetes.io/instance: release-name-flux-system + helm.sh/chart: traefik-24.0.0 + app.kubernetes.io/managed-by: Helm +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: release-name-traefik + maxReplicas: 3 +``` + +# Configure TLS + +The [TLS options](https://doc.traefik.io/traefik/https/tls/#tls-options) allow one to configure some parameters of the TLS connection. + +```yaml +tlsOptions: + default: + labels: {} + sniStrict: true + custom-options: + labels: {} + curvePreferences: + - CurveP521 + - CurveP384 +``` + +# Use latest build of Traefik v3 from master + +An experimental build of Traefik Proxy is available on a specific repository. + +It can be used with those _values_: + +```yaml +image: + repository: traefik/traefik + tag: experimental-v3.0 +``` + +# Use Prometheus Operator + +An optional support of this operator is included in this Chart. See documentation of this operator for more details. + +It can be used with those _values_: + +```yaml +metrics: + prometheus: + service: + enabled: true + disableAPICheck: false + serviceMonitor: + enabled: true + metricRelabelings: + - sourceLabels: [__name__] + separator: ; + regex: ^fluentd_output_status_buffer_(oldest|newest)_.+ + replacement: $1 + action: drop + relabelings: + - sourceLabels: [__meta_kubernetes_pod_node_name] + separator: ; + regex: ^(.*)$ + targetLabel: nodename + replacement: $1 + action: replace + jobLabel: traefik + interval: 30s + honorLabels: true + prometheusRule: + enabled: true + rules: + - alert: TraefikDown + expr: up{job="traefik"} == 0 + for: 5m + labels: + context: traefik + severity: warning + annotations: + summary: "Traefik Down" + description: "{{ $labels.pod }} on {{ $labels.nodename }} is down" +``` + +# Use kubernetes Gateway API + +One can use the new stable kubernetes gateway API provider setting the following _values_: + +```yaml +providers: + kubernetesGateway: + enabled: true +``` + +
+ +With those values, a whoami service can be exposed with a HTTPRoute + +```yaml +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: whoami +spec: + replicas: 2 + selector: + matchLabels: + app: whoami + template: + metadata: + labels: + app: whoami + spec: + containers: + - name: whoami + image: traefik/whoami + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoami +spec: + selector: + app: whoami + ports: + - protocol: TCP + port: 80 + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: whoami +spec: + parentRefs: + - name: traefik-gateway + hostnames: + - whoami.docker.localhost + rules: + - matches: + - path: + type: Exact + value: / + + backendRefs: + - name: whoami + port: 80 + weight: 1 +``` + +Once it's applied, whoami should be accessible on http://whoami.docker.localhost/ + +
+ +:information_source: In this example, `Deployment` and `HTTPRoute` should be deployed in the same namespace as the Traefik Gateway: Chart namespace. + +# Use Kubernetes Gateway API with cert-manager + +One can use the new stable kubernetes gateway API provider with automatic TLS certificates delivery (with cert-manager) setting the following _values_: + +```yaml +providers: + kubernetesGateway: + enabled: true +gateway: + enabled: true + annotations: + cert-manager.io/issuer: selfsigned-issuer + listeners: + websecure: + hostname: whoami.docker.localhost + port: 8443 + protocol: HTTPS + certificateRefs: + - name: whoami-tls +``` + +Install cert-manager: + +```bash +helm repo add jetstack https://charts.jetstack.io --force-update +helm upgrade --install \ +cert-manager jetstack/cert-manager \ +--namespace cert-manager \ +--create-namespace \ +--version v1.15.1 \ +--set crds.enabled=true \ +--set "extraArgs={--enable-gateway-api}" +``` + +
+ +With those values, a whoami service can be exposed with HTTPRoute on both HTTP and HTTPS + +```yaml +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: whoami +spec: + replicas: 2 + selector: + matchLabels: + app: whoami + template: + metadata: + labels: + app: whoami + spec: + containers: + - name: whoami + image: traefik/whoami + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoami +spec: + selector: + app: whoami + ports: + - protocol: TCP + port: 80 + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: whoami +spec: + parentRefs: + - name: traefik-gateway + hostnames: + - whoami.docker.localhost + rules: + - matches: + - path: + type: Exact + value: / + + backendRefs: + - name: whoami + port: 80 + weight: 1 + +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer +spec: + selfSigned: {} +``` + +Once it's applied, whoami should be accessible on https://whoami.docker.localhost/ + +
diff --git a/utils/assets/charts/traefik/Guidelines.md b/utils/assets/charts/traefik/Guidelines.md new file mode 100644 index 0000000..3b72a40 --- /dev/null +++ b/utils/assets/charts/traefik/Guidelines.md @@ -0,0 +1,34 @@ +# Traefik Helm Chart Guidelines + +This document outlines the guidelines for developing, managing and extending the Traefik helm chart. + +This Helm Chart is documented using field description from comments with [helm-docs](https://github.com/norwoodj/helm-docs). + +It comes with a JSON schema generated from values with [helm schema](https://github.com/losisin/helm-values-schema-json) plugin. + +## Feature Example + +```yaml +logs: + general: + # -- Set [logs format](https://doc.traefik.io/traefik/observability/logs/#format) + format: # @schema enum:["common", "json", null]; type:[string, null]; default: "common" +``` + +Documention is on the first comment, starting with `# --` +Specific instructions for schema, when needed, are done with the inline comment starting with `# @schema`. + +## Whitespace + +Extra whitespace is to be avoided in templating. Conditionals should chomp whitespace: + +```yaml +{{- if .Values }} +{{- end }} +``` + +There should be an empty commented line between each primary key in the values.yaml file to separate features from each other. + +## Values YAML Design + +The values.yaml file is designed to be user-friendly. It does not have to resemble the templated configuration if it is not conducive. Similarly, value names to not have to correspond to fields in the template if it is not conducive. diff --git a/utils/assets/charts/traefik/LICENSE b/utils/assets/charts/traefik/LICENSE new file mode 100644 index 0000000..907ff83 --- /dev/null +++ b/utils/assets/charts/traefik/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Containous + Copyright 2020 Traefik Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/utils/assets/charts/traefik/README.md b/utils/assets/charts/traefik/README.md new file mode 100644 index 0000000..cd963c1 --- /dev/null +++ b/utils/assets/charts/traefik/README.md @@ -0,0 +1,158 @@ +# Traefik + +[Traefik](https://traefik.io/) is a modern HTTP reverse proxy and load balancer made to deploy +microservices with ease. + +## Introduction + +Starting with v28.x, this chart now bootstraps Traefik Proxy version 3 as a Kubernetes ingress controller, +using Custom Resources `IngressRoute`: . + +It's possible to use this chart with Traefik Proxy v2 using v27.x +This chart support policy is aligned with [upstream support policy](https://doc.traefik.io/traefik/deprecation/releases/) of Traefik Proxy. + +See [Migration guide from v2 to v3](https://doc.traefik.io/traefik/v3.0/migration/v2-to-v3/) and upgrading section of this chart on CRDs. + +### Philosophy + +The Traefik HelmChart is focused on Traefik deployment configuration. + +To keep this HelmChart as generic as possible we tend +to avoid integrating any third party solutions nor any specific use cases. + +Accordingly, the encouraged approach to fulfill your needs: + +1. Override the default Traefik configuration values ([yaml file or cli](https://helm.sh/docs/chart_template_guide/values_files/)) +2. Append your own configurations (`kubectl apply -f myconf.yaml`) + +[Examples](https://github.com/traefik/traefik-helm-chart/blob/master/EXAMPLES.md) of common usage are provided. + +If needed, one may use [extraObjects](./traefik/tests/values/extra.yaml) or extend this HelmChart [as a Subchart](https://helm.sh/docs/chart_template_guide/subcharts_and_globals/). + +## Installing + +### Prerequisites + +1. [x] Helm **v3 > 3.9.0** [installed](https://helm.sh/docs/using_helm/#installing-helm): `helm version` +2. [x] Traefik's chart repository: `helm repo add traefik https://traefik.github.io/charts` + +### Kubernetes Version Support + +Due to changes in CRD version support, the following versions of the chart are usable and supported on the following Kubernetes versions: + +| | Kubernetes v1.15 and below | Kubernetes v1.16-v1.21 | Kubernetes v1.22 and above | +|-------------------------|-----------------------------|------------------------|----------------------------| +| Chart v9.20.2 and below | [x] | [x] | | +| Chart v10.0.0 and above | | [x] | [x] | +| Chart v22.0.0 and above | | | [x] | + +### CRDs Support of Traefik Proxy + +Due to changes in API Group of Traefik CRDs from `containo.us` to `traefik.io`, this Chart install CRDs needed by default Traefik Proxy version, following this table: + +| | `containo.us` | `traefik.io` | +|-------------------------|-----------------------------|------------------------| +| Chart v22.0.0 and below | [x] | | +| Chart v23.0.0 and above | [x] | [x] | +| Chart v28.0.0 and above | | [x] | + +### Deploying Traefik + +```bash +helm install traefik traefik/traefik +``` + +or: + +```bash +helm install traefik oci://ghcr.io/traefik/helm/traefik +``` + +You can customize the install with a `values` file. There are some [EXAMPLES](./EXAMPLES.md) provided. +Complete documentation on all available parameters is in the [default file](./traefik/values.yaml). + +```bash +helm install -f myvalues.yaml traefik traefik/traefik +``` + +🛂 **Warning**: Helm v2 support was removed in the chart version 10.0.0. + +## Upgrading + +One can check what has changed in the [Changelog](./traefik/Changelog.md). + +:information_source: With Helm v3, CRDs created by this chart can not be updated, cf. the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions). + +:warning: Please read carefully release notes of this chart before upgrading CRDs. + +```bash +# Update repository +helm repo update +# See current Chart & Traefik version +helm search repo traefik/traefik +# Update CRDs (Traefik Proxy v3 CRDs) +kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik/crds/ +# Upgrade Traefik +helm upgrade traefik traefik/traefik +``` + +New major version indicates that there is an incompatible breaking change. + +#### Upgrade up to 27.X + +When upgrading on Traefik Proxy v2 version, one need to stay at Traefik Helm Chart v27.x. The command to upgrade to the latest Traefik Proxy v2 CRD is: + +```bash +kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik/crds/?ref=v27 +``` + +### Upgrading after 18.X+ + +It's detailed in [release notes](https://github.com/traefik/traefik-helm-chart/releases). + +### Upgrading from 17.x to 18.x + +Since v18.x, this chart by default merges TCP and UDP ports into a single (LoadBalancer) `Service`. +Load balancers with mixed protocols are available since v1.20 and in +[beta as of Kubernetes v1.24](https://kubernetes.io/docs/concepts/services-networking/service/#load-balancers-with-mixed-protocol-types). +Availability may depend on your Kubernetes provider. + +To retain the old default behavior, set `service.single` to `false` in your values. + +When using TCP and UDP with a single service, you may encounter +[this issue](https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741) +from Kubernetes. + +On HTTP/3, if you want to avoid this issue, you can set +`ports.websecure.http3.advertisedPort` to an other value than `443` + +If you were previously using HTTP/3, you should update your values as follows: + - Replace the old value (`true`) of `ports.websecure.http3` with a key `enabled: true` + - Remove `experimental.http3.enabled=true` entry + +### Upgrading from 16.x to 17.x + +Since v17.x, this chart provides unified labels following +[Kubernetes recommendation](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/). + +This version needs to change an immutable field, which is not supported by +Kubernetes and Helm, see [this issue](https://github.com/helm/helm/issues/7350) +for more details. +So you will have to delete your `Service`, `Deployment` or `DaemonSet` in +order to be able to upgrade. + +You may also upgrade by deploying another Traefik to a different namespace and +removing after your first Traefik. + +Alternatively, since version 20.3.0 of this chart, you may set `instanceLabelOverride` to the previous value of that label. +This will override the new `Release.Name-Release.Namespace` pattern to avoid any (longer) downtime. + +## Contributing + +If you want to contribute to this chart, please read the [Contributing Guide](./CONTRIBUTING.md). + +Thanks to all the people who have already contributed! + + + + diff --git a/utils/assets/charts/traefik/VALUES.md b/utils/assets/charts/traefik/VALUES.md new file mode 100644 index 0000000..aa3d014 --- /dev/null +++ b/utils/assets/charts/traefik/VALUES.md @@ -0,0 +1,321 @@ +# traefik + +![Version: 33.0.0](https://img.shields.io/badge/Version-33.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v3.2.0](https://img.shields.io/badge/AppVersion-v3.2.0-informational?style=flat-square) + +A Traefik based Kubernetes ingress controller + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| mloiseleur | | | +| charlie-haley | | | +| darkweaver87 | | | +| jnoordsij | | | + +## Source Code + +* +* + +## Requirements + +Kubernetes: `>=1.22.0-0` + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| additionalArguments | list | `[]` | Additional arguments to be passed at Traefik's binary See [CLI Reference](https://docs.traefik.io/reference/static-configuration/cli/) Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}"` | +| additionalVolumeMounts | list | `[]` | Additional volumeMounts to add to the Traefik container | +| affinity | object | `{}` | on nodes where no other traefik pods are scheduled. It should be used when hostNetwork: true to prevent port conflicts | +| autoscaling.enabled | bool | `false` | Create HorizontalPodAutoscaler object. See EXAMPLES.md for more details. | +| certificatesResolvers | object | `{}` | Certificates resolvers configuration. Ref: https://doc.traefik.io/traefik/https/acme/#certificate-resolvers See EXAMPLES.md for more details. | +| commonLabels | object | `{}` | Add additional label to all resources | +| core.defaultRuleSyntax | string | `""` | Can be used to use globally v2 router syntax See https://doc.traefik.io/traefik/v3.0/migration/v2-to-v3/#new-v3-syntax-notable-changes | +| deployment.additionalContainers | list | `[]` | Additional containers (e.g. for metric offloading sidecars) | +| deployment.additionalVolumes | list | `[]` | Additional volumes available for use with initContainers and additionalContainers | +| deployment.annotations | object | `{}` | Additional deployment annotations (e.g. for jaeger-operator sidecar injection) | +| deployment.dnsConfig | object | `{}` | Custom pod [DNS config](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#poddnsconfig-v1-core) | +| deployment.dnsPolicy | string | `""` | Custom pod DNS policy. Apply if `hostNetwork: true` | +| deployment.enabled | bool | `true` | Enable deployment | +| deployment.healthchecksHost | string | `""` | | +| deployment.healthchecksPort | string | `nil` | | +| deployment.healthchecksScheme | string | `nil` | | +| deployment.hostAliases | list | `[]` | Custom [host aliases](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/) | +| deployment.imagePullSecrets | list | `[]` | Pull secret for fetching traefik container image | +| deployment.initContainers | list | `[]` | Additional initContainers (e.g. for setting file permission as shown below) | +| deployment.kind | string | `"Deployment"` | Deployment or DaemonSet | +| deployment.labels | object | `{}` | Additional deployment labels (e.g. for filtering deployment by custom labels) | +| deployment.lifecycle | object | `{}` | Pod lifecycle actions | +| deployment.livenessPath | string | `""` | Override the liveness path. Default: /ping | +| deployment.minReadySeconds | int | `0` | The minimum number of seconds Traefik needs to be up and running before the DaemonSet/Deployment controller considers it available | +| deployment.podAnnotations | object | `{}` | Additional pod annotations (e.g. for mesh injection or prometheus scraping) It supports templating. One can set it with values like traefik/name: '{{ template "traefik.name" . }}' | +| deployment.podLabels | object | `{}` | Additional Pod labels (e.g. for filtering Pod by custom labels) | +| deployment.readinessPath | string | `""` | | +| deployment.replicas | int | `1` | Number of pods of the deployment (only applies when kind == Deployment) | +| deployment.revisionHistoryLimit | string | `nil` | Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) | +| deployment.runtimeClassName | string | `""` | Set a runtimeClassName on pod | +| deployment.shareProcessNamespace | bool | `false` | Use process namespace sharing | +| deployment.terminationGracePeriodSeconds | int | `60` | Amount of time (in seconds) before Kubernetes will send the SIGKILL signal if Traefik does not shut down | +| env | list | See _values.yaml_ | Additional Environment variables to be passed to Traefik's binary | +| envFrom | list | `[]` | Environment variables to be passed to Traefik's binary from configMaps or secrets | +| experimental.kubernetesGateway.enabled | bool | `false` | Enable traefik experimental GatewayClass CRD | +| experimental.plugins | object | `{}` | Enable traefik experimental plugins | +| extraObjects | list | `[]` | Extra objects to deploy (value evaluated as a template) In some cases, it can avoid the need for additional, extended or adhoc deployments. See #595 for more details and traefik/tests/values/extra.yaml for example. | +| gateway.annotations | object | `{}` | Additional gateway annotations (e.g. for cert-manager.io/issuer) | +| gateway.enabled | bool | `true` | When providers.kubernetesGateway.enabled, deploy a default gateway | +| gateway.infrastructure | object | `{}` | [Infrastructure](https://kubernetes.io/blog/2023/11/28/gateway-api-ga/#gateway-infrastructure-labels) | +| gateway.listeners | object | `{"web":{"hostname":"","namespacePolicy":null,"port":8000,"protocol":"HTTP"}}` | Define listeners | +| gateway.listeners.web.hostname | string | `""` | Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) | +| gateway.listeners.web.namespacePolicy | string | `nil` | Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces | +| gateway.listeners.web.port | int | `8000` | Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. The port must match a port declared in ports section. | +| gateway.name | string | `""` | Set a custom name to gateway | +| gateway.namespace | string | `""` | By default, Gateway is created in the same `Namespace` than Traefik. | +| gatewayClass.enabled | bool | `true` | When providers.kubernetesGateway.enabled and gateway.enabled, deploy a default gatewayClass | +| gatewayClass.labels | object | `{}` | Additional gatewayClass labels (e.g. for filtering gateway objects by custom labels) | +| gatewayClass.name | string | `""` | Set a custom name to GatewayClass | +| globalArguments | list | `["--global.checknewversion","--global.sendanonymoususage"]` | Global command arguments to be passed to all traefik's pods | +| hostNetwork | bool | `false` | If hostNetwork is true, runs traefik in the host network namespace To prevent unschedulabel pods due to port collisions, if hostNetwork=true and replicas>1, a pod anti-affinity is recommended and will be set if the affinity is left as default. | +| hub.apimanagement.admission.listenAddr | string | `""` | WebHook admission server listen address. Default: "0.0.0.0:9943". | +| hub.apimanagement.admission.secretName | string | `""` | Certificate of the WebHook admission server. Default: "hub-agent-cert". | +| hub.apimanagement.enabled | bool | `false` | Set to true in order to enable API Management. Requires a valid license token. | +| hub.redis.cluster | string | `nil` | Enable Redis Cluster. Default: true. | +| hub.redis.database | string | `nil` | Database used to store information. Default: "0". | +| hub.redis.endpoints | string | `""` | Endpoints of the Redis instances to connect to. Default: "". | +| hub.redis.password | string | `""` | The password to use when connecting to Redis endpoints. Default: "". | +| hub.redis.sentinel.masterset | string | `""` | Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". | +| hub.redis.sentinel.password | string | `""` | Password to use for sentinel authentication (can be different from endpoint password). Default: "". | +| hub.redis.sentinel.username | string | `""` | Username to use for sentinel authentication (can be different from endpoint username). Default: "". | +| hub.redis.timeout | string | `""` | Timeout applied on connection with redis. Default: "0s". | +| hub.redis.tls.ca | string | `""` | Path to the certificate authority used for the secured connection. | +| hub.redis.tls.cert | string | `""` | Path to the public certificate used for the secure connection. | +| hub.redis.tls.insecureSkipVerify | bool | `false` | When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. | +| hub.redis.tls.key | string | `""` | Path to the private key used for the secure connection. | +| hub.redis.username | string | `""` | The username to use when connecting to Redis endpoints. Default: "". | +| hub.sendlogs | string | `nil` | | +| hub.token | string | `""` | Name of `Secret` with key 'token' set to a valid license token. It enables API Gateway. | +| image.pullPolicy | string | `"IfNotPresent"` | Traefik image pull policy | +| image.registry | string | `"docker.io"` | Traefik image host registry | +| image.repository | string | `"traefik"` | Traefik image repository | +| image.tag | string | `nil` | defaults to appVersion | +| ingressClass | object | `{"enabled":true,"isDefaultClass":true,"name":""}` | Create a default IngressClass for Traefik | +| ingressRoute.dashboard.annotations | object | `{}` | Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) | +| ingressRoute.dashboard.enabled | bool | `false` | Create an IngressRoute for the dashboard | +| ingressRoute.dashboard.entryPoints | list | `["traefik"]` | Specify the allowed entrypoints to use for the dashboard ingress route, (e.g. traefik, web, websecure). By default, it's using traefik entrypoint, which is not exposed. /!\ Do not expose your dashboard without any protection over the internet /!\ | +| ingressRoute.dashboard.labels | object | `{}` | Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) | +| ingressRoute.dashboard.matchRule | string | `"PathPrefix(`/dashboard`) || PathPrefix(`/api`)"` | The router match rule used for the dashboard ingressRoute | +| ingressRoute.dashboard.middlewares | list | `[]` | Additional ingressRoute middlewares (e.g. for authentication) | +| ingressRoute.dashboard.services | list | `[{"kind":"TraefikService","name":"api@internal"}]` | The internal service used for the dashboard ingressRoute | +| ingressRoute.dashboard.tls | object | `{}` | TLS options (e.g. secret containing certificate) | +| ingressRoute.healthcheck.annotations | object | `{}` | Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class) | +| ingressRoute.healthcheck.enabled | bool | `false` | Create an IngressRoute for the healthcheck probe | +| ingressRoute.healthcheck.entryPoints | list | `["traefik"]` | Specify the allowed entrypoints to use for the healthcheck ingress route, (e.g. traefik, web, websecure). By default, it's using traefik entrypoint, which is not exposed. | +| ingressRoute.healthcheck.labels | object | `{}` | Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels) | +| ingressRoute.healthcheck.matchRule | string | `"PathPrefix(`/ping`)"` | The router match rule used for the healthcheck ingressRoute | +| ingressRoute.healthcheck.middlewares | list | `[]` | Additional ingressRoute middlewares (e.g. for authentication) | +| ingressRoute.healthcheck.services | list | `[{"kind":"TraefikService","name":"ping@internal"}]` | The internal service used for the healthcheck ingressRoute | +| ingressRoute.healthcheck.tls | object | `{}` | TLS options (e.g. secret containing certificate) | +| instanceLabelOverride | string | `""` | | +| livenessProbe.failureThreshold | int | `3` | The number of consecutive failures allowed before considering the probe as failed. | +| livenessProbe.initialDelaySeconds | int | `2` | The number of seconds to wait before starting the first probe. | +| livenessProbe.periodSeconds | int | `10` | The number of seconds to wait between consecutive probes. | +| livenessProbe.successThreshold | int | `1` | The minimum consecutive successes required to consider the probe successful. | +| livenessProbe.timeoutSeconds | int | `2` | The number of seconds to wait for a probe response before considering it as failed. | +| logs.access.addInternals | bool | `false` | Enables accessLogs for internal resources. Default: false. | +| logs.access.bufferingSize | string | `nil` | Set [bufferingSize](https://doc.traefik.io/traefik/observability/access-logs/#bufferingsize) | +| logs.access.enabled | bool | `false` | To enable access logs | +| logs.access.fields.general.defaultmode | string | `"keep"` | Set default mode for fields.names | +| logs.access.fields.general.names | object | `{}` | Names of the fields to limit. | +| logs.access.fields.headers | object | `{"defaultmode":"drop","names":{}}` | [Limit logged fields or headers](https://doc.traefik.io/traefik/observability/access-logs/#limiting-the-fieldsincluding-headers) | +| logs.access.fields.headers.defaultmode | string | `"drop"` | Set default mode for fields.headers | +| logs.access.filters | object | `{"minduration":"","retryattempts":false,"statuscodes":""}` | Set [filtering](https://docs.traefik.io/observability/access-logs/#filtering) | +| logs.access.filters.minduration | string | `""` | Set minDuration, to keep access logs when requests take longer than the specified duration | +| logs.access.filters.retryattempts | bool | `false` | Set retryAttempts, to keep the access logs when at least one retry has happened | +| logs.access.filters.statuscodes | string | `""` | Set statusCodes, to limit the access logs to requests with a status codes in the specified range | +| logs.access.format | string | `nil` | Set [access log format](https://doc.traefik.io/traefik/observability/access-logs/#format) | +| logs.general.filePath | string | `""` | To write the logs into a log file, use the filePath option. | +| logs.general.format | string | `nil` | Set [logs format](https://doc.traefik.io/traefik/observability/logs/#format) | +| logs.general.level | string | `"INFO"` | Alternative logging levels are TRACE, DEBUG, INFO, WARN, ERROR, FATAL, and PANIC. | +| logs.general.noColor | bool | `false` | When set to true and format is common, it disables the colorized output. | +| metrics.addInternals | bool | `false` | | +| metrics.otlp.addEntryPointsLabels | string | `nil` | Enable metrics on entry points. Default: true | +| metrics.otlp.addRoutersLabels | string | `nil` | Enable metrics on routers. Default: false | +| metrics.otlp.addServicesLabels | string | `nil` | Enable metrics on services. Default: true | +| metrics.otlp.enabled | bool | `false` | Set to true in order to enable the OpenTelemetry metrics | +| metrics.otlp.explicitBoundaries | list | `[]` | Explicit boundaries for Histogram data points. Default: [.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10] | +| metrics.otlp.grpc.enabled | bool | `false` | Set to true in order to send metrics to the OpenTelemetry Collector using gRPC | +| metrics.otlp.grpc.endpoint | string | `""` | Format: ://:. Default: http://localhost:4318/v1/metrics | +| metrics.otlp.grpc.insecure | bool | `false` | Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. | +| metrics.otlp.grpc.tls.ca | string | `""` | The path to the certificate authority, it defaults to the system bundle. | +| metrics.otlp.grpc.tls.cert | string | `""` | The path to the public certificate. When using this option, setting the key option is required. | +| metrics.otlp.grpc.tls.insecureSkipVerify | bool | `false` | When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. | +| metrics.otlp.grpc.tls.key | string | `""` | The path to the private key. When using this option, setting the cert option is required. | +| metrics.otlp.http.enabled | bool | `false` | Set to true in order to send metrics to the OpenTelemetry Collector using HTTP. | +| metrics.otlp.http.endpoint | string | `""` | Format: ://:. Default: http://localhost:4318/v1/metrics | +| metrics.otlp.http.headers | object | `{}` | Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. | +| metrics.otlp.http.tls.ca | string | `""` | The path to the certificate authority, it defaults to the system bundle. | +| metrics.otlp.http.tls.cert | string | `""` | The path to the public certificate. When using this option, setting the key option is required. | +| metrics.otlp.http.tls.insecureSkipVerify | string | `nil` | When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. | +| metrics.otlp.http.tls.key | string | `""` | The path to the private key. When using this option, setting the cert option is required. | +| metrics.otlp.pushInterval | string | `""` | Interval at which metrics are sent to the OpenTelemetry Collector. Default: 10s | +| metrics.prometheus.addEntryPointsLabels | string | `nil` | | +| metrics.prometheus.addRoutersLabels | string | `nil` | | +| metrics.prometheus.addServicesLabels | string | `nil` | | +| metrics.prometheus.buckets | string | `""` | | +| metrics.prometheus.disableAPICheck | string | `nil` | When set to true, it won't check if Prometheus Operator CRDs are deployed | +| metrics.prometheus.entryPoint | string | `"metrics"` | Entry point used to expose metrics. | +| metrics.prometheus.manualRouting | bool | `false` | | +| metrics.prometheus.prometheusRule.additionalLabels | object | `{}` | | +| metrics.prometheus.prometheusRule.enabled | bool | `false` | Enable optional CR for Prometheus Operator. See EXAMPLES.md for more details. | +| metrics.prometheus.prometheusRule.namespace | string | `""` | | +| metrics.prometheus.service.annotations | object | `{}` | | +| metrics.prometheus.service.enabled | bool | `false` | Create a dedicated metrics service to use with ServiceMonitor | +| metrics.prometheus.service.labels | object | `{}` | | +| metrics.prometheus.serviceMonitor.additionalLabels | object | `{}` | | +| metrics.prometheus.serviceMonitor.enableHttp2 | bool | `false` | | +| metrics.prometheus.serviceMonitor.enabled | bool | `false` | Enable optional CR for Prometheus Operator. See EXAMPLES.md for more details. | +| metrics.prometheus.serviceMonitor.followRedirects | bool | `false` | | +| metrics.prometheus.serviceMonitor.honorLabels | bool | `false` | | +| metrics.prometheus.serviceMonitor.honorTimestamps | bool | `false` | | +| metrics.prometheus.serviceMonitor.interval | string | `""` | | +| metrics.prometheus.serviceMonitor.jobLabel | string | `""` | | +| metrics.prometheus.serviceMonitor.metricRelabelings | list | `[]` | | +| metrics.prometheus.serviceMonitor.namespace | string | `""` | | +| metrics.prometheus.serviceMonitor.namespaceSelector | object | `{}` | | +| metrics.prometheus.serviceMonitor.relabelings | list | `[]` | | +| metrics.prometheus.serviceMonitor.scrapeTimeout | string | `""` | | +| namespaceOverride | string | `""` | This field override the default Release Namespace for Helm. It will not affect optional CRDs such as `ServiceMonitor` and `PrometheusRules` | +| nodeSelector | object | `{}` | nodeSelector is the simplest recommended form of node selection constraint. | +| persistence.accessMode | string | `"ReadWriteOnce"` | | +| persistence.annotations | object | `{}` | | +| persistence.enabled | bool | `false` | Enable persistence using Persistent Volume Claims ref: http://kubernetes.io/docs/user-guide/persistent-volumes/. It can be used to store TLS certificates along with `certificatesResolvers..acme.storage` option | +| persistence.existingClaim | string | `""` | | +| persistence.name | string | `"data"` | | +| persistence.path | string | `"/data"` | | +| persistence.size | string | `"128Mi"` | | +| persistence.storageClass | string | `""` | | +| persistence.subPath | string | `""` | Only mount a subpath of the Volume into the pod | +| persistence.volumeName | string | `""` | | +| podDisruptionBudget | object | `{"enabled":false,"maxUnavailable":null,"minAvailable":null}` | [Pod Disruption Budget](https://kubernetes.io/docs/reference/kubernetes-api/policy-resources/pod-disruption-budget-v1/) | +| podSecurityContext | object | See _values.yaml_ | [Pod Security Context](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context) | +| podSecurityPolicy | object | `{"enabled":false}` | Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding | +| ports.metrics.expose | object | `{"default":false}` | You may not want to expose the metrics port on production deployments. If you want to access it from outside your cluster, use `kubectl port-forward` or create a secure ingress | +| ports.metrics.exposedPort | int | `9100` | The exposed port for this service | +| ports.metrics.port | int | `9100` | When using hostNetwork, use another port to avoid conflict with node exporter: https://github.com/prometheus/prometheus/wiki/Default-port-allocations | +| ports.metrics.protocol | string | `"TCP"` | The port protocol (TCP/UDP) | +| ports.traefik.expose | object | `{"default":false}` | You SHOULD NOT expose the traefik port on production deployments. If you want to access it from outside your cluster, use `kubectl port-forward` or create a secure ingress | +| ports.traefik.exposedPort | int | `8080` | The exposed port for this service | +| ports.traefik.hostIP | string | `nil` | Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which means it's listening on all your interfaces and all your IPs. You may want to set this value if you need traefik to listen on specific interface only. | +| ports.traefik.hostPort | string | `nil` | Use hostPort if set. | +| ports.traefik.port | int | `8080` | | +| ports.traefik.protocol | string | `"TCP"` | The port protocol (TCP/UDP) | +| ports.web.expose.default | bool | `true` | | +| ports.web.exposedPort | int | `80` | | +| ports.web.forwardedHeaders.insecure | bool | `false` | | +| ports.web.forwardedHeaders.trustedIPs | list | `[]` | Trust forwarded headers information (X-Forwarded-*). | +| ports.web.nodePort | string | `nil` | See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) | +| ports.web.port | int | `8000` | | +| ports.web.protocol | string | `"TCP"` | | +| ports.web.proxyProtocol.insecure | bool | `false` | | +| ports.web.proxyProtocol.trustedIPs | list | `[]` | Enable the Proxy Protocol header parsing for the entry point | +| ports.web.redirectTo | object | `{}` | | +| ports.web.targetPort | string | `nil` | | +| ports.web.transport | object | `{"keepAliveMaxRequests":null,"keepAliveMaxTime":null,"lifeCycle":{"graceTimeOut":null,"requestAcceptGraceTimeout":null},"respondingTimeouts":{"idleTimeout":null,"readTimeout":null,"writeTimeout":null}}` | Set transport settings for the entrypoint; see also https://doc.traefik.io/traefik/routing/entrypoints/#transport | +| ports.websecure.allowACMEByPass | bool | `false` | See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#allowacmebypass) | +| ports.websecure.appProtocol | string | `nil` | See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol) | +| ports.websecure.containerPort | string | `nil` | | +| ports.websecure.expose.default | bool | `true` | | +| ports.websecure.exposedPort | int | `443` | | +| ports.websecure.forwardedHeaders.insecure | bool | `false` | | +| ports.websecure.forwardedHeaders.trustedIPs | list | `[]` | Trust forwarded headers information (X-Forwarded-*). | +| ports.websecure.hostPort | string | `nil` | | +| ports.websecure.http3.advertisedPort | string | `nil` | | +| ports.websecure.http3.enabled | bool | `false` | | +| ports.websecure.middlewares | list | `[]` | /!\ It introduces here a link between your static configuration and your dynamic configuration /!\ It follows the provider naming convention: https://doc.traefik.io/traefik/providers/overview/#provider-namespace - namespace-name1@kubernetescrd - namespace-name2@kubernetescrd | +| ports.websecure.nodePort | string | `nil` | See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) | +| ports.websecure.port | int | `8443` | | +| ports.websecure.protocol | string | `"TCP"` | | +| ports.websecure.proxyProtocol.insecure | bool | `false` | | +| ports.websecure.proxyProtocol.trustedIPs | list | `[]` | Enable the Proxy Protocol header parsing for the entry point | +| ports.websecure.targetPort | string | `nil` | | +| ports.websecure.tls | object | `{"certResolver":"","domains":[],"enabled":true,"options":""}` | See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#tls) | +| ports.websecure.transport | object | `{"keepAliveMaxRequests":null,"keepAliveMaxTime":null,"lifeCycle":{"graceTimeOut":null,"requestAcceptGraceTimeout":null},"respondingTimeouts":{"idleTimeout":null,"readTimeout":null,"writeTimeout":null}}` | See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#transport) | +| priorityClassName | string | `""` | [Pod Priority and Preemption](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) | +| providers.file.content | string | `""` | File content (YAML format, go template supported) (see https://doc.traefik.io/traefik/providers/file/) | +| providers.file.enabled | bool | `false` | Create a file provider | +| providers.file.watch | bool | `true` | Allows Traefik to automatically watch for file changes | +| providers.kubernetesCRD.allowCrossNamespace | bool | `false` | Allows IngressRoute to reference resources in namespace other than theirs | +| providers.kubernetesCRD.allowEmptyServices | bool | `true` | Allows to return 503 when there is no endpoints available | +| providers.kubernetesCRD.allowExternalNameServices | bool | `false` | Allows to reference ExternalName services in IngressRoute | +| providers.kubernetesCRD.enabled | bool | `true` | Load Kubernetes IngressRoute provider | +| providers.kubernetesCRD.ingressClass | string | `""` | When the parameter is set, only resources containing an annotation with the same value are processed. Otherwise, resources missing the annotation, having an empty value, or the value traefik are processed. It will also set required annotation on Dashboard and Healthcheck IngressRoute when enabled. | +| providers.kubernetesCRD.namespaces | list | `[]` | Array of namespaces to watch. If left empty, Traefik watches all namespaces. | +| providers.kubernetesCRD.nativeLBByDefault | bool | `false` | Defines whether to use Native Kubernetes load-balancing mode by default. | +| providers.kubernetesGateway.enabled | bool | `false` | Enable Traefik Gateway provider for Gateway API | +| providers.kubernetesGateway.experimentalChannel | bool | `false` | Toggles support for the Experimental Channel resources (Gateway API release channels documentation). This option currently enables support for TCPRoute and TLSRoute. | +| providers.kubernetesGateway.labelselector | string | `""` | A label selector can be defined to filter on specific GatewayClass objects only. | +| providers.kubernetesGateway.namespaces | list | `[]` | Array of namespaces to watch. If left empty, Traefik watches all namespaces. | +| providers.kubernetesGateway.statusAddress.hostname | string | `""` | This Hostname will get copied to the Gateway status.addresses. | +| providers.kubernetesGateway.statusAddress.ip | string | `""` | This IP will get copied to the Gateway status.addresses, and currently only supports one IP value (IPv4 or IPv6). | +| providers.kubernetesGateway.statusAddress.service | object | `{"name":"{{ (include \"traefik.fullname\" .) }}","namespace":"{{ .Release.Namespace }}"}` | The Kubernetes service to copy status addresses from. When using third parties tools like External-DNS, this option can be used to copy the service loadbalancer.status (containing the service's endpoints IPs) to the gateways. Default to Service of this Chart. | +| providers.kubernetesIngress.allowEmptyServices | bool | `true` | Allows to return 503 when there is no endpoints available | +| providers.kubernetesIngress.allowExternalNameServices | bool | `false` | Allows to reference ExternalName services in Ingress | +| providers.kubernetesIngress.enabled | bool | `true` | Load Kubernetes Ingress provider | +| providers.kubernetesIngress.ingressClass | string | `nil` | When ingressClass is set, only Ingresses containing an annotation with the same value are processed. Otherwise, Ingresses missing the annotation, having an empty value, or the value traefik are processed. | +| providers.kubernetesIngress.namespaces | list | `[]` | Array of namespaces to watch. If left empty, Traefik watches all namespaces. | +| providers.kubernetesIngress.nativeLBByDefault | bool | `false` | Defines whether to use Native Kubernetes load-balancing mode by default. | +| providers.kubernetesIngress.publishedService.enabled | bool | `true` | Enable [publishedService](https://doc.traefik.io/traefik/providers/kubernetes-ingress/#publishedservice) | +| providers.kubernetesIngress.publishedService.pathOverride | string | `""` | Override path of Kubernetes Service used to copy status from. Format: namespace/servicename. Default to Service deployed with this Chart. | +| rbac | object | `{"aggregateTo":[],"enabled":true,"namespaced":false,"secretResourceNames":[]}` | Whether Role Based Access Control objects like roles and rolebindings should be created | +| readinessProbe.failureThreshold | int | `1` | The number of consecutive failures allowed before considering the probe as failed. | +| readinessProbe.initialDelaySeconds | int | `2` | The number of seconds to wait before starting the first probe. | +| readinessProbe.periodSeconds | int | `10` | The number of seconds to wait between consecutive probes. | +| readinessProbe.successThreshold | int | `1` | The minimum consecutive successes required to consider the probe successful. | +| readinessProbe.timeoutSeconds | int | `2` | The number of seconds to wait for a probe response before considering it as failed. | +| resources | object | `{}` | [Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for `traefik` container. | +| securityContext | object | See _values.yaml_ | [SecurityContext](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1) | +| service.additionalServices | object | `{}` | | +| service.annotations | object | `{}` | Additional annotations applied to both TCP and UDP services (e.g. for cloud provider specific config) | +| service.annotationsTCP | object | `{}` | Additional annotations for TCP service only | +| service.annotationsUDP | object | `{}` | Additional annotations for UDP service only | +| service.enabled | bool | `true` | | +| service.externalIPs | list | `[]` | | +| service.labels | object | `{}` | Additional service labels (e.g. for filtering Service by custom labels) | +| service.loadBalancerSourceRanges | list | `[]` | | +| service.single | bool | `true` | | +| service.spec | object | `{}` | Cannot contain type, selector or ports entries. | +| service.type | string | `"LoadBalancer"` | | +| serviceAccount | object | `{"name":""}` | The service account the pods will use to interact with the Kubernetes API | +| serviceAccountAnnotations | object | `{}` | Additional serviceAccount annotations (e.g. for oidc authentication) | +| startupProbe | object | `{}` | Define [Startup Probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes) | +| tlsOptions | object | `{}` | TLS Options are created as [TLSOption CRDs](https://doc.traefik.io/traefik/https/tls/#tls-options) When using `labelSelector`, you'll need to set labels on tlsOption accordingly. See EXAMPLE.md for details. | +| tlsStore | object | `{}` | TLS Store are created as [TLSStore CRDs](https://doc.traefik.io/traefik/https/tls/#default-certificate). This is useful if you want to set a default certificate. See EXAMPLE.md for details. | +| tolerations | list | `[]` | Tolerations allow the scheduler to schedule pods with matching taints. | +| topologySpreadConstraints | list | `[]` | You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains. | +| tracing | object | `{"addInternals":false,"otlp":{"enabled":false,"grpc":{"enabled":false,"endpoint":"","insecure":false,"tls":{"ca":"","cert":"","insecureSkipVerify":false,"key":""}},"http":{"enabled":false,"endpoint":"","headers":{},"tls":{"ca":"","cert":"","insecureSkipVerify":false,"key":""}}}}` | https://doc.traefik.io/traefik/observability/tracing/overview/ | +| tracing.addInternals | bool | `false` | Enables tracing for internal resources. Default: false. | +| tracing.otlp.enabled | bool | `false` | See https://doc.traefik.io/traefik/v3.0/observability/tracing/opentelemetry/ | +| tracing.otlp.grpc.enabled | bool | `false` | Set to true in order to send metrics to the OpenTelemetry Collector using gRPC | +| tracing.otlp.grpc.endpoint | string | `""` | Format: ://:. Default: http://localhost:4318/v1/metrics | +| tracing.otlp.grpc.insecure | bool | `false` | Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. | +| tracing.otlp.grpc.tls.ca | string | `""` | The path to the certificate authority, it defaults to the system bundle. | +| tracing.otlp.grpc.tls.cert | string | `""` | The path to the public certificate. When using this option, setting the key option is required. | +| tracing.otlp.grpc.tls.insecureSkipVerify | bool | `false` | When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. | +| tracing.otlp.grpc.tls.key | string | `""` | The path to the private key. When using this option, setting the cert option is required. | +| tracing.otlp.http.enabled | bool | `false` | Set to true in order to send metrics to the OpenTelemetry Collector using HTTP. | +| tracing.otlp.http.endpoint | string | `""` | Format: ://:. Default: http://localhost:4318/v1/metrics | +| tracing.otlp.http.headers | object | `{}` | Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. | +| tracing.otlp.http.tls.ca | string | `""` | The path to the certificate authority, it defaults to the system bundle. | +| tracing.otlp.http.tls.cert | string | `""` | The path to the public certificate. When using this option, setting the key option is required. | +| tracing.otlp.http.tls.insecureSkipVerify | bool | `false` | When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. | +| tracing.otlp.http.tls.key | string | `""` | The path to the private key. When using this option, setting the cert option is required. | +| updateStrategy.rollingUpdate.maxSurge | int | `1` | | +| updateStrategy.rollingUpdate.maxUnavailable | int | `0` | | +| updateStrategy.type | string | `"RollingUpdate"` | Customize updateStrategy of Deployment or DaemonSet | +| volumes | list | `[]` | Add volumes to the traefik pod. The volume name will be passed to tpl. This can be used to mount a cert pair or a configmap that holds a config.toml file. After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg: `additionalArguments: - "--providers.file.filename=/config/dynamic.toml" - "--ping" - "--ping.entrypoint=web"` | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/utils/assets/charts/traefik/crds/gateway-standard-install-v1.2.0.yaml b/utils/assets/charts/traefik/crds/gateway-standard-install-v1.2.0.yaml new file mode 100644 index 0000000..0efb1ac --- /dev/null +++ b/utils/assets/charts/traefik/crds/gateway-standard-install-v1.2.0.yaml @@ -0,0 +1,10345 @@ +# Copyright 2024 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Gateway API Standard channel install +# +--- +# +# config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: gatewayclasses.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GatewayClass + listKind: GatewayClassList + plural: gatewayclasses + shortNames: + - gc + singular: gatewayclass + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1 + schema: + openAPIV3Schema: + description: |- + GatewayClass describes a class of Gateways available to the user for creating + Gateway resources. + + It is recommended that this resource be used as a template for Gateways. This + means that a Gateway is based on the state of the GatewayClass at the time it + was created and changes to the GatewayClass or associated parameters are not + propagated down to existing Gateways. This recommendation is intended to + limit the blast radius of changes to GatewayClass or associated parameters. + If implementations choose to propagate GatewayClass changes to existing + Gateways, that MUST be clearly documented by the implementation. + + Whenever one or more Gateways are using a GatewayClass, implementations SHOULD + add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the + associated GatewayClass. This ensures that a GatewayClass associated with a + Gateway is not deleted while in use. + + GatewayClass is a Cluster level resource. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: |- + ControllerName is the name of the controller that is managing Gateways of + this class. The value of this field MUST be a domain prefixed path. + + Example: "example.net/gateway-controller". + + This field is not mutable and cannot be empty. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the GatewayClass. This is optional if the + controller does not require any additional configuration. + + ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, + or an implementation-specific custom resource. The resource can be + cluster-scoped or namespace-scoped. + + If the referent cannot be found, refers to an unsupported kind, or when + the data within that resource is malformed, the GatewayClass SHOULD be + rejected with the "Accepted" status condition set to "False" and an + "InvalidParameters" reason. + + A Gateway for this GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. + This field is required when referring to a Namespace-scoped resource and + MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Status defines the current state of GatewayClass. + + Implementations MUST populate status on all GatewayClass resources which + specify their controller name. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Conditions is the current status from the controller for + this GatewayClass. + + Controllers should prefer to publish conditions using values + of GatewayClassConditionType for the type of each Condition. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + GatewayClass describes a class of Gateways available to the user for creating + Gateway resources. + + It is recommended that this resource be used as a template for Gateways. This + means that a Gateway is based on the state of the GatewayClass at the time it + was created and changes to the GatewayClass or associated parameters are not + propagated down to existing Gateways. This recommendation is intended to + limit the blast radius of changes to GatewayClass or associated parameters. + If implementations choose to propagate GatewayClass changes to existing + Gateways, that MUST be clearly documented by the implementation. + + Whenever one or more Gateways are using a GatewayClass, implementations SHOULD + add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the + associated GatewayClass. This ensures that a GatewayClass associated with a + Gateway is not deleted while in use. + + GatewayClass is a Cluster level resource. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: |- + ControllerName is the name of the controller that is managing Gateways of + this class. The value of this field MUST be a domain prefixed path. + + Example: "example.net/gateway-controller". + + This field is not mutable and cannot be empty. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the GatewayClass. This is optional if the + controller does not require any additional configuration. + + ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, + or an implementation-specific custom resource. The resource can be + cluster-scoped or namespace-scoped. + + If the referent cannot be found, refers to an unsupported kind, or when + the data within that resource is malformed, the GatewayClass SHOULD be + rejected with the "Accepted" status condition set to "False" and an + "InvalidParameters" reason. + + A Gateway for this GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. + This field is required when referring to a Namespace-scoped resource and + MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Status defines the current state of GatewayClass. + + Implementations MUST populate status on all GatewayClass resources which + specify their controller name. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Conditions is the current status from the controller for + this GatewayClass. + + Controllers should prefer to publish conditions using values + of GatewayClassConditionType for the type of each Condition. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_gateways.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: gateways.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: Gateway + listKind: GatewayList + plural: gateways + shortNames: + - gtw + singular: gateway + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + Gateway represents an instance of a service-traffic handling infrastructure + by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: |+ + Addresses requested for this Gateway. This is optional and behavior can + depend on the implementation. If a value is set in the spec and the + requested address is invalid or unavailable, the implementation MUST + indicate this in the associated entry in GatewayStatus.Addresses. + + The Addresses field represents a request for the address(es) on the + "outside of the Gateway", that traffic bound for this Gateway will use. + This could be the IP address or hostname of an external load balancer or + other networking infrastructure, or some other address that traffic will + be sent to. + + If no Addresses are specified, the implementation MAY schedule the + Gateway in an implementation-specific manner, assigning an appropriate + set of Addresses. + + The implementation MUST bind all Listeners to every GatewayAddress that + it assigns to the Gateway and add a corresponding entry in + GatewayStatus.Addresses. + + Support: Extended + + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + gatewayClassName: + description: |- + GatewayClassName used for this Gateway. This is the name of a + GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + infrastructure: + description: |- + Infrastructure defines infrastructure level attributes about this Gateway instance. + + Support: Extended + properties: + annotations: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Annotations that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. + For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. + + An implementation may chose to add additional implementation-specific annotations as they see fit. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Annotation keys must be in the form of an optional + DNS subdomain prefix followed by a required name segment of + up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the annotation key's prefix must be a + DNS subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + labels: + additionalProperties: + description: |- + LabelValue is the value of a label in the Gateway API. This is used for validation + of maps such as Gateway infrastructure labels. This matches the Kubernetes + label validation rules: + * must be 63 characters or less (can be empty), + * unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), + * could contain dashes (-), underscores (_), dots (.), and alphanumerics between. + + Valid values include: + + * MyValue + * my.name + * 123-my-value + maxLength: 63 + minLength: 0 + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + description: |- + Labels that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. + For other implementations, this refers to any relevant (implementation specific) "labels" concepts. + + An implementation may chose to add additional implementation-specific labels as they see fit. + + If an implementation maps these labels to Pods, or any other resource that would need to be recreated when labels + change, it SHOULD clearly warn about this behavior in documentation. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Label keys must be in the form of an optional DNS subdomain + prefix followed by a required name segment of up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the label key's prefix must be a DNS + subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the Gateway. This is optional if the + controller does not require any additional configuration. + + This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis + + The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + type: object + listeners: + description: |- + Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. + At least one Listener MUST be specified. + + Each Listener in a set of Listeners (for example, in a single Gateway) + MUST be _distinct_, in that a traffic flow MUST be able to be assigned to + exactly one listener. (This section uses "set of Listeners" rather than + "Listeners in a single Gateway" because implementations MAY merge configuration + from multiple Gateways onto a single data plane, and these rules _also_ + apply in that case). + + Practically, this means that each listener in a set MUST have a unique + combination of Port, Protocol, and, if supported by the protocol, Hostname. + + Some combinations of port, protocol, and TLS settings are considered + Core support and MUST be supported by implementations based on their + targeted conformance profile: + + HTTP Profile + + 1. HTTPRoute, Port: 80, Protocol: HTTP + 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided + + TLS Profile + + 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough + + "Distinct" Listeners have the following property: + + The implementation can match inbound requests to a single distinct + Listener. When multiple Listeners share values for fields (for + example, two Listeners with the same Port value), the implementation + can match requests to only one of the Listeners using other + Listener fields. + + For example, the following Listener scenarios are distinct: + + 1. Multiple Listeners with the same Port that all use the "HTTP" + Protocol that all have unique Hostname values. + 2. Multiple Listeners with the same Port that use either the "HTTPS" or + "TLS" Protocol that all have unique Hostname values. + 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener + with the same Protocol has the same Port value. + + Some fields in the Listener struct have possible values that affect + whether the Listener is distinct. Hostname is particularly relevant + for HTTP or HTTPS protocols. + + When using the Hostname value to select between same-Port, same-Protocol + Listeners, the Hostname value must be different on each Listener for the + Listener to be distinct. + + When the Listeners are distinct based on Hostname, inbound request + hostnames MUST match from the most specific to least specific Hostname + values to choose the correct Listener and its associated set of Routes. + + Exact matches must be processed before wildcard matches, and wildcard + matches must be processed before fallback (empty Hostname value) + matches. For example, `"foo.example.com"` takes precedence over + `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. + + Additionally, if there are multiple wildcard entries, more specific + wildcard entries must be processed before less specific wildcard entries. + For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. + The precise definition here is that the higher the number of dots in the + hostname to the right of the wildcard character, the higher the precedence. + + The wildcard character will match any number of characters _and dots_ to + the left, however, so `"*.example.com"` will match both + `"foo.bar.example.com"` _and_ `"bar.example.com"`. + + If a set of Listeners contains Listeners that are not distinct, then those + Listeners are Conflicted, and the implementation MUST set the "Conflicted" + condition in the Listener Status to "True". + + Implementations MAY choose to accept a Gateway with some Conflicted + Listeners only if they only accept the partial Listener set that contains + no Conflicted Listeners. To put this another way, implementations may + accept a partial Listener set only if they throw out *all* the conflicting + Listeners. No picking one of the conflicting listeners as the winner. + This also means that the Gateway must have at least one non-conflicting + Listener in this case, otherwise it violates the requirement that at + least one Listener must be present. + + The implementation MUST set a "ListenersNotValid" condition on the + Gateway Status when the Gateway contains Conflicted Listeners whether or + not they accept the Gateway. That Condition SHOULD clearly + indicate in the Message which Listeners are conflicted, and which are + Accepted. Additionally, the Listener status for those listeners SHOULD + indicate which Listeners are conflicted and not Accepted. + + A Gateway's Listeners are considered "compatible" if: + + 1. They are distinct. + 2. The implementation can serve them in compliance with the Addresses + requirement that all Listeners are available on all assigned + addresses. + + Compatible combinations in Extended support are expected to vary across + implementations. A combination that is compatible for one implementation + may not be compatible for another. + + For example, an implementation that cannot serve both TCP and UDP listeners + on the same address, or cannot mix HTTPS and generic TLS listens on the same port + would not consider those cases compatible, even though they are distinct. + + Note that requests SHOULD match at most one Listener. For example, if + Listeners are defined for "foo.example.com" and "*.example.com", a + request to "foo.example.com" SHOULD only be routed using routes attached + to the "foo.example.com" Listener (and not the "*.example.com" Listener). + This concept is known as "Listener Isolation". Implementations that do + not support Listener Isolation MUST clearly document this. + + Implementations MAY merge separate Gateways onto a single set of + Addresses if all Listeners across all Gateways are compatible. + + Support: Core + items: + description: |- + Listener embodies the concept of a logical endpoint where a Gateway accepts + network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: |- + AllowedRoutes defines the types of routes that MAY be attached to a + Listener and the trusted namespaces where those Route resources MAY be + present. + + Although a client request may match multiple route rules, only one rule + may ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: + + * The most specific match as defined by the Route type. + * The oldest Route based on creation timestamp. For example, a Route with + a creation timestamp of "2020-09-08 01:02:03" is given precedence over + a Route with a creation timestamp of "2020-09-08 01:02:04". + * If everything else is equivalent, the Route appearing first in + alphabetical order (namespace/name) should be given precedence. For + example, foo/bar is given precedence over foo/baz. + + All valid rules within a Route attached to this Listener should be + implemented. Invalid Route rules can be ignored (sometimes that will mean + the full Route). If a Route rule transitions from valid to invalid, + support for that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, the rest + of the rules within that Route should still be supported. + + Support: Core + properties: + kinds: + description: |- + Kinds specifies the groups and kinds of Routes that are allowed to bind + to this Gateway Listener. When unspecified or empty, the kinds of Routes + selected are determined using the Listener protocol. + + A RouteGroupKind MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's Protocol field. + If an implementation does not support or recognize this resource type, it + MUST set the "ResolvedRefs" condition to False for this Listener with the + "InvalidRouteKinds" reason. + + Support: Core + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: |- + Namespaces indicates namespaces from which Routes may be attached to this + Listener. This is restricted to the namespace of this Gateway by default. + + Support: Core + properties: + from: + default: Same + description: |- + From indicates where Routes will be selected for this Gateway. Possible + values are: + + * All: Routes in all namespaces may be used by this Gateway. + * Selector: Routes in namespaces selected by the selector may be used by + this Gateway. + * Same: Only Routes in the same namespace may be used by this Gateway. + + Support: Core + enum: + - All + - Selector + - Same + type: string + selector: + description: |- + Selector must be specified when From is set to "Selector". In that case, + only Routes in Namespaces matching this Selector will be selected by this + Gateway. This field is ignored for other values of "From". + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: object + hostname: + description: |- + Hostname specifies the virtual hostname to match for protocol types that + define this concept. When unspecified, all hostnames are matched. This + field is ignored for protocols that don't require hostname based + matching. + + Implementations MUST apply Hostname matching appropriately for each of + the following protocols: + + * TLS: The Listener Hostname MUST match the SNI. + * HTTP: The Listener Hostname MUST match the Host header of the request. + * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + protocol layers as described above. If an implementation does not + ensure that both the SNI and Host header match the Listener hostname, + it MUST clearly document that. + + For HTTPRoute and TLSRoute resources, there is an interaction with the + `spec.hostnames` array. When both listener and route specify hostnames, + there MUST be an intersection between the values for a Route to be + accepted. For more information, refer to the Route specific Hostnames + documentation. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: |- + Name is the name of the Listener. This name MUST be unique within a + Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: |- + Port is the network port. Multiple listeners may use the + same port, subject to the Listener compatibility rules. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: |- + Protocol specifies the network protocol this listener expects to receive. + + Support: Core + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: |- + TLS is the TLS configuration for the Listener. This field is required if + the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + if the Protocol field is "HTTP", "TCP", or "UDP". + + The association of SNIs to Certificate defined in GatewayTLSConfig is + defined based on the Hostname field for this listener. + + The GatewayClass MUST use the longest matching SNI out of all + available certificates for any TLS handshake. + + Support: Core + properties: + certificateRefs: + description: |- + CertificateRefs contains a series of references to Kubernetes objects that + contains TLS certificates and private keys. These certificates are used to + establish a TLS handshake for requests that match the hostname of the + associated listener. + + A single CertificateRef to a Kubernetes Secret has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a Listener, but this behavior is implementation-specific. + + References to a resource in different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + + This field is required to have at least one element when the mode is set + to "Terminate" (default) and is optional otherwise. + + CertificateRefs can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. + + Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + + Support: Implementation-specific (More than one reference or other resource types) + items: + description: |- + SecretObjectReference identifies an API object including its namespace, + defaulting to Secret. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: |- + Mode defines the TLS behavior for the TLS session initiated by the client. + There are two possible modes: + + - Terminate: The TLS session between the downstream client and the + Gateway is terminated at the Gateway. This mode requires certificates + to be specified in some way, such as populating the certificateRefs + field. + - Passthrough: The TLS session is NOT terminated by the Gateway. This + implies that the Gateway can't decipher the TLS stream except for + the ClientHello message of the TLS protocol. The certificateRefs field + is ignored in this mode. + + Support: Core + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Options are a list of key/value pairs to enable extended TLS + configuration for each implementation. For example, configuring the + minimum TLS version or supported cipher suites. + + A set of common keys MAY be defined by the API in the future. To avoid + any ambiguity, implementation-specific definitions MUST use + domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by Gateway API. + + Support: Implementation-specific + maxProperties: 16 + type: object + type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must not be specified for protocols ['HTTP', 'TCP', + 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? + !has(l.tls) : true)' + - message: tls mode must be Terminate for protocol HTTPS + rule: 'self.all(l, (l.protocol == ''HTTPS'' && has(l.tls)) ? (l.tls.mode + == '''' || l.tls.mode == ''Terminate'') : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) + || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique + for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol + == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname + == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: Status defines the current state of Gateway. + properties: + addresses: + description: |+ + Addresses lists the network addresses that have been bound to the + Gateway. + + This list may differ from the addresses provided in the spec under some + conditions: + + * no addresses are specified, all addresses are dynamically assigned + * a combination of specified and dynamic addresses are assigned + * a specified address was unusable (e.g. already in use) + + items: + description: GatewayStatusAddress describes a network address that + is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: |- + Conditions describe the current conditions of the Gateway. + + Implementations should prefer to express Gateway conditions + using the `GatewayConditionType` and `GatewayConditionReason` + constants so that operators and tools can converge on a common + vocabulary to describe Gateway state. + + Known condition types are: + + * "Accepted" + * "Programmed" + * "Ready" + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: |- + AttachedRoutes represents the total number of Routes that have been + successfully attached to this Listener. + + Successful attachment of a Route to a Listener is based solely on the + combination of the AllowedRoutes field on the corresponding Listener + and the Route's ParentRefs field. A Route is successfully attached to + a Listener when it is selected by the Listener's AllowedRoutes field + AND the Route has a valid ParentRef selecting the whole Gateway + resource or a specific Listener as a parent resource (more detail on + attachment semantics can be found in the documentation on the various + Route kinds ParentRefs fields). Listener or Route status does not impact + successful attachment, i.e. the AttachedRoutes field count MUST be set + for Listeners with condition Accepted: false and MUST count successfully + attached Routes that may themselves have Accepted: false conditions. + + Uses for this field include troubleshooting Route attachment and + measuring blast radius/impact of changes to a Listener. + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: |- + SupportedKinds is the list indicating the Kinds supported by this + listener. This MUST represent the kinds an implementation supports for + that Listener configuration. + + If kinds are specified in Spec that are not supported, they MUST NOT + appear in this list and an implementation MUST set the "ResolvedRefs" + condition to "False" with the "InvalidRouteKinds" reason. If both valid + and invalid Route kinds are specified, the implementation MUST + reference the valid Route kinds that have been specified. + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + Gateway represents an instance of a service-traffic handling infrastructure + by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: |+ + Addresses requested for this Gateway. This is optional and behavior can + depend on the implementation. If a value is set in the spec and the + requested address is invalid or unavailable, the implementation MUST + indicate this in the associated entry in GatewayStatus.Addresses. + + The Addresses field represents a request for the address(es) on the + "outside of the Gateway", that traffic bound for this Gateway will use. + This could be the IP address or hostname of an external load balancer or + other networking infrastructure, or some other address that traffic will + be sent to. + + If no Addresses are specified, the implementation MAY schedule the + Gateway in an implementation-specific manner, assigning an appropriate + set of Addresses. + + The implementation MUST bind all Listeners to every GatewayAddress that + it assigns to the Gateway and add a corresponding entry in + GatewayStatus.Addresses. + + Support: Extended + + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + gatewayClassName: + description: |- + GatewayClassName used for this Gateway. This is the name of a + GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + infrastructure: + description: |- + Infrastructure defines infrastructure level attributes about this Gateway instance. + + Support: Extended + properties: + annotations: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Annotations that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. + For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. + + An implementation may chose to add additional implementation-specific annotations as they see fit. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Annotation keys must be in the form of an optional + DNS subdomain prefix followed by a required name segment of + up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the annotation key's prefix must be a + DNS subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + labels: + additionalProperties: + description: |- + LabelValue is the value of a label in the Gateway API. This is used for validation + of maps such as Gateway infrastructure labels. This matches the Kubernetes + label validation rules: + * must be 63 characters or less (can be empty), + * unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), + * could contain dashes (-), underscores (_), dots (.), and alphanumerics between. + + Valid values include: + + * MyValue + * my.name + * 123-my-value + maxLength: 63 + minLength: 0 + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + description: |- + Labels that SHOULD be applied to any resources created in response to this Gateway. + + For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. + For other implementations, this refers to any relevant (implementation specific) "labels" concepts. + + An implementation may chose to add additional implementation-specific labels as they see fit. + + If an implementation maps these labels to Pods, or any other resource that would need to be recreated when labels + change, it SHOULD clearly warn about this behavior in documentation. + + Support: Extended + maxProperties: 8 + type: object + x-kubernetes-validations: + - message: Label keys must be in the form of an optional DNS subdomain + prefix followed by a required name segment of up to 63 characters. + rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) + - message: If specified, the label key's prefix must be a DNS + subdomain not longer than 253 characters in total. + rule: self.all(key, key.split("/")[0].size() < 253) + parametersRef: + description: |- + ParametersRef is a reference to a resource that contains the configuration + parameters corresponding to the Gateway. This is optional if the + controller does not require any additional configuration. + + This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis + + The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified, + the merging behavior is implementation specific. + It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + type: object + listeners: + description: |- + Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. + At least one Listener MUST be specified. + + Each Listener in a set of Listeners (for example, in a single Gateway) + MUST be _distinct_, in that a traffic flow MUST be able to be assigned to + exactly one listener. (This section uses "set of Listeners" rather than + "Listeners in a single Gateway" because implementations MAY merge configuration + from multiple Gateways onto a single data plane, and these rules _also_ + apply in that case). + + Practically, this means that each listener in a set MUST have a unique + combination of Port, Protocol, and, if supported by the protocol, Hostname. + + Some combinations of port, protocol, and TLS settings are considered + Core support and MUST be supported by implementations based on their + targeted conformance profile: + + HTTP Profile + + 1. HTTPRoute, Port: 80, Protocol: HTTP + 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided + + TLS Profile + + 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough + + "Distinct" Listeners have the following property: + + The implementation can match inbound requests to a single distinct + Listener. When multiple Listeners share values for fields (for + example, two Listeners with the same Port value), the implementation + can match requests to only one of the Listeners using other + Listener fields. + + For example, the following Listener scenarios are distinct: + + 1. Multiple Listeners with the same Port that all use the "HTTP" + Protocol that all have unique Hostname values. + 2. Multiple Listeners with the same Port that use either the "HTTPS" or + "TLS" Protocol that all have unique Hostname values. + 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener + with the same Protocol has the same Port value. + + Some fields in the Listener struct have possible values that affect + whether the Listener is distinct. Hostname is particularly relevant + for HTTP or HTTPS protocols. + + When using the Hostname value to select between same-Port, same-Protocol + Listeners, the Hostname value must be different on each Listener for the + Listener to be distinct. + + When the Listeners are distinct based on Hostname, inbound request + hostnames MUST match from the most specific to least specific Hostname + values to choose the correct Listener and its associated set of Routes. + + Exact matches must be processed before wildcard matches, and wildcard + matches must be processed before fallback (empty Hostname value) + matches. For example, `"foo.example.com"` takes precedence over + `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. + + Additionally, if there are multiple wildcard entries, more specific + wildcard entries must be processed before less specific wildcard entries. + For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. + The precise definition here is that the higher the number of dots in the + hostname to the right of the wildcard character, the higher the precedence. + + The wildcard character will match any number of characters _and dots_ to + the left, however, so `"*.example.com"` will match both + `"foo.bar.example.com"` _and_ `"bar.example.com"`. + + If a set of Listeners contains Listeners that are not distinct, then those + Listeners are Conflicted, and the implementation MUST set the "Conflicted" + condition in the Listener Status to "True". + + Implementations MAY choose to accept a Gateway with some Conflicted + Listeners only if they only accept the partial Listener set that contains + no Conflicted Listeners. To put this another way, implementations may + accept a partial Listener set only if they throw out *all* the conflicting + Listeners. No picking one of the conflicting listeners as the winner. + This also means that the Gateway must have at least one non-conflicting + Listener in this case, otherwise it violates the requirement that at + least one Listener must be present. + + The implementation MUST set a "ListenersNotValid" condition on the + Gateway Status when the Gateway contains Conflicted Listeners whether or + not they accept the Gateway. That Condition SHOULD clearly + indicate in the Message which Listeners are conflicted, and which are + Accepted. Additionally, the Listener status for those listeners SHOULD + indicate which Listeners are conflicted and not Accepted. + + A Gateway's Listeners are considered "compatible" if: + + 1. They are distinct. + 2. The implementation can serve them in compliance with the Addresses + requirement that all Listeners are available on all assigned + addresses. + + Compatible combinations in Extended support are expected to vary across + implementations. A combination that is compatible for one implementation + may not be compatible for another. + + For example, an implementation that cannot serve both TCP and UDP listeners + on the same address, or cannot mix HTTPS and generic TLS listens on the same port + would not consider those cases compatible, even though they are distinct. + + Note that requests SHOULD match at most one Listener. For example, if + Listeners are defined for "foo.example.com" and "*.example.com", a + request to "foo.example.com" SHOULD only be routed using routes attached + to the "foo.example.com" Listener (and not the "*.example.com" Listener). + This concept is known as "Listener Isolation". Implementations that do + not support Listener Isolation MUST clearly document this. + + Implementations MAY merge separate Gateways onto a single set of + Addresses if all Listeners across all Gateways are compatible. + + Support: Core + items: + description: |- + Listener embodies the concept of a logical endpoint where a Gateway accepts + network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: |- + AllowedRoutes defines the types of routes that MAY be attached to a + Listener and the trusted namespaces where those Route resources MAY be + present. + + Although a client request may match multiple route rules, only one rule + may ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: + + * The most specific match as defined by the Route type. + * The oldest Route based on creation timestamp. For example, a Route with + a creation timestamp of "2020-09-08 01:02:03" is given precedence over + a Route with a creation timestamp of "2020-09-08 01:02:04". + * If everything else is equivalent, the Route appearing first in + alphabetical order (namespace/name) should be given precedence. For + example, foo/bar is given precedence over foo/baz. + + All valid rules within a Route attached to this Listener should be + implemented. Invalid Route rules can be ignored (sometimes that will mean + the full Route). If a Route rule transitions from valid to invalid, + support for that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, the rest + of the rules within that Route should still be supported. + + Support: Core + properties: + kinds: + description: |- + Kinds specifies the groups and kinds of Routes that are allowed to bind + to this Gateway Listener. When unspecified or empty, the kinds of Routes + selected are determined using the Listener protocol. + + A RouteGroupKind MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's Protocol field. + If an implementation does not support or recognize this resource type, it + MUST set the "ResolvedRefs" condition to False for this Listener with the + "InvalidRouteKinds" reason. + + Support: Core + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: |- + Namespaces indicates namespaces from which Routes may be attached to this + Listener. This is restricted to the namespace of this Gateway by default. + + Support: Core + properties: + from: + default: Same + description: |- + From indicates where Routes will be selected for this Gateway. Possible + values are: + + * All: Routes in all namespaces may be used by this Gateway. + * Selector: Routes in namespaces selected by the selector may be used by + this Gateway. + * Same: Only Routes in the same namespace may be used by this Gateway. + + Support: Core + enum: + - All + - Selector + - Same + type: string + selector: + description: |- + Selector must be specified when From is set to "Selector". In that case, + only Routes in Namespaces matching this Selector will be selected by this + Gateway. This field is ignored for other values of "From". + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: object + hostname: + description: |- + Hostname specifies the virtual hostname to match for protocol types that + define this concept. When unspecified, all hostnames are matched. This + field is ignored for protocols that don't require hostname based + matching. + + Implementations MUST apply Hostname matching appropriately for each of + the following protocols: + + * TLS: The Listener Hostname MUST match the SNI. + * HTTP: The Listener Hostname MUST match the Host header of the request. + * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + protocol layers as described above. If an implementation does not + ensure that both the SNI and Host header match the Listener hostname, + it MUST clearly document that. + + For HTTPRoute and TLSRoute resources, there is an interaction with the + `spec.hostnames` array. When both listener and route specify hostnames, + there MUST be an intersection between the values for a Route to be + accepted. For more information, refer to the Route specific Hostnames + documentation. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: |- + Name is the name of the Listener. This name MUST be unique within a + Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: |- + Port is the network port. Multiple listeners may use the + same port, subject to the Listener compatibility rules. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: |- + Protocol specifies the network protocol this listener expects to receive. + + Support: Core + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: |- + TLS is the TLS configuration for the Listener. This field is required if + the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + if the Protocol field is "HTTP", "TCP", or "UDP". + + The association of SNIs to Certificate defined in GatewayTLSConfig is + defined based on the Hostname field for this listener. + + The GatewayClass MUST use the longest matching SNI out of all + available certificates for any TLS handshake. + + Support: Core + properties: + certificateRefs: + description: |- + CertificateRefs contains a series of references to Kubernetes objects that + contains TLS certificates and private keys. These certificates are used to + establish a TLS handshake for requests that match the hostname of the + associated listener. + + A single CertificateRef to a Kubernetes Secret has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a Listener, but this behavior is implementation-specific. + + References to a resource in different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + + This field is required to have at least one element when the mode is set + to "Terminate" (default) and is optional otherwise. + + CertificateRefs can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. + + Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + + Support: Implementation-specific (More than one reference or other resource types) + items: + description: |- + SecretObjectReference identifies an API object including its namespace, + defaulting to Secret. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: |- + Mode defines the TLS behavior for the TLS session initiated by the client. + There are two possible modes: + + - Terminate: The TLS session between the downstream client and the + Gateway is terminated at the Gateway. This mode requires certificates + to be specified in some way, such as populating the certificateRefs + field. + - Passthrough: The TLS session is NOT terminated by the Gateway. This + implies that the Gateway can't decipher the TLS stream except for + the ClientHello message of the TLS protocol. The certificateRefs field + is ignored in this mode. + + Support: Core + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Options are a list of key/value pairs to enable extended TLS + configuration for each implementation. For example, configuring the + minimum TLS version or supported cipher suites. + + A set of common keys MAY be defined by the API in the future. To avoid + any ambiguity, implementation-specific definitions MUST use + domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by Gateway API. + + Support: Implementation-specific + maxProperties: 16 + type: object + type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must not be specified for protocols ['HTTP', 'TCP', + 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? + !has(l.tls) : true)' + - message: tls mode must be Terminate for protocol HTTPS + rule: 'self.all(l, (l.protocol == ''HTTPS'' && has(l.tls)) ? (l.tls.mode + == '''' || l.tls.mode == ''Terminate'') : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) + || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique + for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol + == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname + == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: Status defines the current state of Gateway. + properties: + addresses: + description: |+ + Addresses lists the network addresses that have been bound to the + Gateway. + + This list may differ from the addresses provided in the spec under some + conditions: + + * no addresses are specified, all addresses are dynamically assigned + * a combination of specified and dynamic addresses are assigned + * a specified address was unusable (e.g. already in use) + + items: + description: GatewayStatusAddress describes a network address that + is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: |- + Value of the address. The validity of the values will depend + on the type and support by the controller. + + Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: |- + Conditions describe the current conditions of the Gateway. + + Implementations should prefer to express Gateway conditions + using the `GatewayConditionType` and `GatewayConditionReason` + constants so that operators and tools can converge on a common + vocabulary to describe Gateway state. + + Known condition types are: + + * "Accepted" + * "Programmed" + * "Ready" + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: |- + AttachedRoutes represents the total number of Routes that have been + successfully attached to this Listener. + + Successful attachment of a Route to a Listener is based solely on the + combination of the AllowedRoutes field on the corresponding Listener + and the Route's ParentRefs field. A Route is successfully attached to + a Listener when it is selected by the Listener's AllowedRoutes field + AND the Route has a valid ParentRef selecting the whole Gateway + resource or a specific Listener as a parent resource (more detail on + attachment semantics can be found in the documentation on the various + Route kinds ParentRefs fields). Listener or Route status does not impact + successful attachment, i.e. the AttachedRoutes field count MUST be set + for Listeners with condition Accepted: false and MUST count successfully + attached Routes that may themselves have Accepted: false conditions. + + Uses for this field include troubleshooting Route attachment and + measuring blast radius/impact of changes to a Listener. + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: |- + SupportedKinds is the list indicating the Kinds supported by this + listener. This MUST represent the kinds an implementation supports for + that Listener configuration. + + If kinds are specified in Spec that are not supported, they MUST NOT + appear in this list and an implementation MUST set the "ResolvedRefs" + condition to "False" with the "InvalidRouteKinds" reason. If both valid + and invalid Route kinds are specified, the implementation MUST + reference the valid Route kinds that have been specified. + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: grpcroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GRPCRoute + listKind: GRPCRouteList + plural: grpcroutes + singular: grpcroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + GRPCRoute provides a way to route gRPC requests. This includes the capability + to match requests by hostname, gRPC service, gRPC method, or HTTP/2 header. + Filters can be used to specify additional processing steps. Backends specify + where matching requests will be routed. + + GRPCRoute falls under extended support within the Gateway API. Within the + following specification, the word "MUST" indicates that an implementation + supporting GRPCRoute must conform to the indicated requirement, but an + implementation not supporting this route type need not follow the requirement + unless explicitly indicated. + + Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` MUST + accept HTTP/2 connections without an initial upgrade from HTTP/1.1, i.e. via + ALPN. If the implementation does not support this, then it MUST set the + "Accepted" condition to "False" for the affected listener with a reason of + "UnsupportedProtocol". Implementations MAY also accept HTTP/2 connections + with an upgrade from HTTP/1. + + Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` MUST + support HTTP/2 over cleartext TCP (h2c, + https://www.rfc-editor.org/rfc/rfc7540#section-3.1) without an initial + upgrade from HTTP/1.1, i.e. with prior knowledge + (https://www.rfc-editor.org/rfc/rfc7540#section-3.4). If the implementation + does not support this, then it MUST set the "Accepted" condition to "False" + for the affected listener with a reason of "UnsupportedProtocol". + Implementations MAY also accept HTTP/2 connections with an upgrade from + HTTP/1, i.e. without prior knowledge. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GRPCRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of hostnames to match against the GRPC + Host header to select a GRPCRoute to process the request. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label MUST appear by itself as the first label. + + If a hostname is specified by both the Listener and GRPCRoute, there + MUST be at least one intersecting hostname for the GRPCRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches GRPCRoutes + that have either not specified any hostnames, or have specified at + least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches GRPCRoutes + that have either not specified any hostnames or have specified at least + one hostname that matches the Listener hostname. For example, + `test.example.com` and `*.example.com` would both match. On the other + hand, `example.com` and `test.example.net` would not match. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + If both the Listener and GRPCRoute have specified hostnames, any + GRPCRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + GRPCRoute specified `test.example.com` and `test.example.net`, + `test.example.net` MUST NOT be considered for a match. + + If both the Listener and GRPCRoute have specified hostnames, and none + match with the criteria above, then the GRPCRoute MUST NOT be accepted by + the implementation. The implementation MUST raise an 'Accepted' Condition + with a status of `False` in the corresponding RouteParentStatus. + + If a Route (A) of type HTTPRoute or GRPCRoute is attached to a + Listener and that listener already has another Route (B) of the other + type attached and the intersection of the hostnames of A and B is + non-empty, then the implementation MUST accept exactly one of these two + routes, determined by the following criteria, in order: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + The rejected Route MUST raise an 'Accepted' condition with a status of + 'False' in the corresponding RouteParentStatus. + + Support: Core + items: + description: |- + Hostname is the fully qualified domain name of a network host. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + Hostname can be "precise" which is a domain name without the terminating + dot of a network host (e.g. "foo.example.com") or "wildcard", which is a + domain name prefixed with a single wildcard label (e.g. `*.example.com`). + + Note that as per RFC1035 and RFC1123, a *label* must consist of lower case + alphanumeric characters or '-', and must start and end with an alphanumeric + character. No other punctuation is allowed. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: |+ + ParentRefs references the resources (usually Gateways) that a Route wants + to be attached to. Note that the referenced parent resource needs to + allow this for the attachment to be complete. For Gateways, that means + the Gateway needs to allow attachment from Routes of this kind and + namespace. For Services, that means the Service must either be in the same + namespace for a "producer" route, or the mesh implementation must support + and allow "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not possible to + create a "producer" route for a Service in a different namespace from the + Route. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + ParentRefs must be _distinct_. This means either that: + + * They select different objects. If this is the case, then parentRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, `namespace`, and `name` must + be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field used, + each ParentRef that selects the same object must set the same set of + optional fields to different values. If one ParentRef sets a + combination of optional fields, all must set the same combination. + + Some examples: + + * If one ParentRef sets `sectionName`, all ParentRefs referencing the + same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. + * If one ParentRef sets `sectionName` and `port`, all ParentRefs + referencing the same object must also set `sectionName` and `port`. + + It is possible to separately reference multiple distinct objects that may + be collapsed by an implementation. For example, some implementations may + choose to merge compatible Gateway Listeners together. If that is the + case, the list of routes attached to those resources should also be + merged. + + Note that for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example, + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable other kinds of cross-namespace reference. + + + + + + + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''')) : true))' + - message: sectionName must be unique when parentRefs includes 2 or + more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + rules: + description: |+ + Rules are a list of GRPC matchers, filters and actions. + + items: + description: |- + GRPCRouteRule defines the semantics for matching a gRPC request based on + conditions (matches), processing it (filters), and forwarding the request to + an API object (backendRefs). + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. + + Failure behavior here depends on how many BackendRefs are specified and + how many are invalid. + + If *all* entries in BackendRefs are invalid, and there are also no filters + specified in this route rule, *all* traffic which matches this rule MUST + receive an `UNAVAILABLE` status. + + See the GRPCBackendRef definition for the rules about what makes a single + GRPCBackendRef invalid. + + When a GRPCBackendRef is invalid, `UNAVAILABLE` statuses MUST be returned for + requests that would have otherwise been routed to an invalid backend. If + multiple backends are specified, and some are invalid, the proportion of + requests that would otherwise have been routed to an invalid backend + MUST receive an `UNAVAILABLE` status. + + For example, if two backends are specified with equal weights, and one is + invalid, 50 percent of traffic MUST receive an `UNAVAILABLE` status. + Implementations may choose how that 50 percent is determined. + + Support: Core for Kubernetes Service + + Support: Implementation-specific for any other resource + + Support for weight: Core + items: + description: |- + GRPCBackendRef defines how a GRPCRoute forwards a gRPC request. + + Note that when a namespace different than the local namespace is specified, a + ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + + When the BackendRef points to a Kubernetes Service, implementations SHOULD + honor the appProtocol field if it is set for the target Service Port. + + Implementations supporting appProtocol SHOULD recognize the Kubernetes + Standard Application Protocols defined in KEP-3726. + + If a Service appProtocol isn't specified, an implementation MAY infer the + backend protocol through its own means. Implementations MAY infer the + protocol from the Route type referring to the backend Service. + + If a Route is not able to send traffic to the backend using the specified + protocol then the backend is considered invalid. Implementations MUST set the + "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + properties: + filters: + description: |- + Filters defined at this level MUST be executed if and only if the + request is being forwarded to the backend defined here. + + Support: Implementation-specific (For broader support of filters, use the + Filters field in GRPCRouteRule.) + items: + description: |- + GRPCRouteFilter defines processing steps that must be completed during the + request or response lifecycle. GRPCRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + Support: Implementation-specific + + This filter can be used multiple times within the same rule. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |+ + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations supporting GRPCRoute MUST support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` MUST be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + enum: + - ResponseHeaderModifier + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: |- + Weight specifies the proportion of requests forwarded to the referenced + backend. This is computed as weight/(sum of all weights in this + BackendRefs list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If only one backend is specified and it has a weight greater than 0, 100% + of the traffic is forwarded to that backend. If weight is set to 0, no + traffic should be forwarded for this entry. If unspecified, weight + defaults to 1. + + Support for this field varies based on the context where used. + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + Conformance-levels at this level are defined based on the type of filter: + + - ALL core filters MUST be supported by all implementations that support + GRPCRoute. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + If an implementation can not support a combination of filters, it must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + Support: Core + items: + description: |- + GRPCRouteFilter defines processing steps that must be completed during the + request or response lifecycle. GRPCRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + Support: Implementation-specific + + This filter can be used multiple times within the same rule. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |+ + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations supporting GRPCRoute MUST support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` MUST be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + enum: + - ResponseHeaderModifier + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + matches: + description: |- + Matches define conditions used for matching the rule against incoming + gRPC requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + For example, take the following matches configuration: + + ``` + matches: + - method: + service: foo.bar + headers: + values: + version: 2 + - method: + service: foo.bar.v2 + ``` + + For a request to match against this rule, it MUST satisfy + EITHER of the two conditions: + + - service of foo.bar AND contains the header `version: 2` + - service of foo.bar.v2 + + See the documentation for GRPCRouteMatch on how to specify multiple + match conditions to be ANDed together. + + If no matches are specified, the implementation MUST match every gRPC request. + + Proxy or Load Balancer routing configuration generated from GRPCRoutes + MUST prioritize rules based on the following criteria, continuing on + ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes. + Precedence MUST be given to the rule with the largest number of: + + * Characters in a matching non-wildcard hostname. + * Characters in a matching hostname. + * Characters in a matching service. + * Characters in a matching method. + * Header matches. + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + If ties still exist within the Route that has been given precedence, + matching precedence MUST be granted to the first matching rule meeting + the above criteria. + items: + description: |- + GRPCRouteMatch defines the predicate used to match requests to a given + action. Multiple match types are ANDed together, i.e. the match will + evaluate to true only if all conditions are satisfied. + + For example, the match below will match a gRPC request only if its service + is `foo` AND it contains the `version: v1` header: + + ``` + matches: + - method: + type: Exact + service: "foo" + headers: + - name: "version" + value "v1" + + ``` + properties: + headers: + description: |- + Headers specifies gRPC request header matchers. Multiple match values are + ANDed together, meaning, a request MUST match all the specified headers + to select the route. + items: + description: |- + GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request + headers. + properties: + name: + description: |- + Name is the name of the gRPC Header to be matched. + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: Type specifies how to match against + the value of the header. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of the gRPC Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: |- + Method specifies a gRPC request service/method matcher. If this field is + not specified, all services and methods will match. + properties: + method: + description: |- + Value of the method to match against. If left empty or omitted, will + match all services. + + At least one of Service and Method MUST be a non-empty string. + maxLength: 1024 + type: string + service: + description: |- + Value of the service to match against. If left empty or omitted, will + match any service. + + At least one of Service and Method MUST be a non-empty string. + maxLength: 1024 + type: string + type: + default: Exact + description: |- + Type specifies how to match against the service and/or method. + Support: Core (Exact with service and method specified) + + Support: Implementation-specific (Exact with method specified but no service specified) + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - RegularExpression + type: string + type: object + x-kubernetes-validations: + - message: One or both of 'service' or 'method' must be + specified + rule: 'has(self.type) ? has(self.service) || has(self.method) + : true' + - message: service must only contain valid characters + (matching ^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$) + rule: '(!has(self.type) || self.type == ''Exact'') && + has(self.service) ? self.service.matches(r"""^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$"""): + true' + - message: method must only contain valid characters (matching + ^[A-Za-z_][A-Za-z_0-9]*$) + rule: '(!has(self.type) || self.type == ''Exact'') && + has(self.method) ? self.method.matches(r"""^[A-Za-z_][A-Za-z_0-9]*$"""): + true' + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the + total number of matches across all rules in a route must be less + than 128 + rule: '(self.size() > 0 ? (has(self[0].matches) ? self[0].matches.size() + : 0) : 0) + (self.size() > 1 ? (has(self[1].matches) ? self[1].matches.size() + : 0) : 0) + (self.size() > 2 ? (has(self[2].matches) ? self[2].matches.size() + : 0) : 0) + (self.size() > 3 ? (has(self[3].matches) ? self[3].matches.size() + : 0) : 0) + (self.size() > 4 ? (has(self[4].matches) ? self[4].matches.size() + : 0) : 0) + (self.size() > 5 ? (has(self[5].matches) ? self[5].matches.size() + : 0) : 0) + (self.size() > 6 ? (has(self[6].matches) ? self[6].matches.size() + : 0) : 0) + (self.size() > 7 ? (has(self[7].matches) ? self[7].matches.size() + : 0) : 0) + (self.size() > 8 ? (has(self[8].matches) ? self[8].matches.size() + : 0) : 0) + (self.size() > 9 ? (has(self[9].matches) ? self[9].matches.size() + : 0) : 0) + (self.size() > 10 ? (has(self[10].matches) ? self[10].matches.size() + : 0) : 0) + (self.size() > 11 ? (has(self[11].matches) ? self[11].matches.size() + : 0) : 0) + (self.size() > 12 ? (has(self[12].matches) ? self[12].matches.size() + : 0) : 0) + (self.size() > 13 ? (has(self[13].matches) ? self[13].matches.size() + : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() + : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() + : 0) : 0) <= 128' + type: object + status: + description: Status defines the current state of GRPCRoute. + properties: + parents: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the route, and the status of the route with respect to + each parent. When this route attaches to a parent, the controller that + manages the parent must add an entry to this list when the controller + first sees the route and should update the entry as appropriate when the + route or gateway is modified. + + Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this API + can only populate Route status for the Gateways/parent resources they are + responsible for. + + A maximum of 32 Gateways will be represented in this list. An empty list + means the route has not been attached to any Gateway. + items: + description: |- + RouteParentStatus describes the status of a route with respect to an + associated Parent. + properties: + conditions: + description: |- + Conditions describes the status of the route with respect to the Gateway. + Note that the route's availability is also subject to the Gateway's own + status conditions and listener status. + + If the Route's ParentRef specifies an existing Gateway that supports + Routes of this kind AND that Gateway's controller has sufficient access, + then that Gateway's controller MUST set the "Accepted" condition on the + Route, to indicate whether the route has been accepted or rejected by the + Gateway, and why. + + A Route MUST be considered "Accepted" if at least one of the Route's + rules is implemented by the Gateway. + + There are a number of cases where the "Accepted" condition may not be set + due to lack of controller visibility, that includes when: + + * The Route refers to a non-existent parent. + * The Route is of a type that the controller does not support. + * The Route is in a namespace the controller does not have access to. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: |- + ParentRef corresponds with a ParentRef in the spec that this + RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: httproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: HTTPRoute + listKind: HTTPRouteList + plural: httproutes + singular: httproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + HTTPRoute provides a way to route HTTP requests. This includes the capability + to match requests by hostname, path, header, or query param. Filters can be + used to specify additional processing steps. Backends specify where matching + requests should be routed. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of hostnames that should match against the HTTP Host + header to select a HTTPRoute used to process the request. Implementations + MUST ignore any port value specified in the HTTP Host header while + performing a match and (absent of any applicable header modification + configuration) MUST forward this header unmodified to the backend. + + Valid values for Hostnames are determined by RFC 1123 definition of a + hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + If a hostname is specified by both the Listener and HTTPRoute, there + must be at least one intersecting hostname for the HTTPRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames, or have specified at + least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames or have specified at least + one hostname that matches the Listener hostname. For example, + `*.example.com`, `test.example.com`, and `foo.test.example.com` would + all match. On the other hand, `example.com` and `test.example.net` would + not match. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + If both the Listener and HTTPRoute have specified hostnames, any + HTTPRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. + + If both the Listener and HTTPRoute have specified hostnames, and none + match with the criteria above, then the HTTPRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status of + `False` in the corresponding RouteParentStatus. + + In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. + overlapping wildcard matching and exact matching hostnames), precedence must + be given to rules from the HTTPRoute with the largest number of: + + * Characters in a matching non-wildcard hostname. + * Characters in a matching hostname. + + If ties exist across multiple Routes, the matching precedence rules for + HTTPRouteMatches takes over. + + Support: Core + items: + description: |- + Hostname is the fully qualified domain name of a network host. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + Hostname can be "precise" which is a domain name without the terminating + dot of a network host (e.g. "foo.example.com") or "wildcard", which is a + domain name prefixed with a single wildcard label (e.g. `*.example.com`). + + Note that as per RFC1035 and RFC1123, a *label* must consist of lower case + alphanumeric characters or '-', and must start and end with an alphanumeric + character. No other punctuation is allowed. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: |+ + ParentRefs references the resources (usually Gateways) that a Route wants + to be attached to. Note that the referenced parent resource needs to + allow this for the attachment to be complete. For Gateways, that means + the Gateway needs to allow attachment from Routes of this kind and + namespace. For Services, that means the Service must either be in the same + namespace for a "producer" route, or the mesh implementation must support + and allow "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not possible to + create a "producer" route for a Service in a different namespace from the + Route. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + ParentRefs must be _distinct_. This means either that: + + * They select different objects. If this is the case, then parentRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, `namespace`, and `name` must + be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field used, + each ParentRef that selects the same object must set the same set of + optional fields to different values. If one ParentRef sets a + combination of optional fields, all must set the same combination. + + Some examples: + + * If one ParentRef sets `sectionName`, all ParentRefs referencing the + same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. + * If one ParentRef sets `sectionName` and `port`, all ParentRefs + referencing the same object must also set `sectionName` and `port`. + + It is possible to separately reference multiple distinct objects that may + be collapsed by an implementation. For example, some implementations may + choose to merge compatible Gateway Listeners together. If that is the + case, the list of routes attached to those resources should also be + merged. + + Note that for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example, + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable other kinds of cross-namespace reference. + + + + + + + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''')) : true))' + - message: sectionName must be unique when parentRefs includes 2 or + more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: |+ + Rules are a list of HTTP matchers, filters and actions. + + items: + description: |- + HTTPRouteRule defines semantics for matching an HTTP request based on + conditions (matches), processing it (filters), and forwarding the request to + an API object (backendRefs). + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. + + Failure behavior here depends on how many BackendRefs are specified and + how many are invalid. + + If *all* entries in BackendRefs are invalid, and there are also no filters + specified in this route rule, *all* traffic which matches this rule MUST + receive a 500 status code. + + See the HTTPBackendRef definition for the rules about what makes a single + HTTPBackendRef invalid. + + When a HTTPBackendRef is invalid, 500 status codes MUST be returned for + requests that would have otherwise been routed to an invalid backend. If + multiple backends are specified, and some are invalid, the proportion of + requests that would otherwise have been routed to an invalid backend + MUST receive a 500 status code. + + For example, if two backends are specified with equal weights, and one is + invalid, 50 percent of traffic must receive a 500. Implementations may + choose how that 50 percent is determined. + + When a HTTPBackendRef refers to a Service that has no ready endpoints, + implementations SHOULD return a 503 for requests to that backend instead. + If an implementation chooses to do this, all of the above rules for 500 responses + MUST also apply for responses that return a 503. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Core + items: + description: |- + HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. + + Note that when a namespace different than the local namespace is specified, a + ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + + When the BackendRef points to a Kubernetes Service, implementations SHOULD + honor the appProtocol field if it is set for the target Service Port. + + Implementations supporting appProtocol SHOULD recognize the Kubernetes + Standard Application Protocols defined in KEP-3726. + + If a Service appProtocol isn't specified, an implementation MAY infer the + backend protocol through its own means. Implementations MAY infer the + protocol from the Route type referring to the backend Service. + + If a Route is not able to send traffic to the backend using the specified + protocol then the backend is considered invalid. Implementations MUST set the + "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + properties: + filters: + description: |- + Filters defined at this level should be executed if and only if the + request is being forwarded to the backend defined here. + + Support: Implementation-specific (For broader support of filters, use the + Filters field in HTTPRouteRule.) + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the + filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != + ''RequestRedirect'')' + - message: filter.requestRedirect must be specified + for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == + ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() + <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() + <= 1 + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: |- + Weight specifies the proportion of requests forwarded to the referenced + backend. This is computed as weight/(sum of all weights in this + BackendRefs list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If only one backend is specified and it has a weight greater than 0, 100% + of the traffic is forwarded to that backend. If weight is set to 0, no + traffic should be forwarded for this entry. If unspecified, weight + defaults to 1. + + Support for this field varies based on the context where used. + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + Wherever possible, implementations SHOULD implement filters in the order + they are specified. + + Implementations MAY choose to implement this ordering strictly, rejecting + any combination or order of filters that can not be supported. If implementations + choose a strict interpretation of filter ordering, they MUST clearly document + that behavior. + + To reject an invalid combination or order of filters, implementations SHOULD + consider the Route Rules with this configuration invalid. If all Route Rules + in a Route are invalid, the entire Route would be considered invalid. If only + a portion of Route Rules are invalid, implementations MUST set the + "PartiallyInvalid" condition for the Route. + + Conformance-levels at this level are defined based on the type of filter: + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type + is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect + filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && + self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= + 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + For example, take the following matches configuration: + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + Note: The precedence of RegularExpression path matches are implementation-specific. + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given\naction. Multiple match types + are ANDed together, i.e. the match will\nevaluate to true + only if all conditions are satisfied.\n\nFor example, the + match below will match a HTTP request only if its path\nstarts + with `/foo` AND it contains the `version: v1` header:\n\n```\nmatch:\n\n\tpath:\n\t + \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t + \ value \"v1\"\n\n```" + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + Support: Core (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: |- + Method specifies HTTP method matcher. + When specified, this route will be matched only if the request has the + specified method. + + Support: Extended + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: |- + Path specifies a HTTP request path matcher. If this field is not + specified, a default prefix match on the "/" path is provided. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + Support: Core (Exact, PathPrefix) + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with + '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') + : true' + - message: must not contain '//' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') + : true' + - message: must not contain '/./' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') + : true' + - message: must not contain '/../' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') + : true' + - message: must not contain '%2f' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') + : true' + - message: must not contain '%2F' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') + : true' + - message: must not contain '#' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') + : true' + - message: must not end with '/..' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') + : true' + - message: must not end with '/.' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') + : true' + - message: type must be one of ['Exact', 'PathPrefix', + 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type + == 'RegularExpression' + - message: must only contain valid characters (matching + ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) + for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") + : true' + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + Support: Extended (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 64 + type: array + timeouts: + description: |- + Timeouts defines the timeouts that can be configured for an HTTP request. + + Support: Extended + properties: + backendRequest: + description: |- + BackendRequest specifies a timeout for an individual request from the gateway + to a backend. This covers the time from when the request first starts being + sent from the gateway to when the full response has been received from the backend. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + An entire client HTTP transaction with a gateway, covered by the Request timeout, + may result in more than one call from the gateway to the destination backend, + for example, if automatic retries are supported. + + The value of BackendRequest must be a Gateway API Duration string as defined by + GEP-2257. When this field is unspecified, its behavior is implementation-specific; + when specified, the value of BackendRequest must be no more than the value of the + Request timeout (since the Request timeout encompasses the BackendRequest timeout). + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + description: |- + Request specifies the maximum duration for a gateway to respond to an HTTP request. + If the gateway has not been able to respond before this deadline is met, the gateway + MUST return a timeout error. + + For example, setting the `rules.timeouts.request` field to the value `10s` in an + `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds + to complete. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + This timeout is intended to cover as close to the whole request-response transaction + as possible although an implementation MAY choose to start the timeout after the entire + request stream has been received instead of immediately after the transaction is + initiated by the client. + + The value of Request is a Gateway API Duration string as defined by GEP-2257. When this + field is unspecified, request timeout behavior is implementation-specific. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request + timeout + rule: '!(has(self.request) && has(self.backendRequest) && + duration(self.request) != duration(''0s'') && duration(self.backendRequest) + > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with + backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? + (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): + true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + ? ((size(self.matches) != 1 || !has(self.matches[0].path) || + self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter + with path.replacePrefixMatch, exactly one PathPrefix match must + be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) + || self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: Within backendRefs, When using URLRewrite filter with + path.replacePrefixMatch, exactly one PathPrefix match must be + specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the + total number of matches across all rules in a route must be less + than 128 + rule: '(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() + > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() + : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() + > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() + : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() + > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() + : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() + > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() + : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() + > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() + : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the route, and the status of the route with respect to + each parent. When this route attaches to a parent, the controller that + manages the parent must add an entry to this list when the controller + first sees the route and should update the entry as appropriate when the + route or gateway is modified. + + Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this API + can only populate Route status for the Gateways/parent resources they are + responsible for. + + A maximum of 32 Gateways will be represented in this list. An empty list + means the route has not been attached to any Gateway. + items: + description: |- + RouteParentStatus describes the status of a route with respect to an + associated Parent. + properties: + conditions: + description: |- + Conditions describes the status of the route with respect to the Gateway. + Note that the route's availability is also subject to the Gateway's own + status conditions and listener status. + + If the Route's ParentRef specifies an existing Gateway that supports + Routes of this kind AND that Gateway's controller has sufficient access, + then that Gateway's controller MUST set the "Accepted" condition on the + Route, to indicate whether the route has been accepted or rejected by the + Gateway, and why. + + A Route MUST be considered "Accepted" if at least one of the Route's + rules is implemented by the Gateway. + + There are a number of cases where the "Accepted" condition may not be set + due to lack of controller visibility, that includes when: + + * The Route refers to a non-existent parent. + * The Route is of a type that the controller does not support. + * The Route is in a namespace the controller does not have access to. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: |- + ParentRef corresponds with a ParentRef in the spec that this + RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + HTTPRoute provides a way to route HTTP requests. This includes the capability + to match requests by hostname, path, header, or query param. Filters can be + used to specify additional processing steps. Backends specify where matching + requests should be routed. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of hostnames that should match against the HTTP Host + header to select a HTTPRoute used to process the request. Implementations + MUST ignore any port value specified in the HTTP Host header while + performing a match and (absent of any applicable header modification + configuration) MUST forward this header unmodified to the backend. + + Valid values for Hostnames are determined by RFC 1123 definition of a + hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + If a hostname is specified by both the Listener and HTTPRoute, there + must be at least one intersecting hostname for the HTTPRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames, or have specified at + least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames or have specified at least + one hostname that matches the Listener hostname. For example, + `*.example.com`, `test.example.com`, and `foo.test.example.com` would + all match. On the other hand, `example.com` and `test.example.net` would + not match. + + Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` would match + both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + + If both the Listener and HTTPRoute have specified hostnames, any + HTTPRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. + + If both the Listener and HTTPRoute have specified hostnames, and none + match with the criteria above, then the HTTPRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status of + `False` in the corresponding RouteParentStatus. + + In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. + overlapping wildcard matching and exact matching hostnames), precedence must + be given to rules from the HTTPRoute with the largest number of: + + * Characters in a matching non-wildcard hostname. + * Characters in a matching hostname. + + If ties exist across multiple Routes, the matching precedence rules for + HTTPRouteMatches takes over. + + Support: Core + items: + description: |- + Hostname is the fully qualified domain name of a network host. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + Hostname can be "precise" which is a domain name without the terminating + dot of a network host (e.g. "foo.example.com") or "wildcard", which is a + domain name prefixed with a single wildcard label (e.g. `*.example.com`). + + Note that as per RFC1035 and RFC1123, a *label* must consist of lower case + alphanumeric characters or '-', and must start and end with an alphanumeric + character. No other punctuation is allowed. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: |+ + ParentRefs references the resources (usually Gateways) that a Route wants + to be attached to. Note that the referenced parent resource needs to + allow this for the attachment to be complete. For Gateways, that means + the Gateway needs to allow attachment from Routes of this kind and + namespace. For Services, that means the Service must either be in the same + namespace for a "producer" route, or the mesh implementation must support + and allow "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not possible to + create a "producer" route for a Service in a different namespace from the + Route. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + ParentRefs must be _distinct_. This means either that: + + * They select different objects. If this is the case, then parentRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, `namespace`, and `name` must + be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field used, + each ParentRef that selects the same object must set the same set of + optional fields to different values. If one ParentRef sets a + combination of optional fields, all must set the same combination. + + Some examples: + + * If one ParentRef sets `sectionName`, all ParentRefs referencing the + same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. + * If one ParentRef sets `sectionName` and `port`, all ParentRefs + referencing the same object must also set `sectionName` and `port`. + + It is possible to separately reference multiple distinct objects that may + be collapsed by an implementation. For example, some implementations may + choose to merge compatible Gateway Listeners together. If that is the + case, the list of routes attached to those resources should also be + merged. + + Note that for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example, + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable other kinds of cross-namespace reference. + + + + + + + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''')) : true))' + - message: sectionName must be unique when parentRefs includes 2 or + more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: |+ + Rules are a list of HTTP matchers, filters and actions. + + items: + description: |- + HTTPRouteRule defines semantics for matching an HTTP request based on + conditions (matches), processing it (filters), and forwarding the request to + an API object (backendRefs). + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. + + Failure behavior here depends on how many BackendRefs are specified and + how many are invalid. + + If *all* entries in BackendRefs are invalid, and there are also no filters + specified in this route rule, *all* traffic which matches this rule MUST + receive a 500 status code. + + See the HTTPBackendRef definition for the rules about what makes a single + HTTPBackendRef invalid. + + When a HTTPBackendRef is invalid, 500 status codes MUST be returned for + requests that would have otherwise been routed to an invalid backend. If + multiple backends are specified, and some are invalid, the proportion of + requests that would otherwise have been routed to an invalid backend + MUST receive a 500 status code. + + For example, if two backends are specified with equal weights, and one is + invalid, 50 percent of traffic must receive a 500. Implementations may + choose how that 50 percent is determined. + + When a HTTPBackendRef refers to a Service that has no ready endpoints, + implementations SHOULD return a 503 for requests to that backend instead. + If an implementation chooses to do this, all of the above rules for 500 responses + MUST also apply for responses that return a 503. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Core + items: + description: |- + HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. + + Note that when a namespace different than the local namespace is specified, a + ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + + When the BackendRef points to a Kubernetes Service, implementations SHOULD + honor the appProtocol field if it is set for the target Service Port. + + Implementations supporting appProtocol SHOULD recognize the Kubernetes + Standard Application Protocols defined in KEP-3726. + + If a Service appProtocol isn't specified, an implementation MAY infer the + backend protocol through its own means. Implementations MAY infer the + protocol from the Route type referring to the backend Service. + + If a Route is not able to send traffic to the backend using the specified + protocol then the backend is considered invalid. Implementations MUST set the + "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + properties: + filters: + description: |- + Filters defined at this level should be executed if and only if the + request is being forwarded to the backend defined here. + + Support: Implementation-specific (For broader support of filters, use the + Filters field in HTTPRouteRule.) + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the + filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != + ''RequestRedirect'')' + - message: filter.requestRedirect must be specified + for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == + ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() + <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() + <= 1 + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: |- + Weight specifies the proportion of requests forwarded to the referenced + backend. This is computed as weight/(sum of all weights in this + BackendRefs list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If only one backend is specified and it has a weight greater than 0, 100% + of the traffic is forwarded to that backend. If weight is set to 0, no + traffic should be forwarded for this entry. If unspecified, weight + defaults to 1. + + Support for this field varies based on the context where used. + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + Wherever possible, implementations SHOULD implement filters in the order + they are specified. + + Implementations MAY choose to implement this ordering strictly, rejecting + any combination or order of filters that can not be supported. If implementations + choose a strict interpretation of filter ordering, they MUST clearly document + that behavior. + + To reject an invalid combination or order of filters, implementations SHOULD + consider the Route Rules with this configuration invalid. If all Route Rules + in a Route are invalid, the entire Route would be considered invalid. If only + a portion of Route Rules are invalid, implementations MUST set the + "PartiallyInvalid" condition for the Route. + + Conformance-levels at this level are defined based on the type of filter: + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + This filter can be used multiple times within the same rule. + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |+ + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + Support: Extended + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + If no port is specified, the redirect port MUST be derived using the + following rules: + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + add: + - name: "my-header" + value: "bar,baz" + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + Config: + remove: ["my-header1", "my-header3"] + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + Input: + GET /foo HTTP/1.1 + my-header: foo + + Config: + set: + - name: "my-header" + value: "bar" + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + Request Path | Prefix Match | Replace Prefix | Modified Path + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type + is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect + filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && + self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= + 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + For example, take the following matches configuration: + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + Note: The precedence of RegularExpression path matches are implementation-specific. + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given\naction. Multiple match types + are ANDed together, i.e. the match will\nevaluate to true + only if all conditions are satisfied.\n\nFor example, the + match below will match a HTTP request only if its path\nstarts + with `/foo` AND it contains the `version: v1` header:\n\n```\nmatch:\n\n\tpath:\n\t + \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t + \ value \"v1\"\n\n```" + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + Support: Core (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: |- + Method specifies HTTP method matcher. + When specified, this route will be matched only if the request has the + specified method. + + Support: Extended + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: |- + Path specifies a HTTP request path matcher. If this field is not + specified, a default prefix match on the "/" path is provided. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + Support: Core (Exact, PathPrefix) + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with + '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') + : true' + - message: must not contain '//' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') + : true' + - message: must not contain '/./' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') + : true' + - message: must not contain '/../' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') + : true' + - message: must not contain '%2f' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') + : true' + - message: must not contain '%2F' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') + : true' + - message: must not contain '#' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') + : true' + - message: must not end with '/..' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') + : true' + - message: must not end with '/.' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') + : true' + - message: type must be one of ['Exact', 'PathPrefix', + 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type + == 'RegularExpression' + - message: must only contain valid characters (matching + ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) + for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") + : true' + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + Support: Extended (Exact) + + Support: Implementation-specific (RegularExpression) + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 64 + type: array + timeouts: + description: |- + Timeouts defines the timeouts that can be configured for an HTTP request. + + Support: Extended + properties: + backendRequest: + description: |- + BackendRequest specifies a timeout for an individual request from the gateway + to a backend. This covers the time from when the request first starts being + sent from the gateway to when the full response has been received from the backend. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + An entire client HTTP transaction with a gateway, covered by the Request timeout, + may result in more than one call from the gateway to the destination backend, + for example, if automatic retries are supported. + + The value of BackendRequest must be a Gateway API Duration string as defined by + GEP-2257. When this field is unspecified, its behavior is implementation-specific; + when specified, the value of BackendRequest must be no more than the value of the + Request timeout (since the Request timeout encompasses the BackendRequest timeout). + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + description: |- + Request specifies the maximum duration for a gateway to respond to an HTTP request. + If the gateway has not been able to respond before this deadline is met, the gateway + MUST return a timeout error. + + For example, setting the `rules.timeouts.request` field to the value `10s` in an + `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds + to complete. + + Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout + completely. Implementations that cannot completely disable the timeout MUST + instead interpret the zero duration as the longest possible value to which + the timeout can be set. + + This timeout is intended to cover as close to the whole request-response transaction + as possible although an implementation MAY choose to start the timeout after the entire + request stream has been received instead of immediately after the transaction is + initiated by the client. + + The value of Request is a Gateway API Duration string as defined by GEP-2257. When this + field is unspecified, request timeout behavior is implementation-specific. + + Support: Extended + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request + timeout + rule: '!(has(self.request) && has(self.backendRequest) && + duration(self.request) != duration(''0s'') && duration(self.backendRequest) + > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with + backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? + (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): + true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + ? ((size(self.matches) != 1 || !has(self.matches[0].path) || + self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter + with path.replacePrefixMatch, exactly one PathPrefix match must + be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) + || self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: Within backendRefs, When using URLRewrite filter with + path.replacePrefixMatch, exactly one PathPrefix match must be + specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the + total number of matches across all rules in a route must be less + than 128 + rule: '(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() + > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() + : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() + > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() + : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() + > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() + : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() + > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() + : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() + > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() + : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the route, and the status of the route with respect to + each parent. When this route attaches to a parent, the controller that + manages the parent must add an entry to this list when the controller + first sees the route and should update the entry as appropriate when the + route or gateway is modified. + + Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this API + can only populate Route status for the Gateways/parent resources they are + responsible for. + + A maximum of 32 Gateways will be represented in this list. An empty list + means the route has not been attached to any Gateway. + items: + description: |- + RouteParentStatus describes the status of a route with respect to an + associated Parent. + properties: + conditions: + description: |- + Conditions describes the status of the route with respect to the Gateway. + Note that the route's availability is also subject to the Gateway's own + status conditions and listener status. + + If the Route's ParentRef specifies an existing Gateway that supports + Routes of this kind AND that Gateway's controller has sufficient access, + then that Gateway's controller MUST set the "Accepted" condition on the + Route, to indicate whether the route has been accepted or rejected by the + Gateway, and why. + + A Route MUST be considered "Accepted" if at least one of the Route's + rules is implemented by the Gateway. + + There are a number of cases where the "Accepted" condition may not be set + due to lack of controller visibility, that includes when: + + * The Route refers to a non-existent parent. + * The Route is of a type that the controller does not support. + * The Route is in a namespace the controller does not have access to. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: |- + ParentRef corresponds with a ParentRef in the spec that this + RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# +# config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.2.0 + gateway.networking.k8s.io/channel: standard + creationTimestamp: null + name: referencegrants.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: ReferenceGrant + listKind: ReferenceGrantList + plural: referencegrants + shortNames: + - refgrant + singular: referencegrant + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + ReferenceGrant identifies kinds of resources in other namespaces that are + trusted to reference the specified kinds of resources in the same namespace + as the policy. + + Each ReferenceGrant can be used to represent a unique trust relationship. + Additional Reference Grants can be used to add to the set of trusted + sources of inbound references for the namespace they are defined within. + + All cross-namespace references in Gateway API (with the exception of cross-namespace + Gateway-route attachment) require a ReferenceGrant. + + ReferenceGrant is a form of runtime verification allowing users to assert + which cross-namespace object references are permitted. Implementations that + support ReferenceGrant MUST NOT permit cross-namespace references which have + no grant, and MUST respond to the removal of a grant by revoking the access + that the grant allowed. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReferenceGrant. + properties: + from: + description: |- + From describes the trusted namespaces and kinds that can reference the + resources described in "To". Each entry in this list MUST be considered + to be an additional place that references can be valid from, or to put + this another way, entries MUST be combined using OR. + + Support: Core + items: + description: ReferenceGrantFrom describes trusted namespaces and + kinds. + properties: + group: + description: |- + Group is the group of the referent. + When empty, the Kubernetes core API group is inferred. + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: |- + Kind is the kind of the referent. Although implementations may support + additional resources, the following types are part of the "Core" + support level for this field. + + When used to permit a SecretObjectReference: + + * Gateway + + When used to permit a BackendObjectReference: + + * GRPCRoute + * HTTPRoute + * TCPRoute + * TLSRoute + * UDPRoute + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + namespace: + description: |- + Namespace is the namespace of the referent. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - namespace + type: object + maxItems: 16 + minItems: 1 + type: array + to: + description: |- + To describes the resources that may be referenced by the resources + described in "From". Each entry in this list MUST be considered to be an + additional place that references can be valid to, or to put this another + way, entries MUST be combined using OR. + + Support: Core + items: + description: |- + ReferenceGrantTo describes what Kinds are allowed as targets of the + references. + properties: + group: + description: |- + Group is the group of the referent. + When empty, the Kubernetes core API group is inferred. + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: |- + Kind is the kind of the referent. Although implementations may support + additional resources, the following types are part of the "Core" + support level for this field: + + * Secret when used to permit a SecretObjectReference + * Service when used to permit a BackendObjectReference + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. When unspecified, this policy + refers to all resources of the specified Group and Kind in the local + namespace. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - from + - to + type: object + type: object + served: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml new file mode 100644 index 0000000..821f969 --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_accesscontrolpolicies.yaml @@ -0,0 +1,368 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: accesscontrolpolicies.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: AccessControlPolicy + listKind: AccessControlPolicyList + plural: accesscontrolpolicies + singular: accesscontrolpolicy + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: AccessControlPolicy defines an access control policy. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: AccessControlPolicySpec configures an access control policy. + properties: + apiKey: + description: AccessControlPolicyAPIKey configure an APIKey control + policy. + properties: + forwardHeaders: + additionalProperties: + type: string + description: ForwardHeaders instructs the middleware to forward + key metadata as header values upon successful authentication. + type: object + keySource: + description: KeySource defines how to extract API keys from requests. + properties: + cookie: + description: Cookie is the name of a cookie. + type: string + header: + description: Header is the name of a header. + type: string + headerAuthScheme: + description: |- + HeaderAuthScheme sets an optional auth scheme when Header is set to "Authorization". + If set, this scheme is removed from the token, and all requests not including it are dropped. + type: string + query: + description: Query is the name of a query parameter. + type: string + type: object + keys: + description: Keys define the set of authorized keys to access + a protected resource. + items: + description: AccessControlPolicyAPIKeyKey defines an API key. + properties: + id: + description: ID is the unique identifier of the key. + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds arbitrary metadata for this + key, can be used by ForwardHeaders. + type: object + value: + description: Value is the SHAKE-256 hash (using 64 bytes) + of the API key. + type: string + required: + - id + - value + type: object + type: array + required: + - keySource + type: object + basicAuth: + description: AccessControlPolicyBasicAuth holds the HTTP basic authentication + configuration. + properties: + forwardUsernameHeader: + type: string + realm: + type: string + stripAuthorizationHeader: + type: boolean + users: + items: + type: string + type: array + type: object + jwt: + description: AccessControlPolicyJWT configures a JWT access control + policy. + properties: + claims: + type: string + forwardHeaders: + additionalProperties: + type: string + type: object + jwksFile: + type: string + jwksUrl: + type: string + publicKey: + type: string + signingSecret: + type: string + signingSecretBase64Encoded: + type: boolean + stripAuthorizationHeader: + type: boolean + tokenQueryKey: + type: string + type: object + oAuthIntro: + description: AccessControlOAuthIntro configures an OAuth 2.0 Token + Introspection access control policy. + properties: + claims: + type: string + clientConfig: + description: AccessControlOAuthIntroClientConfig configures the + OAuth 2.0 client for issuing token introspection requests. + properties: + headers: + additionalProperties: + type: string + description: Headers to set when sending requests to the Authorization + Server. + type: object + maxRetries: + default: 3 + description: MaxRetries defines the number of retries for + introspection requests. + type: integer + timeoutSeconds: + default: 5 + description: TimeoutSeconds configures the maximum amount + of seconds to wait before giving up on requests. + type: integer + tls: + description: TLS configures TLS communication with the Authorization + Server. + properties: + ca: + description: CA sets the CA bundle used to sign the Authorization + Server certificate. + type: string + insecureSkipVerify: + description: |- + InsecureSkipVerify skips the Authorization Server certificate validation. + For testing purposes only, do not use in production. + type: boolean + type: object + tokenTypeHint: + description: |- + TokenTypeHint is a hint to pass to the Authorization Server. + See https://tools.ietf.org/html/rfc7662#section-2.1 for more information. + type: string + url: + description: URL of the Authorization Server. + type: string + required: + - url + type: object + forwardHeaders: + additionalProperties: + type: string + type: object + tokenSource: + description: |- + TokenSource describes how to extract tokens from HTTP requests. + If multiple sources are set, the order is the following: header > query > cookie. + properties: + cookie: + description: Cookie is the name of a cookie. + type: string + header: + description: Header is the name of a header. + type: string + headerAuthScheme: + description: |- + HeaderAuthScheme sets an optional auth scheme when Header is set to "Authorization". + If set, this scheme is removed from the token, and all requests not including it are dropped. + type: string + query: + description: Query is the name of a query parameter. + type: string + type: object + required: + - clientConfig + - tokenSource + type: object + oidc: + description: AccessControlPolicyOIDC holds the OIDC authentication + configuration. + properties: + authParams: + additionalProperties: + type: string + type: object + claims: + type: string + clientId: + type: string + disableAuthRedirectionPaths: + items: + type: string + type: array + forwardHeaders: + additionalProperties: + type: string + type: object + issuer: + type: string + logoutUrl: + type: string + redirectUrl: + type: string + scopes: + items: + type: string + type: array + secret: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + session: + description: Session holds session configuration. + properties: + domain: + type: string + path: + type: string + refresh: + type: boolean + sameSite: + type: string + secure: + type: boolean + type: object + stateCookie: + description: StateCookie holds state cookie configuration. + properties: + domain: + type: string + path: + type: string + sameSite: + type: string + secure: + type: boolean + type: object + type: object + oidcGoogle: + description: AccessControlPolicyOIDCGoogle holds the Google OIDC authentication + configuration. + properties: + authParams: + additionalProperties: + type: string + type: object + clientId: + type: string + emails: + description: Emails are the allowed emails to connect. + items: + type: string + minItems: 1 + type: array + forwardHeaders: + additionalProperties: + type: string + type: object + logoutUrl: + type: string + redirectUrl: + type: string + secret: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + session: + description: Session holds session configuration. + properties: + domain: + type: string + path: + type: string + refresh: + type: boolean + sameSite: + type: string + secure: + type: boolean + type: object + stateCookie: + description: StateCookie holds state cookie configuration. + properties: + domain: + type: string + path: + type: string + sameSite: + type: string + secure: + type: boolean + type: object + type: object + type: object + status: + description: The current status of this access control policy. + properties: + specHash: + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_apiaccesses.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_apiaccesses.yaml new file mode 100644 index 0000000..ee8ecaf --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_apiaccesses.yaml @@ -0,0 +1,188 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiaccesses.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIAccess + listKind: APIAccessList + plural: apiaccesses + singular: apiaccess + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIAccess defines who can access to a set of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIAccess. + properties: + apiBundles: + description: |- + APIBundles defines a set of APIBundle that will be accessible to the configured audience. + Multiple APIAccesses can select the same APIBundles. + items: + description: APIBundleReference references an APIBundle. + properties: + name: + description: Name of the APIBundle. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apiBundles + rule: self.all(x, self.exists_one(y, x.name == y.name)) + apiPlan: + description: APIPlan defines which APIPlan will be used. + properties: + name: + description: Name of the APIPlan. + maxLength: 253 + type: string + required: + - name + type: object + apiSelector: + description: |- + APISelector selects the APIs that will be accessible to the configured audience. + Multiple APIAccesses can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be accessible to the configured audience. + Multiple APIAccesses can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + everyone: + description: Everyone indicates that all users will have access to + the selected APIs. + type: boolean + groups: + description: Groups are the consumer groups that will gain access + to the selected APIs. + items: + type: string + type: array + operationFilter: + description: |- + OperationFilter specifies the allowed operations on APIs and APIVersions. + If not set, all operations are available. + An empty OperationFilter prohibits all operations. + properties: + include: + description: Include defines the names of OperationSets that will + be accessible. + items: + type: string + maxItems: 100 + type: array + type: object + weight: + description: Weight specifies the evaluation order of the plan. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + type: object + x-kubernetes-validations: + - message: groups and everyone are mutually exclusive + rule: '(has(self.everyone) && has(self.groups)) ? !(self.everyone && + self.groups.size() > 0) : true' + status: + description: The current status of this APIAccess. + properties: + hash: + description: Hash is a hash representing the APIAccess. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_apibundles.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_apibundles.yaml new file mode 100644 index 0000000..a45a0b1 --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_apibundles.yaml @@ -0,0 +1,125 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apibundles.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIBundle + listKind: APIBundleList + plural: apibundles + singular: apibundle + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIBundle defines a set of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIBundle. + properties: + apiSelector: + description: |- + APISelector selects the APIs that will be accessible to the configured audience. + Multiple APIBundles can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be accessible to the configured audience. + Multiple APIBundles can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + type: object + status: + description: The current status of this APIBundle. + properties: + hash: + description: Hash is a hash representing the APIBundle. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_apiplans.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_apiplans.yaml new file mode 100644 index 0000000..92e1b9b --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_apiplans.yaml @@ -0,0 +1,103 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiplans.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIPlan + listKind: APIPlanList + plural: apiplans + singular: apiplan + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIPlan defines API Plan policy. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIPlan. + properties: + description: + description: Description describes the plan. + type: string + quota: + description: Quota defines the quota policy. + properties: + limit: + description: Limit is the maximum number of token in the bucket. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + period: + description: Period is the unit of time for the Limit. + format: duration + type: string + x-kubernetes-validations: + - message: must be between 1s and 9999h + rule: self >= duration('1s') && self <= duration('9999h') + required: + - limit + type: object + rateLimit: + description: RateLimit defines the rate limit policy. + properties: + limit: + description: Limit is the maximum number of token in the bucket. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + period: + description: Period is the unit of time for the Limit. + format: duration + type: string + x-kubernetes-validations: + - message: must be between 1s and 1h + rule: self >= duration('1s') && self <= duration('1h') + required: + - limit + type: object + title: + description: Title is the human-readable name of the plan. + type: string + required: + - title + type: object + status: + description: The current status of this APIPlan. + properties: + hash: + description: Hash is a hash representing the APIPlan. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_apiportals.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_apiportals.yaml new file mode 100644 index 0000000..bc04170 --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_apiportals.yaml @@ -0,0 +1,139 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiportals.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIPortal + listKind: APIPortalList + plural: apiportals + singular: apiportal + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIPortal defines a developer portal for accessing the documentation + of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIPortal. + properties: + description: + description: Description of the APIPortal. + type: string + title: + description: Title is the public facing name of the APIPortal. + type: string + trustedUrls: + description: TrustedURLs are the urls that are trusted by the OAuth + 2.0 authorization server. + items: + type: string + maxItems: 1 + minItems: 1 + type: array + x-kubernetes-validations: + - message: must be a valid URLs + rule: self.all(x, isURL(x)) + ui: + description: UI holds the UI customization options. + properties: + logoUrl: + description: LogoURL is the public URL of the logo. + type: string + type: object + required: + - trustedUrls + type: object + status: + description: The current status of this APIPortal. + properties: + hash: + description: Hash is a hash representing the APIPortal. + type: string + oidc: + description: OIDC is the OIDC configuration for accessing the exposed + APIPortal WebUI. + properties: + clientId: + description: ClientID is the OIDC ClientID for accessing the exposed + APIPortal WebUI. + type: string + companyClaim: + description: CompanyClaim is the name of the JWT claim containing + the user company. + type: string + emailClaim: + description: EmailClaim is the name of the JWT claim containing + the user email. + type: string + firstnameClaim: + description: FirstnameClaim is the name of the JWT claim containing + the user firstname. + type: string + generic: + description: Generic indicates whether or not the APIPortal authentication + relies on Generic OIDC. + type: boolean + groupsClaim: + description: GroupsClaim is the name of the JWT claim containing + the user groups. + type: string + issuer: + description: Issuer is the OIDC issuer for accessing the exposed + APIPortal WebUI. + type: string + lastnameClaim: + description: LastnameClaim is the name of the JWT claim containing + the user lastname. + type: string + scopes: + description: Scopes is the OIDC scopes for getting user attributes + during the authentication to the exposed APIPortal WebUI. + type: string + secretName: + description: SecretName is the name of the secret containing the + OIDC ClientSecret for accessing the exposed APIPortal WebUI. + type: string + syncedAttributes: + description: SyncedAttributes configure the user attributes to + sync. + items: + type: string + type: array + userIdClaim: + description: UserIDClaim is the name of the JWT claim containing + the user ID. + type: string + type: object + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_apiratelimits.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_apiratelimits.yaml new file mode 100644 index 0000000..8e328d3 --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_apiratelimits.yaml @@ -0,0 +1,166 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiratelimits.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIRateLimit + listKind: APIRateLimitList + plural: apiratelimits + singular: apiratelimit + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIRateLimit defines how group of consumers are rate limited + on a set of APIs. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIRateLimit. + properties: + apiSelector: + description: |- + APISelector selects the APIs that will be rate limited. + Multiple APIRateLimits can select the same set of APIs. + This field is optional and follows standard label selector semantics. + An empty APISelector matches any API. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + apis: + description: |- + APIs defines a set of APIs that will be rate limited. + Multiple APIRateLimits can select the same APIs. + When combined with APISelector, this set of APIs is appended to the matching APIs. + items: + description: APIReference references an API. + properties: + name: + description: Name of the API. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + type: array + x-kubernetes-validations: + - message: duplicated apis + rule: self.all(x, self.exists_one(y, x.name == y.name)) + everyone: + description: |- + Everyone indicates that all users will, by default, be rate limited with this configuration. + If an APIRateLimit explicitly target a group, the default rate limit will be ignored. + type: boolean + groups: + description: |- + Groups are the consumer groups that will be rate limited. + Multiple APIRateLimits can target the same set of consumer groups, the most restrictive one applies. + When a consumer belongs to multiple groups, the least restrictive APIRateLimit applies. + items: + type: string + type: array + limit: + description: Limit is the maximum number of token in the bucket. + type: integer + x-kubernetes-validations: + - message: must be a positive number + rule: self >= 0 + period: + description: Period is the unit of time for the Limit. + format: duration + type: string + x-kubernetes-validations: + - message: must be between 1s and 1h + rule: self >= duration('1s') && self <= duration('1h') + strategy: + description: |- + Strategy defines how the bucket state will be synchronized between the different Traefik Hub instances. + It can be, either "local" or "distributed". + enum: + - local + - distributed + type: string + required: + - limit + type: object + x-kubernetes-validations: + - message: groups and everyone are mutually exclusive + rule: '(has(self.everyone) && has(self.groups)) ? !(self.everyone && + self.groups.size() > 0) : true' + status: + description: The current status of this APIRateLimit. + properties: + hash: + description: Hash is a hash representing the APIRateLimit. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_apis.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_apis.yaml new file mode 100644 index 0000000..a7b9e5e --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_apis.yaml @@ -0,0 +1,190 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apis.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: API + listKind: APIList + plural: apis + singular: api + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + API defines an HTTP interface that is exposed to external clients. It specifies the supported versions + and provides instructions for accessing its documentation. Once instantiated, an API object is associated + with an Ingress, IngressRoute, or HTTPRoute resource, enabling the exposure of the described API to the outside world. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: APISpec describes the API. + properties: + openApiSpec: + description: OpenAPISpec defines the API contract as an OpenAPI specification. + properties: + operationSets: + description: OperationSets defines the sets of operations to be + referenced for granular filtering in APIAccesses. + items: + description: |- + OperationSet gives a name to a set of matching OpenAPI operations. + This set of operations can then be referenced for granular filtering in APIAccesses. + properties: + matchers: + description: Matchers defines a list of alternative rules + for matching OpenAPI operations. + items: + description: OperationMatcher defines criteria for matching + an OpenAPI operation. + minProperties: 1 + properties: + methods: + description: Methods specifies the HTTP methods to + be included for selection. + items: + type: string + maxItems: 10 + type: array + path: + description: Path specifies the exact path of the + operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathPrefix: + description: PathPrefix specifies the path prefix + of the operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathRegex: + description: PathRegex specifies a regular expression + pattern for matching operations based on their paths. + type: string + type: object + x-kubernetes-validations: + - message: path, pathPrefix and pathRegex are mutually + exclusive + rule: '[has(self.path), has(self.pathPrefix), has(self.pathRegex)].filter(x, + x).size() <= 1' + maxItems: 100 + minItems: 1 + type: array + name: + description: Name is the name of the OperationSet to reference + in APIAccesses. + maxLength: 253 + type: string + required: + - matchers + - name + type: object + maxItems: 100 + type: array + override: + description: Override holds data used to override OpenAPI specification. + properties: + servers: + items: + properties: + url: + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + required: + - url + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - servers + type: object + path: + description: |- + Path specifies the endpoint path within the Kubernetes Service where the OpenAPI specification can be obtained. + The Service queried is determined by the associated Ingress, IngressRoute, or HTTPRoute resource to which the API is attached. + It's important to note that this option is incompatible if the Ingress or IngressRoute specifies multiple backend services. + The Path must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + url: + description: |- + URL is a Traefik Hub agent accessible URL for obtaining the OpenAPI specification. + The URL must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + type: object + x-kubernetes-validations: + - message: path or url must be defined + rule: has(self.path) || has(self.url) + versions: + description: Versions are the different APIVersions available. + items: + description: APIVersionRef references an APIVersion. + properties: + name: + description: Name of the APIVersion. + maxLength: 253 + type: string + required: + - name + type: object + maxItems: 100 + minItems: 1 + type: array + type: object + status: + description: The current status of this API. + properties: + hash: + description: Hash is a hash representing the API. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/hub.traefik.io_apiversions.yaml b/utils/assets/charts/traefik/crds/hub.traefik.io_apiversions.yaml new file mode 100644 index 0000000..97184ef --- /dev/null +++ b/utils/assets/charts/traefik/crds/hub.traefik.io_apiversions.yaml @@ -0,0 +1,194 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: apiversions.hub.traefik.io +spec: + group: hub.traefik.io + names: + kind: APIVersion + listKind: APIVersionList + plural: apiversions + singular: apiversion + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.title + name: Title + type: string + - jsonPath: .spec.release + name: Release + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: APIVersion defines a version of an API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: The desired behavior of this APIVersion. + properties: + openApiSpec: + description: OpenAPISpec defines the API contract as an OpenAPI specification. + properties: + operationSets: + description: OperationSets defines the sets of operations to be + referenced for granular filtering in APIAccesses. + items: + description: |- + OperationSet gives a name to a set of matching OpenAPI operations. + This set of operations can then be referenced for granular filtering in APIAccesses. + properties: + matchers: + description: Matchers defines a list of alternative rules + for matching OpenAPI operations. + items: + description: OperationMatcher defines criteria for matching + an OpenAPI operation. + minProperties: 1 + properties: + methods: + description: Methods specifies the HTTP methods to + be included for selection. + items: + type: string + maxItems: 10 + type: array + path: + description: Path specifies the exact path of the + operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathPrefix: + description: PathPrefix specifies the path prefix + of the operations to select. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + pathRegex: + description: PathRegex specifies a regular expression + pattern for matching operations based on their paths. + type: string + type: object + x-kubernetes-validations: + - message: path, pathPrefix and pathRegex are mutually + exclusive + rule: '[has(self.path), has(self.pathPrefix), has(self.pathRegex)].filter(x, + x).size() <= 1' + maxItems: 100 + minItems: 1 + type: array + name: + description: Name is the name of the OperationSet to reference + in APIAccesses. + maxLength: 253 + type: string + required: + - matchers + - name + type: object + maxItems: 100 + type: array + override: + description: Override holds data used to override OpenAPI specification. + properties: + servers: + items: + properties: + url: + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + required: + - url + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - servers + type: object + path: + description: |- + Path specifies the endpoint path within the Kubernetes Service where the OpenAPI specification can be obtained. + The Service queried is determined by the associated Ingress, IngressRoute, or HTTPRoute resource to which the API is attached. + It's important to note that this option is incompatible if the Ingress or IngressRoute specifies multiple backend services. + The Path must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + maxLength: 255 + type: string + x-kubernetes-validations: + - message: must start with a '/' + rule: self.startsWith('/') + - message: cannot contains '../' + rule: '!self.matches(r"""(\/\.\.\/)|(\/\.\.$)""")' + url: + description: |- + URL is a Traefik Hub agent accessible URL for obtaining the OpenAPI specification. + The URL must be accessible via a GET request method and should serve a YAML or JSON document containing the OpenAPI specification. + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + type: object + x-kubernetes-validations: + - message: path or url must be defined + rule: has(self.path) || has(self.url) + release: + description: |- + Release is the version number of the API. + This value must follow the SemVer format: https://semver.org/ + maxLength: 100 + type: string + x-kubernetes-validations: + - message: must be a valid semver version + rule: self.matches(r"""^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$""") + title: + description: Title is the public facing name of the APIVersion. + type: string + required: + - release + type: object + status: + description: The current status of this APIVersion. + properties: + hash: + description: Hash is a hash representing the APIVersion. + type: string + syncedAt: + format: date-time + type: string + version: + type: string + type: object + type: object + served: true + storage: true + subresources: {} diff --git a/utils/assets/charts/traefik/crds/traefik.io_ingressroutes.yaml b/utils/assets/charts/traefik/crds/traefik.io_ingressroutes.yaml new file mode 100644 index 0000000..ccb374a --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_ingressroutes.yaml @@ -0,0 +1,366 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: ingressroutes.traefik.io +spec: + group: traefik.io + names: + kind: IngressRoute + listKind: IngressRouteList + plural: ingressroutes + singular: ingressroute + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IngressRoute is the CRD implementation of a Traefik HTTP Router. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IngressRouteSpec defines the desired state of IngressRoute. + properties: + entryPoints: + description: |- + EntryPoints defines the list of entry point names to bind to. + Entry points have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/entrypoints/ + Default: all. + items: + type: string + type: array + routes: + description: Routes defines the list of routes. + items: + description: Route holds the HTTP route configuration. + properties: + kind: + description: |- + Kind defines the kind of the route. + Rule is the only supported kind. + enum: + - Rule + type: string + match: + description: |- + Match defines the router's rule. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rule + type: string + middlewares: + description: |- + Middlewares defines the list of references to Middleware resources. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-middleware + items: + description: MiddlewareRef is a reference to a Middleware + resource. + properties: + name: + description: Name defines the name of the referenced Middleware + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Middleware resource. + type: string + required: + - name + type: object + type: array + priority: + description: |- + Priority defines the router's priority. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#priority + type: integer + services: + description: |- + Services defines the list of Service. + It can contain any combination of TraefikService and/or reference to a Kubernetes Service. + items: + description: Service defines an upstream HTTP service to proxy + traffic to. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be + sent to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname + in the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for + the health check endpoint. + type: string + port: + description: Port defines the server URL port for + the health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme + for the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status + code of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to + the client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie + can be accessed by client-side APIs, such as + JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie + can only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + type: array + syntax: + description: |- + Syntax defines the router's rule syntax. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rulesyntax + type: string + required: + - kind + - match + type: object + type: array + tls: + description: |- + TLS defines the TLS configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#tls + properties: + certResolver: + description: |- + CertResolver defines the name of the certificate resolver to use. + Cert resolvers have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/https/acme/#certificate-resolvers + type: string + domains: + description: |- + Domains defines the list of domains that will be used to issue certificates. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#domains + items: + description: Domain holds a domain name with SANs. + properties: + main: + description: Main defines the main domain name. + type: string + sans: + description: SANs defines the subject alternative domain + names. + items: + type: string + type: array + type: object + type: array + options: + description: |- + Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. + If not defined, the `default` TLSOption is used. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#tls-options + properties: + name: + description: |- + Name defines the name of the referenced TLSOption. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsoption + type: string + namespace: + description: |- + Namespace defines the namespace of the referenced TLSOption. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsoption + type: string + required: + - name + type: object + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + store: + description: |- + Store defines the reference to the TLSStore, that will be used to store certificates. + Please note that only `default` TLSStore can be used. + properties: + name: + description: |- + Name defines the name of the referenced TLSStore. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsstore + type: string + namespace: + description: |- + Namespace defines the namespace of the referenced TLSStore. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-tlsstore + type: string + required: + - name + type: object + type: object + required: + - routes + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_ingressroutetcps.yaml b/utils/assets/charts/traefik/crds/traefik.io_ingressroutetcps.yaml new file mode 100644 index 0000000..ae675f6 --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_ingressroutetcps.yaml @@ -0,0 +1,247 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: ingressroutetcps.traefik.io +spec: + group: traefik.io + names: + kind: IngressRouteTCP + listKind: IngressRouteTCPList + plural: ingressroutetcps + singular: ingressroutetcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IngressRouteTCP is the CRD implementation of a Traefik TCP Router. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IngressRouteTCPSpec defines the desired state of IngressRouteTCP. + properties: + entryPoints: + description: |- + EntryPoints defines the list of entry point names to bind to. + Entry points have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/entrypoints/ + Default: all. + items: + type: string + type: array + routes: + description: Routes defines the list of routes. + items: + description: RouteTCP holds the TCP route configuration. + properties: + match: + description: |- + Match defines the router's rule. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rule_1 + type: string + middlewares: + description: Middlewares defines the list of references to MiddlewareTCP + resources. + items: + description: ObjectReference is a generic reference to a Traefik + resource. + properties: + name: + description: Name defines the name of the referenced Traefik + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Traefik resource. + type: string + required: + - name + type: object + type: array + priority: + description: |- + Priority defines the router's priority. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#priority_1 + type: integer + services: + description: Services defines the list of TCP services. + items: + description: ServiceTCP defines an upstream TCP service to + proxy traffic to. + properties: + name: + description: Name defines the name of the referenced Kubernetes + Service. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + proxyProtocol: + description: |- + ProxyProtocol defines the PROXY protocol configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#proxy-protocol + properties: + version: + description: Version defines the PROXY Protocol version + to use. + type: integer + type: object + serversTransport: + description: |- + ServersTransport defines the name of ServersTransportTCP resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + terminationDelay: + description: |- + TerminationDelay defines the deadline that the proxy sets, after one of its connected peers indicates + it has closed the writing capability of its connection, to close the reading capability as well, + hence fully terminating the connection. + It is a duration in milliseconds, defaulting to 100. + A negative value means an infinite deadline (i.e. the reading capability is never closed). + Deprecated: TerminationDelay will not be supported in future APIVersions, please use ServersTransport to configure the TerminationDelay instead. + type: integer + tls: + description: TLS determines whether to use TLS when dialing + with the backend. + type: boolean + weight: + description: Weight defines the weight used when balancing + requests between multiple Kubernetes Service. + type: integer + required: + - name + - port + type: object + type: array + syntax: + description: |- + Syntax defines the router's rule syntax. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#rulesyntax_1 + type: string + required: + - match + type: object + type: array + tls: + description: |- + TLS defines the TLS configuration on a layer 4 / TCP Route. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#tls_1 + properties: + certResolver: + description: |- + CertResolver defines the name of the certificate resolver to use. + Cert resolvers have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/https/acme/#certificate-resolvers + type: string + domains: + description: |- + Domains defines the list of domains that will be used to issue certificates. + More info: https://doc.traefik.io/traefik/v3.2/routing/routers/#domains + items: + description: Domain holds a domain name with SANs. + properties: + main: + description: Main defines the main domain name. + type: string + sans: + description: SANs defines the subject alternative domain + names. + items: + type: string + type: array + type: object + type: array + options: + description: |- + Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. + If not defined, the `default` TLSOption is used. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#tls-options + properties: + name: + description: Name defines the name of the referenced Traefik + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Traefik resource. + type: string + required: + - name + type: object + passthrough: + description: Passthrough defines whether a TLS router will terminate + the TLS connection. + type: boolean + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + store: + description: |- + Store defines the reference to the TLSStore, that will be used to store certificates. + Please note that only `default` TLSStore can be used. + properties: + name: + description: Name defines the name of the referenced Traefik + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Traefik resource. + type: string + required: + - name + type: object + type: object + required: + - routes + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_ingressrouteudps.yaml b/utils/assets/charts/traefik/crds/traefik.io_ingressrouteudps.yaml new file mode 100644 index 0000000..a815d86 --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_ingressrouteudps.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: ingressrouteudps.traefik.io +spec: + group: traefik.io + names: + kind: IngressRouteUDP + listKind: IngressRouteUDPList + plural: ingressrouteudps + singular: ingressrouteudp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IngressRouteUDP is a CRD implementation of a Traefik UDP Router. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IngressRouteUDPSpec defines the desired state of a IngressRouteUDP. + properties: + entryPoints: + description: |- + EntryPoints defines the list of entry point names to bind to. + Entry points have to be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/entrypoints/ + Default: all. + items: + type: string + type: array + routes: + description: Routes defines the list of routes. + items: + description: RouteUDP holds the UDP route configuration. + properties: + services: + description: Services defines the list of UDP services. + items: + description: ServiceUDP defines an upstream UDP service to + proxy traffic to. + properties: + name: + description: Name defines the name of the referenced Kubernetes + Service. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + weight: + description: Weight defines the weight used when balancing + requests between multiple Kubernetes Service. + type: integer + required: + - name + - port + type: object + type: array + type: object + type: array + required: + - routes + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_middlewares.yaml b/utils/assets/charts/traefik/crds/traefik.io_middlewares.yaml new file mode 100644 index 0000000..f3ea9fc --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_middlewares.yaml @@ -0,0 +1,1126 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: middlewares.traefik.io +spec: + group: traefik.io + names: + kind: Middleware + listKind: MiddlewareList + plural: middlewares + singular: middleware + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + Middleware is the CRD implementation of a Traefik Middleware. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/overview/ + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: MiddlewareSpec defines the desired state of a Middleware. + properties: + addPrefix: + description: |- + AddPrefix holds the add prefix middleware configuration. + This middleware updates the path of a request before forwarding it. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/addprefix/ + properties: + prefix: + description: |- + Prefix is the string to add before the current path in the requested URL. + It should include a leading slash (/). + type: string + type: object + basicAuth: + description: |- + BasicAuth holds the basic auth middleware configuration. + This middleware restricts access to your services to known users. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/basicauth/ + properties: + headerField: + description: |- + HeaderField defines a header field to store the authenticated user. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/basicauth/#headerfield + type: string + realm: + description: |- + Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme. + Default: traefik. + type: string + removeHeader: + description: |- + RemoveHeader sets the removeHeader option to true to remove the authorization header before forwarding the request to your service. + Default: false. + type: boolean + secret: + description: Secret is the name of the referenced Kubernetes Secret + containing user credentials. + type: string + type: object + buffering: + description: |- + Buffering holds the buffering middleware configuration. + This middleware retries or limits the size of requests that can be forwarded to backends. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/buffering/#maxrequestbodybytes + properties: + maxRequestBodyBytes: + description: |- + MaxRequestBodyBytes defines the maximum allowed body size for the request (in bytes). + If the request exceeds the allowed size, it is not forwarded to the service, and the client gets a 413 (Request Entity Too Large) response. + Default: 0 (no maximum). + format: int64 + type: integer + maxResponseBodyBytes: + description: |- + MaxResponseBodyBytes defines the maximum allowed response size from the service (in bytes). + If the response exceeds the allowed size, it is not forwarded to the client. The client gets a 500 (Internal Server Error) response instead. + Default: 0 (no maximum). + format: int64 + type: integer + memRequestBodyBytes: + description: |- + MemRequestBodyBytes defines the threshold (in bytes) from which the request will be buffered on disk instead of in memory. + Default: 1048576 (1Mi). + format: int64 + type: integer + memResponseBodyBytes: + description: |- + MemResponseBodyBytes defines the threshold (in bytes) from which the response will be buffered on disk instead of in memory. + Default: 1048576 (1Mi). + format: int64 + type: integer + retryExpression: + description: |- + RetryExpression defines the retry conditions. + It is a logical combination of functions with operators AND (&&) and OR (||). + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/buffering/#retryexpression + type: string + type: object + chain: + description: |- + Chain holds the configuration of the chain middleware. + This middleware enables to define reusable combinations of other pieces of middleware. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/chain/ + properties: + middlewares: + description: Middlewares is the list of MiddlewareRef which composes + the chain. + items: + description: MiddlewareRef is a reference to a Middleware resource. + properties: + name: + description: Name defines the name of the referenced Middleware + resource. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Middleware resource. + type: string + required: + - name + type: object + type: array + type: object + circuitBreaker: + description: CircuitBreaker holds the circuit breaker configuration. + properties: + checkPeriod: + anyOf: + - type: integer + - type: string + description: CheckPeriod is the interval between successive checks + of the circuit breaker condition (when in standby state). + x-kubernetes-int-or-string: true + expression: + description: Expression is the condition that triggers the tripped + state. + type: string + fallbackDuration: + anyOf: + - type: integer + - type: string + description: FallbackDuration is the duration for which the circuit + breaker will wait before trying to recover (from a tripped state). + x-kubernetes-int-or-string: true + recoveryDuration: + anyOf: + - type: integer + - type: string + description: RecoveryDuration is the duration for which the circuit + breaker will try to recover (as soon as it is in recovering + state). + x-kubernetes-int-or-string: true + responseCode: + description: ResponseCode is the status code that the circuit + breaker will return while it is in the open state. + type: integer + type: object + compress: + description: |- + Compress holds the compress middleware configuration. + This middleware compresses responses before sending them to the client, using gzip, brotli, or zstd compression. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/compress/ + properties: + defaultEncoding: + description: DefaultEncoding specifies the default encoding if + the `Accept-Encoding` header is not in the request or contains + a wildcard (`*`). + type: string + encodings: + description: Encodings defines the list of supported compression + algorithms. + items: + type: string + type: array + excludedContentTypes: + description: |- + ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing. + `application/grpc` is always excluded. + items: + type: string + type: array + includedContentTypes: + description: IncludedContentTypes defines the list of content + types to compare the Content-Type header of the responses before + compressing. + items: + type: string + type: array + minResponseBodyBytes: + description: |- + MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed. + Default: 1024. + type: integer + type: object + contentType: + description: |- + ContentType holds the content-type middleware configuration. + This middleware exists to enable the correct behavior until at least the default one can be changed in a future version. + properties: + autoDetect: + description: |- + AutoDetect specifies whether to let the `Content-Type` header, if it has not been set by the backend, + be automatically set to a value derived from the contents of the response. + Deprecated: AutoDetect option is deprecated, Content-Type middleware is only meant to be used to enable the content-type detection, please remove any usage of this option. + type: boolean + type: object + digestAuth: + description: |- + DigestAuth holds the digest auth middleware configuration. + This middleware restricts access to your services to known users. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/digestauth/ + properties: + headerField: + description: |- + HeaderField defines a header field to store the authenticated user. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/basicauth/#headerfield + type: string + realm: + description: |- + Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme. + Default: traefik. + type: string + removeHeader: + description: RemoveHeader defines whether to remove the authorization + header before forwarding the request to the backend. + type: boolean + secret: + description: Secret is the name of the referenced Kubernetes Secret + containing user credentials. + type: string + type: object + errors: + description: |- + ErrorPage holds the custom error middleware configuration. + This middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/errorpages/ + properties: + query: + description: |- + Query defines the URL for the error page (hosted by service). + The {status} variable can be used in order to insert the status code in the URL. + type: string + service: + description: |- + Service defines the reference to a Kubernetes Service that will serve the error page. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/errorpages/#service + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent + to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname in + the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the + health check endpoint. + type: string + port: + description: Port defines the server URL port for the + health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for + the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status code + of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to the + client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie can + be accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can + only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + status: + description: |- + Status defines which status or range of statuses should result in an error page. + It can be either a status code as a number (500), + as multiple comma-separated numbers (500,502), + as ranges by separating two codes with a dash (500-599), + or a combination of the two (404,418,500-599). + items: + type: string + type: array + type: object + forwardAuth: + description: |- + ForwardAuth holds the forward auth middleware configuration. + This middleware delegates the request authentication to a Service. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/forwardauth/ + properties: + addAuthCookiesToResponse: + description: AddAuthCookiesToResponse defines the list of cookies + to copy from the authentication server response to the response. + items: + type: string + type: array + address: + description: Address defines the authentication server address. + type: string + authRequestHeaders: + description: |- + AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server. + If not set or empty then all request headers are passed. + items: + type: string + type: array + authResponseHeaders: + description: AuthResponseHeaders defines the list of headers to + copy from the authentication server response and set on forwarded + request, replacing any existing conflicting headers. + items: + type: string + type: array + authResponseHeadersRegex: + description: |- + AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match the regex. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/forwardauth/#authresponseheadersregex + type: string + tls: + description: TLS defines the configuration used to secure the + connection to the authentication server. + properties: + caOptional: + description: 'Deprecated: TLS client authentication is a server + side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).' + type: boolean + caSecret: + description: |- + CASecret is the name of the referenced Kubernetes Secret containing the CA to validate the server certificate. + The CA certificate is extracted from key `tls.ca` or `ca.crt`. + type: string + certSecret: + description: |- + CertSecret is the name of the referenced Kubernetes Secret containing the client certificate. + The client certificate is extracted from the keys `tls.crt` and `tls.key`. + type: string + insecureSkipVerify: + description: InsecureSkipVerify defines whether the server + certificates should be validated. + type: boolean + type: object + trustForwardHeader: + description: 'TrustForwardHeader defines whether to trust (ie: + forward) all X-Forwarded-* headers.' + type: boolean + type: object + grpcWeb: + description: |- + GrpcWeb holds the gRPC web middleware configuration. + This middleware converts a gRPC web request to an HTTP/2 gRPC request. + properties: + allowOrigins: + description: |- + AllowOrigins is a list of allowable origins. + Can also be a wildcard origin "*". + items: + type: string + type: array + type: object + headers: + description: |- + Headers holds the headers middleware configuration. + This middleware manages the requests and responses headers. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/headers/#customrequestheaders + properties: + accessControlAllowCredentials: + description: AccessControlAllowCredentials defines whether the + request can include user credentials. + type: boolean + accessControlAllowHeaders: + description: AccessControlAllowHeaders defines the Access-Control-Request-Headers + values sent in preflight response. + items: + type: string + type: array + accessControlAllowMethods: + description: AccessControlAllowMethods defines the Access-Control-Request-Method + values sent in preflight response. + items: + type: string + type: array + accessControlAllowOriginList: + description: AccessControlAllowOriginList is a list of allowable + origins. Can also be a wildcard origin "*". + items: + type: string + type: array + accessControlAllowOriginListRegex: + description: AccessControlAllowOriginListRegex is a list of allowable + origins written following the Regular Expression syntax (https://golang.org/pkg/regexp/). + items: + type: string + type: array + accessControlExposeHeaders: + description: AccessControlExposeHeaders defines the Access-Control-Expose-Headers + values sent in preflight response. + items: + type: string + type: array + accessControlMaxAge: + description: AccessControlMaxAge defines the time that a preflight + request may be cached. + format: int64 + type: integer + addVaryHeader: + description: AddVaryHeader defines whether the Vary header is + automatically added/updated when the AccessControlAllowOriginList + is set. + type: boolean + allowedHosts: + description: AllowedHosts defines the fully qualified list of + allowed domain names. + items: + type: string + type: array + browserXssFilter: + description: BrowserXSSFilter defines whether to add the X-XSS-Protection + header with the value 1; mode=block. + type: boolean + contentSecurityPolicy: + description: ContentSecurityPolicy defines the Content-Security-Policy + header value. + type: string + contentSecurityPolicyReportOnly: + description: ContentSecurityPolicyReportOnly defines the Content-Security-Policy-Report-Only + header value. + type: string + contentTypeNosniff: + description: ContentTypeNosniff defines whether to add the X-Content-Type-Options + header with the nosniff value. + type: boolean + customBrowserXSSValue: + description: |- + CustomBrowserXSSValue defines the X-XSS-Protection header value. + This overrides the BrowserXssFilter option. + type: string + customFrameOptionsValue: + description: |- + CustomFrameOptionsValue defines the X-Frame-Options header value. + This overrides the FrameDeny option. + type: string + customRequestHeaders: + additionalProperties: + type: string + description: CustomRequestHeaders defines the header names and + values to apply to the request. + type: object + customResponseHeaders: + additionalProperties: + type: string + description: CustomResponseHeaders defines the header names and + values to apply to the response. + type: object + featurePolicy: + description: 'Deprecated: FeaturePolicy option is deprecated, + please use PermissionsPolicy instead.' + type: string + forceSTSHeader: + description: ForceSTSHeader defines whether to add the STS header + even when the connection is HTTP. + type: boolean + frameDeny: + description: FrameDeny defines whether to add the X-Frame-Options + header with the DENY value. + type: boolean + hostsProxyHeaders: + description: HostsProxyHeaders defines the header keys that may + hold a proxied hostname value for the request. + items: + type: string + type: array + isDevelopment: + description: |- + IsDevelopment defines whether to mitigate the unwanted effects of the AllowedHosts, SSL, and STS options when developing. + Usually testing takes place using HTTP, not HTTPS, and on localhost, not your production domain. + If you would like your development environment to mimic production with complete Host blocking, SSL redirects, + and STS headers, leave this as false. + type: boolean + permissionsPolicy: + description: |- + PermissionsPolicy defines the Permissions-Policy header value. + This allows sites to control browser features. + type: string + publicKey: + description: PublicKey is the public key that implements HPKP + to prevent MITM attacks with forged certificates. + type: string + referrerPolicy: + description: |- + ReferrerPolicy defines the Referrer-Policy header value. + This allows sites to control whether browsers forward the Referer header to other sites. + type: string + sslForceHost: + description: 'Deprecated: SSLForceHost option is deprecated, please + use RedirectRegex instead.' + type: boolean + sslHost: + description: 'Deprecated: SSLHost option is deprecated, please + use RedirectRegex instead.' + type: string + sslProxyHeaders: + additionalProperties: + type: string + description: |- + SSLProxyHeaders defines the header keys with associated values that would indicate a valid HTTPS request. + It can be useful when using other proxies (example: "X-Forwarded-Proto": "https"). + type: object + sslRedirect: + description: 'Deprecated: SSLRedirect option is deprecated, please + use EntryPoint redirection or RedirectScheme instead.' + type: boolean + sslTemporaryRedirect: + description: 'Deprecated: SSLTemporaryRedirect option is deprecated, + please use EntryPoint redirection or RedirectScheme instead.' + type: boolean + stsIncludeSubdomains: + description: STSIncludeSubdomains defines whether the includeSubDomains + directive is appended to the Strict-Transport-Security header. + type: boolean + stsPreload: + description: STSPreload defines whether the preload flag is appended + to the Strict-Transport-Security header. + type: boolean + stsSeconds: + description: |- + STSSeconds defines the max-age of the Strict-Transport-Security header. + If set to 0, the header is not set. + format: int64 + type: integer + type: object + inFlightReq: + description: |- + InFlightReq holds the in-flight request middleware configuration. + This middleware limits the number of requests being processed and served concurrently. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/inflightreq/ + properties: + amount: + description: |- + Amount defines the maximum amount of allowed simultaneous in-flight request. + The middleware responds with HTTP 429 Too Many Requests if there are already amount requests in progress (based on the same sourceCriterion strategy). + format: int64 + type: integer + sourceCriterion: + description: |- + SourceCriterion defines what criterion is used to group requests as originating from a common source. + If several strategies are defined at the same time, an error will be raised. + If none are set, the default is to use the requestHost. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/inflightreq/#sourcecriterion + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position + (starting from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the + X-Forwarded-For header and select the first IP not in + the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider + all IPv6 addresses from the defined subnet as originating + from the same IP. Applies to RemoteAddrStrategy and + DepthStrategy. + type: integer + type: object + requestHeaderName: + description: RequestHeaderName defines the name of the header + used to group incoming requests. + type: string + requestHost: + description: RequestHost defines whether to consider the request + Host as the source. + type: boolean + type: object + type: object + ipAllowList: + description: |- + IPAllowList holds the IP allowlist middleware configuration. + This middleware limits allowed requests based on the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/ + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider all + IPv6 addresses from the defined subnet as originating from + the same IP. Applies to RemoteAddrStrategy and DepthStrategy. + type: integer + type: object + rejectStatusCode: + description: |- + RejectStatusCode defines the HTTP status code used for refused requests. + If not set, the default is 403 (Forbidden). + type: integer + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider all + IPv6 addresses from the defined subnet as originating from + the same IP. Applies to RemoteAddrStrategy and DepthStrategy. + type: integer + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). Required. + items: + type: string + type: array + type: object + passTLSClientCert: + description: |- + PassTLSClientCert holds the pass TLS client cert middleware configuration. + This middleware adds the selected data from the passed client TLS certificate to a header. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/passtlsclientcert/ + properties: + info: + description: Info selects the specific client certificate details + you want to add to the X-Forwarded-Tls-Client-Cert-Info header. + properties: + issuer: + description: Issuer defines the client certificate issuer + details to add to the X-Forwarded-Tls-Client-Cert-Info header. + properties: + commonName: + description: CommonName defines whether to add the organizationalUnit + information into the issuer. + type: boolean + country: + description: Country defines whether to add the country + information into the issuer. + type: boolean + domainComponent: + description: DomainComponent defines whether to add the + domainComponent information into the issuer. + type: boolean + locality: + description: Locality defines whether to add the locality + information into the issuer. + type: boolean + organization: + description: Organization defines whether to add the organization + information into the issuer. + type: boolean + province: + description: Province defines whether to add the province + information into the issuer. + type: boolean + serialNumber: + description: SerialNumber defines whether to add the serialNumber + information into the issuer. + type: boolean + type: object + notAfter: + description: NotAfter defines whether to add the Not After + information from the Validity part. + type: boolean + notBefore: + description: NotBefore defines whether to add the Not Before + information from the Validity part. + type: boolean + sans: + description: Sans defines whether to add the Subject Alternative + Name information from the Subject Alternative Name part. + type: boolean + serialNumber: + description: SerialNumber defines whether to add the client + serialNumber information. + type: boolean + subject: + description: Subject defines the client certificate subject + details to add to the X-Forwarded-Tls-Client-Cert-Info header. + properties: + commonName: + description: CommonName defines whether to add the organizationalUnit + information into the subject. + type: boolean + country: + description: Country defines whether to add the country + information into the subject. + type: boolean + domainComponent: + description: DomainComponent defines whether to add the + domainComponent information into the subject. + type: boolean + locality: + description: Locality defines whether to add the locality + information into the subject. + type: boolean + organization: + description: Organization defines whether to add the organization + information into the subject. + type: boolean + organizationalUnit: + description: OrganizationalUnit defines whether to add + the organizationalUnit information into the subject. + type: boolean + province: + description: Province defines whether to add the province + information into the subject. + type: boolean + serialNumber: + description: SerialNumber defines whether to add the serialNumber + information into the subject. + type: boolean + type: object + type: object + pem: + description: PEM sets the X-Forwarded-Tls-Client-Cert header with + the certificate. + type: boolean + type: object + plugin: + additionalProperties: + x-kubernetes-preserve-unknown-fields: true + description: |- + Plugin defines the middleware plugin configuration. + More info: https://doc.traefik.io/traefik/plugins/ + type: object + rateLimit: + description: |- + RateLimit holds the rate limit configuration. + This middleware ensures that services will receive a fair amount of requests, and allows one to define what fair is. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ratelimit/ + properties: + average: + description: |- + Average is the maximum rate, by default in requests/s, allowed for the given source. + It defaults to 0, which means no rate limiting. + The rate is actually defined by dividing Average by Period. So for a rate below 1req/s, + one needs to define a Period larger than a second. + format: int64 + type: integer + burst: + description: |- + Burst is the maximum number of requests allowed to arrive in the same arbitrarily small period of time. + It defaults to 1. + format: int64 + type: integer + period: + anyOf: + - type: integer + - type: string + description: |- + Period, in combination with Average, defines the actual maximum rate, such as: + r = Average / Period. It defaults to a second. + x-kubernetes-int-or-string: true + sourceCriterion: + description: |- + SourceCriterion defines what criterion is used to group requests as originating from a common source. + If several strategies are defined at the same time, an error will be raised. + If none are set, the default is to use the request's remote address field (as an ipStrategy). + properties: + ipStrategy: + description: |- + IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/ipallowlist/#ipstrategy + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position + (starting from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the + X-Forwarded-For header and select the first IP not in + the list. + items: + type: string + type: array + ipv6Subnet: + description: IPv6Subnet configures Traefik to consider + all IPv6 addresses from the defined subnet as originating + from the same IP. Applies to RemoteAddrStrategy and + DepthStrategy. + type: integer + type: object + requestHeaderName: + description: RequestHeaderName defines the name of the header + used to group incoming requests. + type: string + requestHost: + description: RequestHost defines whether to consider the request + Host as the source. + type: boolean + type: object + type: object + redirectRegex: + description: |- + RedirectRegex holds the redirect regex middleware configuration. + This middleware redirects a request using regex matching and replacement. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/redirectregex/#regex + properties: + permanent: + description: Permanent defines whether the redirection is permanent + (301). + type: boolean + regex: + description: Regex defines the regex used to match and capture + elements from the request URL. + type: string + replacement: + description: Replacement defines how to modify the URL to have + the new target URL. + type: string + type: object + redirectScheme: + description: |- + RedirectScheme holds the redirect scheme middleware configuration. + This middleware redirects requests from a scheme/port to another. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/redirectscheme/ + properties: + permanent: + description: Permanent defines whether the redirection is permanent + (301). + type: boolean + port: + description: Port defines the port of the new URL. + type: string + scheme: + description: Scheme defines the scheme of the new URL. + type: string + type: object + replacePath: + description: |- + ReplacePath holds the replace path middleware configuration. + This middleware replaces the path of the request URL and store the original path in an X-Replaced-Path header. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/replacepath/ + properties: + path: + description: Path defines the path to use as replacement in the + request URL. + type: string + type: object + replacePathRegex: + description: |- + ReplacePathRegex holds the replace path regex middleware configuration. + This middleware replaces the path of a URL using regex matching and replacement. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/replacepathregex/ + properties: + regex: + description: Regex defines the regular expression used to match + and capture the path from the request URL. + type: string + replacement: + description: Replacement defines the replacement path format, + which can include captured variables. + type: string + type: object + retry: + description: |- + Retry holds the retry middleware configuration. + This middleware reissues requests a given number of times to a backend server if that server does not reply. + As soon as the server answers, the middleware stops retrying, regardless of the response status. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/retry/ + properties: + attempts: + description: Attempts defines how many times the request should + be retried. + type: integer + initialInterval: + anyOf: + - type: integer + - type: string + description: |- + InitialInterval defines the first wait time in the exponential backoff series. + The maximum interval is calculated as twice the initialInterval. + If unspecified, requests will be retried immediately. + The value of initialInterval should be provided in seconds or as a valid duration format, + see https://pkg.go.dev/time#ParseDuration. + x-kubernetes-int-or-string: true + type: object + stripPrefix: + description: |- + StripPrefix holds the strip prefix middleware configuration. + This middleware removes the specified prefixes from the URL path. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/stripprefix/ + properties: + forceSlash: + description: |- + Deprecated: ForceSlash option is deprecated, please remove any usage of this option. + ForceSlash ensures that the resulting stripped path is not the empty string, by replacing it with / when necessary. + Default: true. + type: boolean + prefixes: + description: Prefixes defines the prefixes to strip from the request + URL. + items: + type: string + type: array + type: object + stripPrefixRegex: + description: |- + StripPrefixRegex holds the strip prefix regex middleware configuration. + This middleware removes the matching prefixes from the URL path. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/stripprefixregex/ + properties: + regex: + description: Regex defines the regular expression to match the + path prefix from the request URL. + items: + type: string + type: array + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_middlewaretcps.yaml b/utils/assets/charts/traefik/crds/traefik.io_middlewaretcps.yaml new file mode 100644 index 0000000..fc23e11 --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_middlewaretcps.yaml @@ -0,0 +1,87 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: middlewaretcps.traefik.io +spec: + group: traefik.io + names: + kind: MiddlewareTCP + listKind: MiddlewareTCPList + plural: middlewaretcps + singular: middlewaretcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/overview/ + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: MiddlewareTCPSpec defines the desired state of a MiddlewareTCP. + properties: + inFlightConn: + description: InFlightConn defines the InFlightConn middleware configuration. + properties: + amount: + description: |- + Amount defines the maximum amount of allowed simultaneous connections. + The middleware closes the connection if there are already amount connections opened. + format: int64 + type: integer + type: object + ipAllowList: + description: |- + IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client IP. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/tcp/ipallowlist/ + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: |- + IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client IP. + Deprecated: please use IPAllowList instead. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/tcp/ipwhitelist/ + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_serverstransports.yaml b/utils/assets/charts/traefik/crds/traefik.io_serverstransports.yaml new file mode 100644 index 0000000..fe2f129 --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_serverstransports.yaml @@ -0,0 +1,139 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: serverstransports.traefik.io +spec: + group: traefik.io + names: + kind: ServersTransport + listKind: ServersTransportList + plural: serverstransports + singular: serverstransport + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ServersTransport is the CRD implementation of a ServersTransport. + If no serversTransport is specified, the default@internal will be used. + The default@internal serversTransport is created from the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#serverstransport_1 + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ServersTransportSpec defines the desired state of a ServersTransport. + properties: + certificatesSecrets: + description: CertificatesSecrets defines a list of secret storing + client certificates for mTLS. + items: + type: string + type: array + disableHTTP2: + description: DisableHTTP2 disables HTTP/2 for connections with backend + servers. + type: boolean + forwardingTimeouts: + description: ForwardingTimeouts defines the timeouts for requests + forwarded to the backend servers. + properties: + dialTimeout: + anyOf: + - type: integer + - type: string + description: DialTimeout is the amount of time to wait until a + connection to a backend server can be established. + x-kubernetes-int-or-string: true + idleConnTimeout: + anyOf: + - type: integer + - type: string + description: IdleConnTimeout is the maximum period for which an + idle HTTP keep-alive connection will remain open before closing + itself. + x-kubernetes-int-or-string: true + pingTimeout: + anyOf: + - type: integer + - type: string + description: PingTimeout is the timeout after which the HTTP/2 + connection will be closed if a response to ping is not received. + x-kubernetes-int-or-string: true + readIdleTimeout: + anyOf: + - type: integer + - type: string + description: ReadIdleTimeout is the timeout after which a health + check using ping frame will be carried out if no frame is received + on the HTTP/2 connection. + x-kubernetes-int-or-string: true + responseHeaderTimeout: + anyOf: + - type: integer + - type: string + description: ResponseHeaderTimeout is the amount of time to wait + for a server's response headers after fully writing the request + (including its body, if any). + x-kubernetes-int-or-string: true + type: object + insecureSkipVerify: + description: InsecureSkipVerify disables SSL certificate verification. + type: boolean + maxIdleConnsPerHost: + description: MaxIdleConnsPerHost controls the maximum idle (keep-alive) + to keep per-host. + type: integer + peerCertURI: + description: PeerCertURI defines the peer cert URI used to match against + SAN URI during the peer certificate verification. + type: string + rootCAsSecrets: + description: RootCAsSecrets defines a list of CA secret used to validate + self-signed certificate. + items: + type: string + type: array + serverName: + description: ServerName defines the server name used to contact the + server. + type: string + spiffe: + description: Spiffe defines the SPIFFE configuration. + properties: + ids: + description: IDs defines the allowed SPIFFE IDs (takes precedence + over the SPIFFE TrustDomain). + items: + type: string + type: array + trustDomain: + description: TrustDomain defines the allowed SPIFFE trust domain. + type: string + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_serverstransporttcps.yaml b/utils/assets/charts/traefik/crds/traefik.io_serverstransporttcps.yaml new file mode 100644 index 0000000..2f24c84 --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_serverstransporttcps.yaml @@ -0,0 +1,120 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: serverstransporttcps.traefik.io +spec: + group: traefik.io + names: + kind: ServersTransportTCP + listKind: ServersTransportTCPList + plural: serverstransporttcps + singular: serverstransporttcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ServersTransportTCP is the CRD implementation of a TCPServersTransport. + If no tcpServersTransport is specified, a default one named default@internal will be used. + The default@internal tcpServersTransport can be configured in the static configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#serverstransport_3 + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ServersTransportTCPSpec defines the desired state of a ServersTransportTCP. + properties: + dialKeepAlive: + anyOf: + - type: integer + - type: string + description: DialKeepAlive is the interval between keep-alive probes + for an active network connection. If zero, keep-alive probes are + sent with a default value (currently 15 seconds), if supported by + the protocol and operating system. Network protocols or operating + systems that do not support keep-alives ignore this field. If negative, + keep-alive probes are disabled. + x-kubernetes-int-or-string: true + dialTimeout: + anyOf: + - type: integer + - type: string + description: DialTimeout is the amount of time to wait until a connection + to a backend server can be established. + x-kubernetes-int-or-string: true + terminationDelay: + anyOf: + - type: integer + - type: string + description: TerminationDelay defines the delay to wait before fully + terminating the connection, after one connected peer has closed + its writing capability. + x-kubernetes-int-or-string: true + tls: + description: TLS defines the TLS configuration + properties: + certificatesSecrets: + description: CertificatesSecrets defines a list of secret storing + client certificates for mTLS. + items: + type: string + type: array + insecureSkipVerify: + description: InsecureSkipVerify disables TLS certificate verification. + type: boolean + peerCertURI: + description: |- + MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host. + PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + type: string + rootCAsSecrets: + description: RootCAsSecrets defines a list of CA secret used to + validate self-signed certificates. + items: + type: string + type: array + serverName: + description: ServerName defines the server name used to contact + the server. + type: string + spiffe: + description: Spiffe defines the SPIFFE configuration. + properties: + ids: + description: IDs defines the allowed SPIFFE IDs (takes precedence + over the SPIFFE TrustDomain). + items: + type: string + type: array + trustDomain: + description: TrustDomain defines the allowed SPIFFE trust + domain. + type: string + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_tlsoptions.yaml b/utils/assets/charts/traefik/crds/traefik.io_tlsoptions.yaml new file mode 100644 index 0000000..498fc3c --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_tlsoptions.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: tlsoptions.traefik.io +spec: + group: traefik.io + names: + kind: TLSOption + listKind: TLSOptionList + plural: tlsoptions + singular: tlsoption + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#tls-options + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TLSOptionSpec defines the desired state of a TLSOption. + properties: + alpnProtocols: + description: |- + ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#alpn-protocols + items: + type: string + type: array + cipherSuites: + description: |- + CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#cipher-suites + items: + type: string + type: array + clientAuth: + description: ClientAuth defines the server's policy for TLS Client + Authentication. + properties: + clientAuthType: + description: ClientAuthType defines the client authentication + type to apply. + enum: + - NoClientCert + - RequestClientCert + - RequireAnyClientCert + - VerifyClientCertIfGiven + - RequireAndVerifyClientCert + type: string + secretNames: + description: SecretNames defines the names of the referenced Kubernetes + Secret storing certificate details. + items: + type: string + type: array + type: object + curvePreferences: + description: |- + CurvePreferences defines the preferred elliptic curves in a specific order. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#curve-preferences + items: + type: string + type: array + maxVersion: + description: |- + MaxVersion defines the maximum TLS version that Traefik will accept. + Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + Default: None. + type: string + minVersion: + description: |- + MinVersion defines the minimum TLS version that Traefik will accept. + Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + Default: VersionTLS10. + type: string + preferServerCipherSuites: + description: |- + PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's. + It is enabled automatically when minVersion or maxVersion is set. + Deprecated: https://github.com/golang/go/issues/45430 + type: boolean + sniStrict: + description: SniStrict defines whether Traefik allows connections + from clients connections that do not specify a server_name extension. + type: boolean + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_tlsstores.yaml b/utils/assets/charts/traefik/crds/traefik.io_tlsstores.yaml new file mode 100644 index 0000000..7eacb77 --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_tlsstores.yaml @@ -0,0 +1,97 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: tlsstores.traefik.io +spec: + group: traefik.io + names: + kind: TLSStore + listKind: TLSStoreList + plural: tlsstores + singular: tlsstore + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TLSStore is the CRD implementation of a Traefik TLS Store. + For the time being, only the TLSStore named default is supported. + This means that you cannot have two stores that are named default in different Kubernetes namespaces. + More info: https://doc.traefik.io/traefik/v3.2/https/tls/#certificates-stores + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TLSStoreSpec defines the desired state of a TLSStore. + properties: + certificates: + description: Certificates is a list of secret names, each secret holding + a key/certificate pair to add to the store. + items: + description: Certificate holds a secret name for the TLSStore resource. + properties: + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + required: + - secretName + type: object + type: array + defaultCertificate: + description: DefaultCertificate defines the default certificate configuration. + properties: + secretName: + description: SecretName is the name of the referenced Kubernetes + Secret to specify the certificate details. + type: string + required: + - secretName + type: object + defaultGeneratedCert: + description: DefaultGeneratedCert defines the default generated certificate + configuration. + properties: + domain: + description: Domain is the domain definition for the DefaultCertificate. + properties: + main: + description: Main defines the main domain name. + type: string + sans: + description: SANs defines the subject alternative domain names. + items: + type: string + type: array + type: object + resolver: + description: Resolver is the name of the resolver that will be + used to issue the DefaultCertificate. + type: string + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/crds/traefik.io_traefikservices.yaml b/utils/assets/charts/traefik/crds/traefik.io_traefikservices.yaml new file mode 100644 index 0000000..01e28fc --- /dev/null +++ b/utils/assets/charts/traefik/crds/traefik.io_traefikservices.yaml @@ -0,0 +1,644 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: traefikservices.traefik.io +spec: + group: traefik.io + names: + kind: TraefikService + listKind: TraefikServiceList + plural: traefikservices + singular: traefikservice + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + TraefikService is the CRD implementation of a Traefik Service. + TraefikService object allows to: + - Apply weight to Services on load-balancing + - Mirror traffic on services + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#kind-traefikservice + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TraefikServiceSpec defines the desired state of a TraefikService. + properties: + mirroring: + description: Mirroring defines the Mirroring service configuration. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent to + the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname in the + Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the health + check endpoint. + type: string + port: + description: Port defines the server URL port for the health + check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for the + health check endpoint. + type: string + status: + description: Status defines the expected HTTP status code + of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + maxBodySize: + description: |- + MaxBodySize defines the maximum size allowed for the body of the request. + If the body is larger, the request is not mirrored. + Default value is -1, which means unlimited size. + format: int64 + type: integer + mirrorBody: + description: |- + MirrorBody defines whether the body of the request should be mirrored. + Default value is true. + type: boolean + mirrors: + description: Mirrors defines the list of mirrors where Traefik + will duplicate the traffic. + items: + description: MirrorService holds the mirror configuration. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent + to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname + in the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the + health check endpoint. + type: string + port: + description: Port defines the server URL port for the + health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for + the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status + code of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + percent: + description: |- + Percent defines the part of the traffic to mirror. + Supported values: 0 to 100. + type: integer + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to the + client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie + can be accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can + only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + type: array + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards the + response from the upstream Kubernetes Service to the client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie can be + accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can only + be transmitted over an encrypted connection (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + weighted: + description: Weighted defines the Weighted Round Robin configuration. + properties: + services: + description: Services defines the list of Kubernetes Service and/or + TraefikService to load-balance, with weight. + items: + description: Service defines an upstream HTTP service to proxy + traffic to. + properties: + healthCheck: + description: Healthcheck defines health checks for ExternalName + services. + properties: + followRedirects: + description: |- + FollowRedirects defines whether redirects should be followed during the health check calls. + Default: true + type: boolean + headers: + additionalProperties: + type: string + description: Headers defines custom headers to be sent + to the health check endpoint. + type: object + hostname: + description: Hostname defines the value of hostname + in the Host header of the health check request. + type: string + interval: + anyOf: + - type: integer + - type: string + description: |- + Interval defines the frequency of the health check calls. + Default: 30s + x-kubernetes-int-or-string: true + method: + description: Method defines the healthcheck method. + type: string + mode: + description: |- + Mode defines the health check mode. + If defined to grpc, will use the gRPC health check protocol to probe the server. + Default: http + type: string + path: + description: Path defines the server URL path for the + health check endpoint. + type: string + port: + description: Port defines the server URL port for the + health check endpoint. + type: integer + scheme: + description: Scheme replaces the server URL scheme for + the health check endpoint. + type: string + status: + description: Status defines the expected HTTP status + code of the response to the health check request. + type: integer + timeout: + anyOf: + - type: integer + - type: string + description: |- + Timeout defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy. + Default: 5s + x-kubernetes-int-or-string: true + type: object + kind: + description: Kind defines the kind of the Service. + enum: + - Service + - TraefikService + type: string + name: + description: |- + Name defines the name of the referenced Kubernetes Service or TraefikService. + The differentiation between the two is specified in the Kind field. + type: string + namespace: + description: Namespace defines the namespace of the referenced + Kubernetes Service or TraefikService. + type: string + nativeLB: + description: |- + NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean + nodePortLB: + description: |- + NodePortLB controls, when creating the load-balancer, + whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort. + It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes. + By default, NodePortLB is false. + type: boolean + passHostHeader: + description: |- + PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. + By default, passHostHeader is true. + type: boolean + port: + anyOf: + - type: integer + - type: string + description: |- + Port defines the port of a Kubernetes Service. + This can be a reference to a named port. + x-kubernetes-int-or-string: true + responseForwarding: + description: ResponseForwarding defines how Traefik forwards + the response from the upstream Kubernetes Service to the + client. + properties: + flushInterval: + description: |- + FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body. + A negative value means to flush immediately after each write to the client. + This configuration is ignored when ReverseProxy recognizes a response as a streaming response; + for such responses, writes are flushed to the client immediately. + Default: 100ms + type: string + type: object + scheme: + description: |- + Scheme defines the scheme to use for the request to the upstream Kubernetes Service. + It defaults to https when Kubernetes Service port is 443, http otherwise. + type: string + serversTransport: + description: |- + ServersTransport defines the name of ServersTransport resource to use. + It allows to configure the transport between Traefik and your servers. + Can only be used on a Kubernetes Service. + type: string + sticky: + description: |- + Sticky defines the sticky sessions configuration. + More info: https://doc.traefik.io/traefik/v3.2/routing/services/#sticky-sessions + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie + can be accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can + only be transmitted over an encrypted connection + (i.e. HTTPS). + type: boolean + type: object + type: object + strategy: + description: |- + Strategy defines the load balancing strategy between the servers. + RoundRobin is the only supported value at the moment. + type: string + weight: + description: |- + Weight defines the weight and should only be specified when Name references a TraefikService object + (and to be precise, one that embeds a Weighted Round Robin). + type: integer + required: + - name + type: object + type: array + sticky: + description: |- + Sticky defines whether sticky sessions are enabled. + More info: https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-crd/#stickiness-and-load-balancing + properties: + cookie: + description: Cookie defines the sticky cookie configuration. + properties: + httpOnly: + description: HTTPOnly defines whether the cookie can be + accessed by client-side APIs, such as JavaScript. + type: boolean + maxAge: + description: |- + MaxAge indicates the number of seconds until the cookie expires. + When set to a negative number, the cookie expires immediately. + When set to zero, the cookie never expires. + type: integer + name: + description: Name defines the Cookie name. + type: string + sameSite: + description: |- + SameSite defines the same site policy. + More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + type: string + secure: + description: Secure defines whether the cookie can only + be transmitted over an encrypted connection (i.e. HTTPS). + type: boolean + type: object + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true diff --git a/utils/assets/charts/traefik/templates/NOTES.txt b/utils/assets/charts/traefik/templates/NOTES.txt new file mode 100644 index 0000000..a1a10bf --- /dev/null +++ b/utils/assets/charts/traefik/templates/NOTES.txt @@ -0,0 +1,36 @@ + + +{{ .Release.Name }} with {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }} has been deployed successfully on {{ template "traefik.namespace" . }} namespace ! + +{{- if .Values.persistence }} +{{- if and .Values.persistence.enabled (empty .Values.deployment.initContainer)}} + +🚨 When enabling persistence for certificates, permissions on acme.json can be +lost when Traefik restarts. You can ensure correct permissions with an +initContainer. See https://github.com/traefik/traefik-helm-chart/blob/master/EXAMPLES.md#use-traefik-native-lets-encrypt-integration-without-cert-manager +for more info. 🚨 + +{{- end }} +{{- end }} +{{- with .Values.providers.kubernetesCRD.labelSelector }} + {{- $labelsApplied := include "traefik.labels" $ }} + {{- $labelSelectors := regexSplit "," . -1 }} + {{- range $labelSelectors }} + {{- $labelSelectorRaw := regexSplit "=" . -1 }} + {{- $labelSelector := printf "%s: %s" (first $labelSelectorRaw) (last $labelSelectorRaw) }} + {{- if not (contains $labelSelector $labelsApplied) }} +🚨 Resources populated with this chart don't match with labelSelector `{{.}}` applied on kubernetesCRD provider 🚨 + {{- end }} + {{- end }} +{{- end }} +{{- with .Values.providers.kubernetesIngress.labelSelector }} + {{- $labelsApplied := include "traefik.labels" $ }} + {{- $labelSelectors := regexSplit "," . -1 }} + {{- range $labelSelectors }} + {{- $labelSelectorRaw := regexSplit "=" . -1 }} + {{- $labelSelector := printf "%s: %s" (first $labelSelectorRaw) (last $labelSelectorRaw) }} + {{- if not (contains $labelSelector $labelsApplied) }} +🚨 Resources populated with this chart don't match with labelSelector `{{.}}` applied on kubernetesIngress provider 🚨 + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/traefik/templates/_helpers.tpl b/utils/assets/charts/traefik/templates/_helpers.tpl new file mode 100644 index 0000000..284e912 --- /dev/null +++ b/utils/assets/charts/traefik/templates/_helpers.tpl @@ -0,0 +1,178 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "traefik.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "traefik.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the chart image name. +*/}} +{{- define "traefik.image-name" -}} +{{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository (.Values.image.tag | default .Chart.AppVersion) }} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "traefik.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow customization of the instance label value. +*/}} +{{- define "traefik.instance-name" -}} +{{- default (printf "%s-%s" .Release.Name .Release.Namespace) .Values.instanceLabelOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Shared labels used for selector*/}} +{{/* This is an immutable field: this should not change between upgrade */}} +{{- define "traefik.labelselector" -}} +app.kubernetes.io/name: {{ template "traefik.name" . }} +app.kubernetes.io/instance: {{ template "traefik.instance-name" . }} +{{- end }} + +{{/* Shared labels used in metada */}} +{{- define "traefik.labels" -}} +{{ include "traefik.labelselector" . }} +helm.sh/chart: {{ template "traefik.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Construct the namespace for all namespaced resources +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +Preserve the default behavior of the Release namespace if no override is provided +*/}} +{{- define "traefik.namespace" -}} +{{- if .Values.namespaceOverride -}} +{{- .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- .Release.Namespace -}} +{{- end -}} +{{- end -}} + +{{/* +The name of the service account to use +*/}} +{{- define "traefik.serviceAccountName" -}} +{{- default (include "traefik.fullname" .) .Values.serviceAccount.name -}} +{{- end -}} + +{{/* +The name of the ClusterRole and ClusterRoleBinding to use. +Adds the namespace to name to prevent duplicate resource names when there +are multiple namespaced releases with the same release name. +*/}} +{{- define "traefik.clusterRoleName" -}} +{{- (printf "%s-%s" (include "traefik.fullname" .) .Release.Namespace) | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Construct the path for the providers.kubernetesingress.ingressendpoint.publishedservice. +By convention this will simply use the / to match the name of the +service generated. +Users can provide an override for an explicit service they want bound via `.Values.providers.kubernetesIngress.publishedService.pathOverride` +*/}} +{{- define "providers.kubernetesIngress.publishedServicePath" -}} +{{- $defServiceName := printf "%s/%s" .Release.Namespace (include "traefik.fullname" .) -}} +{{- $servicePath := default $defServiceName .Values.providers.kubernetesIngress.publishedService.pathOverride }} +{{- print $servicePath | trimSuffix "-" -}} +{{- end -}} + +{{/* +Construct a comma-separated list of whitelisted namespaces +*/}} +{{- define "providers.kubernetesCRD.namespaces" -}} +{{- default (include "traefik.namespace" .) (join "," .Values.providers.kubernetesCRD.namespaces) }} +{{- end -}} +{{- define "providers.kubernetesGateway.namespaces" -}} +{{- default (include "traefik.namespace" .) (join "," .Values.providers.kubernetesGateway.namespaces) }} +{{- end -}} +{{- define "providers.kubernetesIngress.namespaces" -}} +{{- default (include "traefik.namespace" .) (join "," .Values.providers.kubernetesIngress.namespaces) }} +{{- end -}} + +{{/* +Renders a complete tree, even values that contains template. +*/}} +{{- define "traefik.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{ else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} + +{{- define "imageVersion" -}} +{{/* +Traefik hub is based on v3.1 (v3.0 before v3.3.1) of traefik proxy, so this is a hack to avoid to much complexity in RBAC management which are +based on semverCompare +*/}} +{{- if $.Values.hub.token -}} +{{ if and (regexMatch "v[0-9]+.[0-9]+.[0-9]+" (default "" $.Values.image.tag)) (semverCompare "=3.1.2-0" $version) }} + - "--providers.kubernetescrd.disableClusterScopeResources=true" + {{- end }} + {{- if .Values.providers.kubernetesCRD.nativeLBByDefault }} + - "--providers.kubernetescrd.nativeLBByDefault=true" + {{- end }} + {{- end }} + {{- if .Values.providers.kubernetesIngress.enabled }} + - "--providers.kubernetesingress" + {{- if .Values.providers.kubernetesIngress.allowExternalNameServices }} + - "--providers.kubernetesingress.allowExternalNameServices=true" + {{- end }} + {{- if .Values.providers.kubernetesIngress.allowEmptyServices }} + - "--providers.kubernetesingress.allowEmptyServices=true" + {{- end }} + {{- if and .Values.service.enabled .Values.providers.kubernetesIngress.publishedService.enabled }} + - "--providers.kubernetesingress.ingressendpoint.publishedservice={{ template "providers.kubernetesIngress.publishedServicePath" . }}" + {{- end }} + {{- if .Values.providers.kubernetesIngress.labelSelector }} + - "--providers.kubernetesingress.labelSelector={{ .Values.providers.kubernetesIngress.labelSelector }}" + {{- end }} + {{- if .Values.providers.kubernetesIngress.ingressClass }} + - "--providers.kubernetesingress.ingressClass={{ .Values.providers.kubernetesIngress.ingressClass }}" + {{- end }} + {{- if .Values.rbac.namespaced }} + {{- if semverCompare "<3.1.5-0" $version }} + - "--providers.kubernetesingress.disableIngressClassLookup=true" + {{- if semverCompare ">=3.1.2-0" $version }} + - "--providers.kubernetesingress.disableClusterScopeResources=true" + {{- end }} + {{- else }} + - "--providers.kubernetesingress.disableClusterScopeResources=true" + {{- end }} + {{- end }} + {{- if .Values.providers.kubernetesIngress.nativeLBByDefault }} + - "--providers.kubernetesingress.nativeLBByDefault=true" + {{- end }} + {{- end }} + {{- if .Values.experimental.kubernetesGateway.enabled }} + - "--experimental.kubernetesgateway" + {{- end }} + {{- with .Values.providers.kubernetesCRD }} + {{- if (and .enabled (or .namespaces (and $.Values.rbac.enabled $.Values.rbac.namespaced))) }} + - "--providers.kubernetescrd.namespaces={{ template "providers.kubernetesCRD.namespaces" $ }}" + {{- end }} + {{- end }} + {{- with .Values.providers.kubernetesGateway }} + {{- if .enabled }} + - "--providers.kubernetesgateway" + {{- with .statusAddress }} + {{- with .ip }} + - "--providers.kubernetesgateway.statusaddress.ip={{ . }}" + {{- end }} + {{- with .hostname }} + - "--providers.kubernetesgateway.statusaddress.hostname={{ . }}" + {{- end }} + {{- with .service }} + - "--providers.kubernetesgateway.statusaddress.service.name={{ tpl .name $ }}" + - "--providers.kubernetesgateway.statusaddress.service.namespace={{ tpl .namespace $ }}" + {{- end }} + {{- end }} + {{- if or .namespaces (and $.Values.rbac.enabled $.Values.rbac.namespaced) }} + - "--providers.kubernetesgateway.namespaces={{ template "providers.kubernetesGateway.namespaces" $ }}" + {{- end }} + {{- if .experimentalChannel }} + - "--providers.kubernetesgateway.experimentalchannel=true" + {{- end }} + {{- with .labelselector }} + - "--providers.kubernetesgateway.labelselector={{ . }}" + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.providers.kubernetesIngress }} + {{- if (and .enabled (or .namespaces (and $.Values.rbac.enabled $.Values.rbac.namespaced))) }} + - "--providers.kubernetesingress.namespaces={{ template "providers.kubernetesIngress.namespaces" $ }}" + {{- end }} + {{- end }} + {{- with .Values.providers.file }} + {{- if .enabled }} + - "--providers.file.directory=/etc/traefik/dynamic" + {{- if .watch }} + - "--providers.file.watch=true" + {{- end }} + {{- end }} + {{- end }} + {{- range $entrypoint, $config := $.Values.ports }} + {{- if $config }} + {{- if $config.redirectTo }} + {{- $toPort := index $.Values.ports $config.redirectTo.port }} + - "--entryPoints.{{ $entrypoint }}.http.redirections.entryPoint.to=:{{ $toPort.exposedPort }}" + - "--entryPoints.{{ $entrypoint }}.http.redirections.entryPoint.scheme=https" + {{- if $config.redirectTo.priority }} + - "--entryPoints.{{ $entrypoint }}.http.redirections.entryPoint.priority={{ $config.redirectTo.priority }}" + {{- end }} + {{- if $config.redirectTo.permanent }} + - "--entryPoints.{{ $entrypoint }}.http.redirections.entryPoint.permanent=true" + {{- end }} + {{- end }} + {{- if $config.middlewares }} + - "--entryPoints.{{ $entrypoint }}.http.middlewares={{ join "," $config.middlewares }}" + {{- end }} + {{- if $config.tls }} + {{- if $config.tls.enabled }} + - "--entryPoints.{{ $entrypoint }}.http.tls=true" + {{- if $config.tls.options }} + - "--entryPoints.{{ $entrypoint }}.http.tls.options={{ $config.tls.options }}" + {{- end }} + {{- if $config.tls.certResolver }} + - "--entryPoints.{{ $entrypoint }}.http.tls.certResolver={{ $config.tls.certResolver }}" + {{- end }} + {{- if $config.tls.domains }} + {{- range $index, $domain := $config.tls.domains }} + {{- if $domain.main }} + - "--entryPoints.{{ $entrypoint }}.http.tls.domains[{{ $index }}].main={{ $domain.main }}" + {{- end }} + {{- if $domain.sans }} + - "--entryPoints.{{ $entrypoint }}.http.tls.domains[{{ $index }}].sans={{ join "," $domain.sans }}" + {{- end }} + {{- end }} + {{- end }} + {{- if $config.http3 }} + {{- if $config.http3.enabled }} + - "--entryPoints.{{ $entrypoint }}.http3" + {{- if $config.http3.advertisedPort }} + - "--entryPoints.{{ $entrypoint }}.http3.advertisedPort={{ $config.http3.advertisedPort }}" + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if $config.allowACMEByPass }} + {{- if (semverCompare "<3.1.3-0" $version) }} + {{- fail "ERROR: allowACMEByPass has been introduced with Traefik v3.1.3+" -}} + {{- end }} + - "--entryPoints.name.allowACMEByPass=true" + {{- end }} + {{- if $config.forwardedHeaders }} + {{- if $config.forwardedHeaders.trustedIPs }} + - "--entryPoints.{{ $entrypoint }}.forwardedHeaders.trustedIPs={{ join "," $config.forwardedHeaders.trustedIPs }}" + {{- end }} + {{- if $config.forwardedHeaders.insecure }} + - "--entryPoints.{{ $entrypoint }}.forwardedHeaders.insecure" + {{- end }} + {{- end }} + {{- if $config.proxyProtocol }} + {{- if $config.proxyProtocol.trustedIPs }} + - "--entryPoints.{{ $entrypoint }}.proxyProtocol.trustedIPs={{ join "," $config.proxyProtocol.trustedIPs }}" + {{- end }} + {{- if $config.proxyProtocol.insecure }} + - "--entryPoints.{{ $entrypoint }}.proxyProtocol.insecure" + {{- end }} + {{- end }} + {{- with $config.transport }} + {{- with .respondingTimeouts }} + {{- if and (ne .readTimeout nil) (toString .readTimeout) }} + - "--entryPoints.{{ $entrypoint }}.transport.respondingTimeouts.readTimeout={{ .readTimeout }}" + {{- end }} + {{- if and (ne .writeTimeout nil) (toString .writeTimeout) }} + - "--entryPoints.{{ $entrypoint }}.transport.respondingTimeouts.writeTimeout={{ .writeTimeout }}" + {{- end }} + {{- if and (ne .idleTimeout nil) (toString .idleTimeout) }} + - "--entryPoints.{{ $entrypoint }}.transport.respondingTimeouts.idleTimeout={{ .idleTimeout }}" + {{- end }} + {{- end }} + {{- with .lifeCycle }} + {{- if and (ne .requestAcceptGraceTimeout nil) (toString .requestAcceptGraceTimeout) }} + - "--entryPoints.{{ $entrypoint }}.transport.lifeCycle.requestAcceptGraceTimeout={{ .requestAcceptGraceTimeout }}" + {{- end }} + {{- if and (ne .graceTimeOut nil) (toString .graceTimeOut) }} + - "--entryPoints.{{ $entrypoint }}.transport.lifeCycle.graceTimeOut={{ .graceTimeOut }}" + {{- end }} + {{- end }} + {{- if and (ne .keepAliveMaxRequests nil) (toString .keepAliveMaxRequests) }} + - "--entryPoints.{{ $entrypoint }}.transport.keepAliveMaxRequests={{ .keepAliveMaxRequests }}" + {{- end }} + {{- if and (ne .keepAliveMaxTime nil) (toString .keepAliveMaxTime) }} + - "--entryPoints.{{ $entrypoint }}.transport.keepAliveMaxTime={{ .keepAliveMaxTime }}" + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.logs }} + {{- if and .general.format (not (has .general.format (list "common" "json"))) }} + {{- fail "ERROR: .Values.logs.general.format must be either common or json" }} + {{- end }} + {{- with .general.format }} + - "--log.format={{ . }}" + {{- end }} + {{- with .general.filePath }} + - "--log.filePath={{ . }}" + {{- end }} + {{- if and (or (eq .general.format "common") (not .general.format)) (eq .general.noColor true) }} + - "--log.noColor={{ .general.noColor }}" + {{- end }} + {{- with .general.level }} + - "--log.level={{ . | upper }}" + {{- end }} + {{- if .access.enabled }} + - "--accesslog=true" + {{- with .access.format }} + - "--accesslog.format={{ . }}" + {{- end }} + {{- with .access.filePath }} + - "--accesslog.filepath={{ . }}" + {{- end }} + {{- if .access.addInternals }} + - "--accesslog.addinternals" + {{- end }} + {{- with .access.bufferingSize }} + - "--accesslog.bufferingsize={{ . }}" + {{- end }} + {{- with .access.filters }} + {{- with .statuscodes }} + - "--accesslog.filters.statuscodes={{ . }}" + {{- end }} + {{- if .retryattempts }} + - "--accesslog.filters.retryattempts" + {{- end }} + {{- with .minduration }} + - "--accesslog.filters.minduration={{ . }}" + {{- end }} + {{- end }} + - "--accesslog.fields.defaultmode={{ .access.fields.general.defaultmode }}" + {{- range $fieldname, $fieldaction := .access.fields.general.names }} + - "--accesslog.fields.names.{{ $fieldname }}={{ $fieldaction }}" + {{- end }} + - "--accesslog.fields.headers.defaultmode={{ .access.fields.headers.defaultmode }}" + {{- range $fieldname, $fieldaction := .access.fields.headers.names }} + - "--accesslog.fields.headers.names.{{ $fieldname }}={{ $fieldaction }}" + {{- end }} + {{- end }} + {{- end }} + {{- include "traefik.yaml2CommandLineArgs" (dict "path" "certificatesresolvers" "content" $.Values.certificatesResolvers) | nindent 10 }} + {{- with .Values.additionalArguments }} + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- with .Values.hub }} + {{- if .token }} + - "--hub.token=$(HUB_TOKEN)" + {{- if and (not .apimanagement.enabled) ($.Values.hub.apimanagement.admission.listenAddr) }} + {{- fail "ERROR: Cannot configure admission without enabling hub.apimanagement" }} + {{- end }} + {{- with .apimanagement }} + {{- if .enabled }} + {{- $listenAddr := default ":9943" .admission.listenAddr }} + - "--hub.apimanagement" + - "--hub.apimanagement.admission.listenAddr={{ $listenAddr }}" + {{- with .admission.secretName }} + - "--hub.apimanagement.admission.secretName={{ . }}" + {{- end }} + {{- end }} + {{- end }} + {{- with .platformUrl }} + - "--hub.platformUrl={{ . }}" + {{- end -}} + {{- range $field, $value := .redis }} + {{- if has $field (list "cluster" "database" "endpoints" "username" "password" "timeout") -}} + {{- with $value }} + - "--hub.redis.{{ $field }}={{ $value }}" + {{- end }} + {{- end }} + {{- end }} + {{- range $field, $value := .redis.sentinel }} + {{- if has $field (list "masterset" "password" "username") -}} + {{- with $value }} + - "--hub.redis.sentinel.{{ $field }}={{ $value }}" + {{- end }} + {{- end }} + {{- end }} + {{- range $field, $value := .redis.tls }} + {{- if has $field (list "ca" "cert" "insecureSkipVerify" "key") -}} + {{- with $value }} + - "--hub.redis.tls.{{ $field }}={{ $value }}" + {{- end }} + {{- end }} + {{- end }} + {{- with .sendlogs }} + - "--hub.sendlogs={{ . }}" + {{- end }} + {{- end }} + {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if ($.Values.resources.limits).cpu }} + - name: GOMAXPROCS + valueFrom: + resourceFieldRef: + resource: limits.cpu + divisor: '1' + {{- end }} + {{- if ($.Values.resources.limits).memory }} + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + divisor: '1' + {{- end }} + {{- with .Values.hub.token }} + - name: HUB_TOKEN + valueFrom: + secretKeyRef: + name: {{ . }} + key: token + {{- end }} + {{- with .Values.env }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.envFrom }} + envFrom: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.deployment.additionalContainers }} + {{- toYaml .Values.deployment.additionalContainers | nindent 6 }} + {{- end }} + volumes: + - name: {{ .Values.persistence.name }} + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ default (include "traefik.fullname" .) .Values.persistence.existingClaim }} + {{- else }} + emptyDir: {} + {{- end }} + - name: tmp + emptyDir: {} + {{- $root := . }} + {{- range .Values.volumes }} + - name: {{ tpl (.name) $root | replace "." "-" }} + {{- if eq .type "secret" }} + secret: + secretName: {{ tpl (.name) $root }} + {{- else if eq .type "configMap" }} + configMap: + name: {{ tpl (.name) $root }} + {{- end }} + {{- end }} + {{- if .Values.deployment.additionalVolumes }} + {{- toYaml .Values.deployment.additionalVolumes | nindent 8 }} + {{- end }} + {{- if gt (len .Values.experimental.plugins) 0 }} + - name: plugins + emptyDir: {} + {{- end }} + {{- if .Values.providers.file.enabled }} + - name: traefik-extra-config + configMap: + name: {{ template "traefik.fullname" . }}-file-provider + {{- end }} + {{- if .Values.affinity }} + affinity: + {{- tpl (toYaml .Values.affinity) . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + {{- if (semverCompare "<1.19.0-0" .Capabilities.KubeVersion.Version) }} + {{- fail "ERROR: topologySpreadConstraints are supported only on kubernetes >= v1.19" -}} + {{- end }} + topologySpreadConstraints: + {{- tpl (toYaml .Values.topologySpreadConstraints) . | nindent 8 }} + {{- end }} +{{ end -}} diff --git a/utils/assets/charts/traefik/templates/_service-metrics.tpl b/utils/assets/charts/traefik/templates/_service-metrics.tpl new file mode 100644 index 0000000..d16a362 --- /dev/null +++ b/utils/assets/charts/traefik/templates/_service-metrics.tpl @@ -0,0 +1,25 @@ +{{- define "traefik.metrics-service-metadata" }} + labels: + {{- include "traefik.metricsservicelabels" . | nindent 4 -}} + {{- with .Values.metrics.prometheus.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{/* Labels used for metrics-relevant selector*/}} +{{/* This is an immutable field: this should not change between upgrade */}} +{{- define "traefik.metricslabelselector" -}} +{{- include "traefik.labelselector" . }} +app.kubernetes.io/component: metrics +{{- end }} + +{{/* Shared labels used in metadata of metrics-service and servicemonitor */}} +{{- define "traefik.metricsservicelabels" -}} +{{ include "traefik.metricslabelselector" . }} +helm.sh/chart: {{ template "traefik.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + diff --git a/utils/assets/charts/traefik/templates/_service.tpl b/utils/assets/charts/traefik/templates/_service.tpl new file mode 100644 index 0000000..27d5bc4 --- /dev/null +++ b/utils/assets/charts/traefik/templates/_service.tpl @@ -0,0 +1,84 @@ +{{- define "traefik.service-name" -}} +{{- $fullname := printf "%s-%s" (include "traefik.fullname" .root) .name -}} +{{- if eq .name "default" -}} +{{- $fullname = include "traefik.fullname" .root -}} +{{- end -}} + +{{- if ge (len $fullname) 60 -}} # 64 - 4 (udp-postfix) = 60 + {{- fail "ERROR: Cannot create a service whose full name contains more than 60 characters" -}} +{{- end -}} + +{{- $fullname -}} +{{- end -}} + +{{- define "traefik.service-metadata" }} + labels: + {{- include "traefik.labels" .root | nindent 4 -}} + {{- with .service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- define "traefik.service-spec" -}} + {{- $type := default "LoadBalancer" .service.type }} + type: {{ $type }} + {{- with .service.loadBalancerClass }} + loadBalancerClass: {{ . }} + {{- end}} + {{- with .service.spec }} + {{- toYaml . | nindent 2 }} + {{- end }} + selector: + {{- include "traefik.labelselector" .root | nindent 4 }} + {{- if eq $type "LoadBalancer" }} + {{- with .service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml . | nindent 2 }} + {{- end -}} + {{- end -}} + {{- with .service.externalIPs }} + externalIPs: + {{- toYaml . | nindent 2 }} + {{- end -}} + {{- with .service.ipFamilyPolicy }} + ipFamilyPolicy: {{ . }} + {{- end }} + {{- with .service.ipFamilies }} + ipFamilies: + {{- toYaml . | nindent 2 }} + {{- end -}} +{{- end }} + +{{- define "traefik.service-ports" }} + {{- range $name, $config := .ports }} + {{- if (index (default dict $config.expose) $.serviceName) }} + {{- $port := default $config.port $config.exposedPort }} + {{- if empty $port }} + {{- fail (print "ERROR: Cannot create " (trim $name) " port on Service without .port or .exposedPort") }} + {{- end }} + - port: {{ $port }} + name: {{ $name | quote }} + targetPort: {{ default $name $config.targetPort }} + protocol: {{ default "TCP" $config.protocol }} + {{- if $config.nodePort }} + nodePort: {{ $config.nodePort }} + {{- end }} + {{- if $config.appProtocol }} + appProtocol: {{ $config.appProtocol }} + {{- end }} + {{- if and ($config.http3).enabled ($config.single) }} + {{- $http3Port := default $config.exposedPort $config.http3.advertisedPort }} + - port: {{ $http3Port }} + name: "{{ $name }}-http3" + targetPort: "{{ $name }}-http3" + protocol: UDP + {{- if $config.nodePort }} + nodePort: {{ $config.nodePort }} + {{- end }} + {{- if $config.appProtocol }} + appProtocol: {{ $config.appProtocol }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/traefik/templates/daemonset.yaml b/utils/assets/charts/traefik/templates/daemonset.yaml new file mode 100644 index 0000000..b370c22 --- /dev/null +++ b/utils/assets/charts/traefik/templates/daemonset.yaml @@ -0,0 +1,58 @@ +{{- if and .Values.deployment.enabled (eq .Values.deployment.kind "DaemonSet") -}} + {{- with .Values.additionalArguments -}} + {{- range . -}} + {{- if contains ".acme." . -}} + {{- fail (printf "ACME functionality is not supported when running Traefik as a DaemonSet") -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if eq (default .Chart.AppVersion .Values.image.tag) "latest" }} + {{- fail "\n\n ERROR: latest tag should not be used" }} + {{- end }} + {{- with .Values.updateStrategy }} + {{- if and (eq (.type) "RollingUpdate") (.rollingUpdate) }} + {{- if not (contains "%" (toString .rollingUpdate.maxUnavailable)) }} + {{- if and ($.Values.hostNetwork) (lt (float64 .rollingUpdate.maxUnavailable) 1.0) }} + {{- fail "maxUnavailable should be greater than 1 when using hostNetwork." }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "traefik.fullname" . }} + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- if and .Values.providers.file.enabled (not .Values.providers.file.watch) }} + checksum/traefik-dynamic-conf: {{ include (print $.Template.BasePath "/provider-file-cm.yaml") . | sha256sum }} + {{- end }} + {{- with .Values.deployment.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "traefik.labelselector" . | nindent 6 }} + {{- with .Values.updateStrategy }} + updateStrategy: + type: {{ .type }} + {{- if (eq .type "RollingUpdate") }} + rollingUpdate: + maxUnavailable: {{ .rollingUpdate.maxUnavailable }} + maxSurge: {{ .rollingUpdate.maxSurge }} + {{- end }} + {{- end }} + minReadySeconds: {{ .Values.deployment.minReadySeconds }} + {{- if .Values.deployment.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }} + {{- end }} + template: {{ template "traefik.podTemplate" . }} +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/deployment.yaml b/utils/assets/charts/traefik/templates/deployment.yaml new file mode 100644 index 0000000..4b3a1ae --- /dev/null +++ b/utils/assets/charts/traefik/templates/deployment.yaml @@ -0,0 +1,58 @@ +{{/* check helm version */}} +{{- if (semverCompare "= 3.9.0 is required" -}} +{{- end -}} + +{{- if and .Values.deployment.enabled (eq .Values.deployment.kind "Deployment") -}} + {{- if gt (int .Values.deployment.replicas) 1 -}} + {{- with .Values.additionalArguments -}} + {{- range . -}} + {{- if contains ".acme." . -}} + {{- fail (printf "You can not enable acme if you set more than one traefik replica") -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- if eq (default .Chart.AppVersion .Values.image.tag) "latest" }} + {{- fail "\n\n ERROR: latest tag should not be used" }} + {{- end }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "traefik.fullname" . }} + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} + {{- with .Values.deployment.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- if and .Values.providers.file.enabled (not .Values.providers.file.watch) }} + checksum/traefik-dynamic-conf: {{ include (print $.Template.BasePath "/provider-file-cm.yaml") . | sha256sum }} + {{- end }} + {{- with .Values.deployment.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ default 1 .Values.deployment.replicas }} + {{- end }} + {{- if .Values.deployment.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + {{- include "traefik.labelselector" . | nindent 6 }} + {{- with .Values.updateStrategy }} + strategy: + type: {{ .type }} + {{- if (eq .type "RollingUpdate") }} + rollingUpdate: + maxUnavailable: {{ .rollingUpdate.maxUnavailable }} + maxSurge: {{ .rollingUpdate.maxSurge }} + {{- end }} + {{- end }} + minReadySeconds: {{ .Values.deployment.minReadySeconds }} + template: {{ template "traefik.podTemplate" . }} +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/extra-objects.yaml b/utils/assets/charts/traefik/templates/extra-objects.yaml new file mode 100644 index 0000000..fb38e97 --- /dev/null +++ b/utils/assets/charts/traefik/templates/extra-objects.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraObjects }} +--- +{{ include "traefik.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/utils/assets/charts/traefik/templates/gateway.yaml b/utils/assets/charts/traefik/templates/gateway.yaml new file mode 100644 index 0000000..42bc33d --- /dev/null +++ b/utils/assets/charts/traefik/templates/gateway.yaml @@ -0,0 +1,62 @@ +{{- if and (.Values.gateway).enabled (.Values.providers.kubernetesGateway).enabled }} + {{- if not .Values.gateway.listeners }} + {{- fail "ERROR: gateway must have at least one listener or should be disabled" }} + {{- end }} +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: {{ default "traefik-gateway" .Values.gateway.name }} + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} + {{- with .Values.gateway.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + gatewayClassName: {{ default "traefik" .Values.gatewayClass.name }} + {{- with .Values.gateway.infrastructure }} + infrastructure: + {{ toYaml . | nindent 4 }} + {{- end }} + listeners: + {{- range $name, $config := .Values.gateway.listeners }} + - name: {{ $name }} + {{ if not .port }} + {{- fail "ERROR: port needs to be specified" }} + {{- end -}} + {{ $found := false }} + {{- range $portName, $portConfig := $.Values.ports -}} + {{- if eq $portConfig.port $config.port -}} + {{ $found = true }} + {{- end -}} + {{- end -}} + {{ if not $found }} + {{- fail (printf "ERROR: port %0.f is not declared in ports" .port ) }} + {{- end -}} + port: {{ .port }} + protocol: {{ .protocol }} + {{- with .hostname }} + hostname: {{ . | toYaml }} + {{- end }} + {{- with .namespacePolicy }} + allowedRoutes: + namespaces: + from: {{ . }} + {{- end }} + {{ if and (eq .protocol "HTTPS") (not .certificateRefs) }} + {{- fail "ERROR: certificateRefs needs to be specified using HTTPS" }} + {{- end }} + {{ if or .certificateRefs .mode }} + tls: + {{ with .mode }} + mode: {{ . }} + {{- end }} + {{ with .certificateRefs }} + certificateRefs: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/utils/assets/charts/traefik/templates/gatewayclass.yaml b/utils/assets/charts/traefik/templates/gatewayclass.yaml new file mode 100644 index 0000000..7f98c1e --- /dev/null +++ b/utils/assets/charts/traefik/templates/gatewayclass.yaml @@ -0,0 +1,14 @@ +{{- if and (.Values.gatewayClass).enabled (.Values.providers.kubernetesGateway).enabled }} +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: {{ default "traefik" .Values.gatewayClass.name }} + labels: + {{- include "traefik.labels" . | nindent 4 }} + {{- with .Values.gatewayClass.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + controllerName: traefik.io/gateway-controller +{{- end }} diff --git a/utils/assets/charts/traefik/templates/hpa.yaml b/utils/assets/charts/traefik/templates/hpa.yaml new file mode 100644 index 0000000..cfa1e5a --- /dev/null +++ b/utils/assets/charts/traefik/templates/hpa.yaml @@ -0,0 +1,35 @@ +{{- if .Values.autoscaling.enabled }} + +{{- if not .Values.autoscaling.maxReplicas }} + {{- fail "ERROR: maxReplicas is required on HPA" }} +{{- end }} + +{{- if semverCompare ">=1.23.0-0" .Capabilities.KubeVersion.Version }} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta2 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "traefik.fullname" . }} + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "traefik.fullname" . }} +{{- if .Values.autoscaling.minReplicas }} + minReplicas: {{ .Values.autoscaling.minReplicas }} +{{- end }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} +{{- if .Values.autoscaling.metrics }} + metrics: +{{ toYaml .Values.autoscaling.metrics | indent 4 }} +{{- end }} +{{- if .Values.autoscaling.behavior }} + behavior: +{{ toYaml .Values.autoscaling.behavior | indent 4 }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/traefik/templates/hub-admission-controller.yaml b/utils/assets/charts/traefik/templates/hub-admission-controller.yaml new file mode 100644 index 0000000..37b2314 --- /dev/null +++ b/utils/assets/charts/traefik/templates/hub-admission-controller.yaml @@ -0,0 +1,198 @@ +{{- if .Values.hub.token -}} +{{- if .Values.hub.apimanagement.enabled }} +{{- $cert := include "traefik-hub.webhook_cert" . | fromYaml }} +--- +apiVersion: v1 +kind: Secret +type: kubernetes.io/tls +metadata: + name: hub-agent-cert + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} +data: + tls.crt: {{ $cert.Cert }} + tls.key: {{ $cert.Key }} + +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: hub-acp + labels: + {{- include "traefik.labels" . | nindent 4 }} +webhooks: + - name: admission.traefik.svc + clientConfig: + service: + name: admission + namespace: {{ template "traefik.namespace" . }} + path: /acp + caBundle: {{ $cert.Cert }} + sideEffects: None + admissionReviewVersions: + - v1 + rules: + - operations: + - CREATE + - UPDATE + - DELETE + apiGroups: + - hub.traefik.io + apiVersions: + - v1alpha1 + resources: + - accesscontrolpolicies + +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: hub-api + labels: + {{- include "traefik.labels" . | nindent 4 }} +webhooks: + - name: hub-agent.traefik.portal + clientConfig: + service: + name: admission + namespace: {{ template "traefik.namespace" . }} + path: /api-portal + caBundle: {{ $cert.Cert }} + sideEffects: None + admissionReviewVersions: + - v1 + rules: + - operations: + - CREATE + - UPDATE + - DELETE + apiGroups: + - hub.traefik.io + apiVersions: + - v1alpha1 + resources: + - apiportals + - name: hub-agent.traefik.api + clientConfig: + service: + name: admission + namespace: {{ template "traefik.namespace" . }} + path: /api + caBundle: {{ $cert.Cert }} + sideEffects: None + admissionReviewVersions: + - v1 + rules: + - operations: + - CREATE + - UPDATE + - DELETE + apiGroups: + - hub.traefik.io + apiVersions: + - v1alpha1 + resources: + - apis + - name: hub-agent.traefik.access + clientConfig: + service: + name: admission + namespace: {{ template "traefik.namespace" . }} + path: /api-access + caBundle: {{ $cert.Cert }} + sideEffects: None + admissionReviewVersions: + - v1 + rules: + - operations: + - CREATE + - UPDATE + - DELETE + apiGroups: + - hub.traefik.io + apiVersions: + - v1alpha1 + resources: + - apiaccesses + - name: hub-agent.traefik.plan + clientConfig: + service: + name: admission + namespace: {{ template "traefik.namespace" . }} + path: /api-plan + caBundle: {{ $cert.Cert }} + sideEffects: None + admissionReviewVersions: + - v1 + rules: + - operations: + - CREATE + - UPDATE + - DELETE + apiGroups: + - hub.traefik.io + apiVersions: + - v1alpha1 + resources: + - apiplans + - name: hub-agent.traefik.bundle + clientConfig: + service: + name: admission + namespace: {{ template "traefik.namespace" . }} + path: /api-bundle + caBundle: {{ $cert.Cert }} + sideEffects: None + admissionReviewVersions: + - v1 + rules: + - operations: + - CREATE + - UPDATE + - DELETE + apiGroups: + - hub.traefik.io + apiVersions: + - v1alpha1 + resources: + - apibundles + - name: hub-agent.traefik.version + clientConfig: + service: + name: admission + namespace: {{ template "traefik.namespace" . }} + path: /api-version + caBundle: {{ $cert.Cert }} + sideEffects: None + admissionReviewVersions: + - v1 + rules: + - operations: + - CREATE + - UPDATE + - DELETE + apiGroups: + - hub.traefik.io + apiVersions: + - v1alpha1 + resources: + - apiversions + +--- +apiVersion: v1 +kind: Service +metadata: + name: admission + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} +spec: + ports: + - name: https + port: 443 + targetPort: admission + selector: + {{- include "traefik.labelselector" . | nindent 4 }} +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/hub-apiportal.yaml b/utils/assets/charts/traefik/templates/hub-apiportal.yaml new file mode 100644 index 0000000..246b127 --- /dev/null +++ b/utils/assets/charts/traefik/templates/hub-apiportal.yaml @@ -0,0 +1,19 @@ +{{- if .Values.hub.apimanagement.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: apiportal + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} +spec: + ports: + - name: apiportal + port: 9903 + protocol: TCP + targetPort: apiportal + selector: + {{- include "traefik.labelselector" . | nindent 4 }} +{{- end -}} + diff --git a/utils/assets/charts/traefik/templates/ingressclass.yaml b/utils/assets/charts/traefik/templates/ingressclass.yaml new file mode 100644 index 0000000..6a8ff81 --- /dev/null +++ b/utils/assets/charts/traefik/templates/ingressclass.yaml @@ -0,0 +1,12 @@ +{{- if .Values.ingressClass.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + annotations: + ingressclass.kubernetes.io/is-default-class: {{ .Values.ingressClass.isDefaultClass | quote }} + labels: + {{- include "traefik.labels" . | nindent 4 }} + name: {{ .Values.ingressClass.name | default (include "traefik.fullname" .) }} +spec: + controller: traefik.io/ingress-controller +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/ingressroute.yaml b/utils/assets/charts/traefik/templates/ingressroute.yaml new file mode 100644 index 0000000..2f35abb --- /dev/null +++ b/utils/assets/charts/traefik/templates/ingressroute.yaml @@ -0,0 +1,43 @@ +{{ range $name, $config := .Values.ingressRoute }} +{{ if $config.enabled }} +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: {{ $.Release.Name }}-{{ $name }} + namespace: {{ template "traefik.namespace" $ }} + annotations: + {{- if and $.Values.ingressClass.enabled $.Values.providers.kubernetesCRD.enabled $.Values.providers.kubernetesCRD.ingressClass }} + kubernetes.io/ingress.class: {{ $.Values.providers.kubernetesCRD.ingressClass }} + {{- end }} + {{- with $config.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "traefik.labels" $ | nindent 4 }} + {{- with $config.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + entryPoints: + {{- range $config.entryPoints }} + - {{ . }} + {{- end }} + routes: + - match: {{ $config.matchRule }} + kind: Rule + {{- with $config.services }} + services: + {{- toYaml . | nindent 6 }} + {{- end -}} + {{- with $config.middlewares }} + middlewares: + {{- toYaml . | nindent 6 }} + {{- end -}} + + {{- with $config.tls }} + tls: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{ end }} diff --git a/utils/assets/charts/traefik/templates/poddisruptionbudget.yaml b/utils/assets/charts/traefik/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..f171639 --- /dev/null +++ b/utils/assets/charts/traefik/templates/poddisruptionbudget.yaml @@ -0,0 +1,23 @@ +{{- if .Values.podDisruptionBudget.enabled -}} +{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ template "traefik.fullname" . }} + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "traefik.labelselector" . | nindent 6 }} + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/prometheusrules.yaml b/utils/assets/charts/traefik/templates/prometheusrules.yaml new file mode 100644 index 0000000..3231aba --- /dev/null +++ b/utils/assets/charts/traefik/templates/prometheusrules.yaml @@ -0,0 +1,28 @@ +{{- if .Values.metrics.prometheus }} +{{- if (.Values.metrics.prometheus.prometheusRule).enabled }} + {{- if (not (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1")) }} + {{- if (not (.Values.metrics.prometheus.disableAPICheck)) }} + {{- fail "ERROR: You have to deploy monitoring.coreos.com/v1 first" }} + {{- end }} + {{- end }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "traefik.fullname" . }} + namespace: {{ .Values.metrics.prometheus.prometheusRule.namespace | default (include "traefik.namespace" .) }} + labels: + {{- include "traefik.labels" . | nindent 4 }} + {{- with .Values.metrics.prometheus.prometheusRule.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.prometheus.prometheusRule.rules }} + groups: + - name: {{ template "traefik.name" $ }} + rules: + {{- with .Values.metrics.prometheus.prometheusRule.rules }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/utils/assets/charts/traefik/templates/provider-file-cm.yaml b/utils/assets/charts/traefik/templates/provider-file-cm.yaml new file mode 100644 index 0000000..139a5a6 --- /dev/null +++ b/utils/assets/charts/traefik/templates/provider-file-cm.yaml @@ -0,0 +1,12 @@ +{{- if .Values.providers.file.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "traefik.fullname" . }}-file-provider + namespace: {{ template "traefik.namespace" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} +data: + config.yml: + {{ toYaml .Values.providers.file.content | nindent 4 }} +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/pvc.yaml b/utils/assets/charts/traefik/templates/pvc.yaml new file mode 100644 index 0000000..7ab96f9 --- /dev/null +++ b/utils/assets/charts/traefik/templates/pvc.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "traefik.fullname" . }} + namespace: {{ template "traefik.namespace" . }} + annotations: + {{- with .Values.persistence.annotations }} + {{ toYaml . | nindent 4 }} + {{- end }} + helm.sh/resource-policy: keep + labels: + {{- include "traefik.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.persistence.accessMode | quote }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClass }} + storageClassName: {{ .Values.persistence.storageClass | quote }} + {{- end }} + {{- if .Values.persistence.volumeName }} + volumeName: {{ .Values.persistence.volumeName | quote }} + {{- end }} +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/rbac/clusterrole.yaml b/utils/assets/charts/traefik/templates/rbac/clusterrole.yaml new file mode 100644 index 0000000..9e52d53 --- /dev/null +++ b/utils/assets/charts/traefik/templates/rbac/clusterrole.yaml @@ -0,0 +1,271 @@ +{{- $version := include "imageVersion" $ }} +{{- if and .Values.rbac.enabled (not .Values.rbac.namespaced) }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "traefik.clusterRoleName" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} + {{- range .Values.rbac.aggregateTo }} + rbac.authorization.k8s.io/aggregate-to-{{ . }}: "true" + {{- end }} +rules: + {{- if semverCompare ">=v3.1.0-0" $version }} + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + {{- end }} + {{- if (semverCompare "=v3.2.0-0" $version }} + - configmaps + {{- end }} + verbs: + - get + - list + - watch + {{- if (semverCompare ">=v3.1.0-0" $version) }} + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + {{- end }} + - apiGroups: + - gateway.networking.k8s.io + resources: + {{- if semverCompare ">=v3.2.0-0" $version }} + - backendtlspolicies + {{- end }} + - gatewayclasses + - gateways + {{- if semverCompare ">=v3.2.0-0" $version }} + - grpcroutes + {{- end }} + - httproutes + - referencegrants + - tcproutes + - tlsroutes + verbs: + - get + - list + - watch + - apiGroups: + - gateway.networking.k8s.io + resources: + {{- if semverCompare ">=v3.2.0-0" $version }} + - backendtlspolicies/status + {{- end }} + - gatewayclasses/status + - gateways/status + {{- if semverCompare ">=v3.2.0-0" $version }} + - grpcroutes/status + {{- end }} + - httproutes/status + - tcproutes/status + - tlsroutes/status + verbs: + - update + {{- end }} + {{- if .Values.hub.token }} + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + {{- end }} + {{- if .Values.hub.token }} + {{- if or (semverCompare ">=v3.1.0-0" $version) .Values.hub.apimanagement.enabled }} + - apiGroups: + - "" + resources: + - endpoints + verbs: + - list + - watch + {{- end }} + - apiGroups: + - "" + resources: + - namespaces + {{- if .Values.hub.apimanagement.enabled }} + - pods + {{- end }} + verbs: + - get + - list + {{- if .Values.hub.apimanagement.enabled }} + - watch + {{- end }} + {{- if .Values.hub.apimanagement.enabled }} + - apiGroups: + - hub.traefik.io + resources: + - accesscontrolpolicies + - apiaccesses + - apiportals + - apiratelimits + - apis + - apiversions + - apibundles + - apiplans + verbs: + - list + - watch + - create + - update + - patch + - delete + - get + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - list + - watch + {{- if (semverCompare "=1.25.0-0" .Capabilities.KubeVersion.Version }} + {{- fail "ERROR: PodSecurityPolicy has been removed in Kubernetes v1.25+" }} +{{- end }} +--- +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: runtime/default + seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default + name: {{ template "traefik.fullname" . }} + labels: + {{- include "traefik.labels" . | nindent 4 }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL +{{- if not .Values.securityContext.runAsNonRoot }} + allowedCapabilities: + - NET_BIND_SERVICE +{{- end }} + hostNetwork: {{ .Values.hostNetwork }} + hostIPC: false + hostPID: false + fsGroup: +{{- if .Values.securityContext.runAsNonRoot }} + ranges: + - max: 65535 + min: 1 + rule: MustRunAs +{{- else }} + rule: RunAsAny +{{- end }} +{{- if .Values.hostNetwork }} + hostPorts: + - max: 65535 + min: 1 +{{- end }} + readOnlyRootFilesystem: true + runAsUser: +{{- if .Values.securityContext.runAsNonRoot }} + rule: MustRunAsNonRoot +{{- else }} + rule: RunAsAny +{{- end }} + seLinux: + rule: RunAsAny + supplementalGroups: +{{- if .Values.securityContext.runAsNonRoot }} + ranges: + - max: 65535 + min: 1 + rule: MustRunAs +{{- else }} + rule: RunAsAny +{{- end }} + volumes: + - configMap + - downwardAPI + - secret + - emptyDir + - projected +{{- if .Values.persistence.enabled }} + - persistentVolumeClaim +{{- end -}} +{{- end -}} diff --git a/utils/assets/charts/traefik/templates/rbac/role.yaml b/utils/assets/charts/traefik/templates/rbac/role.yaml new file mode 100644 index 0000000..e81aaa8 --- /dev/null +++ b/utils/assets/charts/traefik/templates/rbac/role.yaml @@ -0,0 +1,143 @@ +{{- $version := include "imageVersion" $ }} +{{- $ingressNamespaces := concat (include "traefik.namespace" . | list) .Values.providers.kubernetesIngress.namespaces -}} +{{- $CRDNamespaces := concat (include "traefik.namespace" . | list) .Values.providers.kubernetesCRD.namespaces -}} +{{- $allNamespaces := sortAlpha (uniq (concat $ingressNamespaces $CRDNamespaces)) -}} + +{{- if and .Values.rbac.enabled .Values.rbac.namespaced -}} +{{- range $allNamespaces }} +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "traefik.fullname" $ }} + namespace: {{ . }} + labels: + {{- include "traefik.labels" $ | nindent 4 }} +rules: + {{- if (semverCompare "://:. Default: http://localhost:4318/v1/metrics + endpoint: "" + # -- Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. + headers: {} + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. + ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. + cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. + key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. + insecureSkipVerify: # @schema type:[boolean, null] + grpc: + # -- Set to true in order to send metrics to the OpenTelemetry Collector using gRPC + enabled: false + # -- Format: ://:. Default: http://localhost:4318/v1/metrics + endpoint: "" + # -- Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. + insecure: false + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. + ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. + cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. + key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. + insecureSkipVerify: false + +## Tracing +# -- https://doc.traefik.io/traefik/observability/tracing/overview/ +tracing: # @schema additionalProperties: false + # -- Enables tracing for internal resources. Default: false. + addInternals: false + otlp: + # -- See https://doc.traefik.io/traefik/v3.0/observability/tracing/opentelemetry/ + enabled: false + http: + # -- Set to true in order to send metrics to the OpenTelemetry Collector using HTTP. + enabled: false + # -- Format: ://:. Default: http://localhost:4318/v1/metrics + endpoint: "" + # -- Additional headers sent with metrics by the reporter to the OpenTelemetry Collector. + headers: {} + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. + ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. + cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. + key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. + insecureSkipVerify: false + grpc: + # -- Set to true in order to send metrics to the OpenTelemetry Collector using gRPC + enabled: false + # -- Format: ://:. Default: http://localhost:4318/v1/metrics + endpoint: "" + # -- Allows reporter to send metrics to the OpenTelemetry Collector without using a secured protocol. + insecure: false + ## Defines the TLS configuration used by the reporter to send metrics to the OpenTelemetry Collector. + tls: + # -- The path to the certificate authority, it defaults to the system bundle. + ca: "" + # -- The path to the public certificate. When using this option, setting the key option is required. + cert: "" + # -- The path to the private key. When using this option, setting the cert option is required. + key: "" + # -- When set to true, the TLS connection accepts any certificate presented by the server regardless of the hostnames it covers. + insecureSkipVerify: false + +# -- Global command arguments to be passed to all traefik's pods +globalArguments: +- "--global.checknewversion" +- "--global.sendanonymoususage" + +# -- Additional arguments to be passed at Traefik's binary +# See [CLI Reference](https://docs.traefik.io/reference/static-configuration/cli/) +# Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}"` +additionalArguments: [] +# - "--providers.kubernetesingress.ingressclass=traefik-internal" +# - "--log.level=DEBUG" + +# -- Additional Environment variables to be passed to Traefik's binary +# @default -- See _values.yaml_ +env: [] + +# -- Environment variables to be passed to Traefik's binary from configMaps or secrets +envFrom: [] + +ports: + traefik: + port: 8080 + # -- Use hostPort if set. + hostPort: # @schema type:[integer, null]; minimum:0 + # -- Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which + # means it's listening on all your interfaces and all your IPs. You may want + # to set this value if you need traefik to listen on specific interface + # only. + hostIP: # @schema type:[string, null] + + # Defines whether the port is exposed if service.type is LoadBalancer or + # NodePort. + # + # -- You SHOULD NOT expose the traefik port on production deployments. + # If you want to access it from outside your cluster, + # use `kubectl port-forward` or create a secure ingress + expose: + default: false + # -- The exposed port for this service + exposedPort: 8080 + # -- The port protocol (TCP/UDP) + protocol: TCP + web: + ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8000 + # hostPort: 8000 + # containerPort: 8000 + expose: + default: true + exposedPort: 80 + ## -- Different target traefik port on the cluster, useful for IP type LB + targetPort: # @schema type:[string, integer, null]; minimum:0 + # The port protocol (TCP/UDP) + protocol: TCP + # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) + nodePort: # @schema type:[integer, null]; minimum:0 + # Port Redirections + # Added in 2.2, you can make permanent redirects via entrypoints. + # https://docs.traefik.io/routing/entrypoints/#redirection + redirectTo: {} + forwardedHeaders: + # -- Trust forwarded headers information (X-Forwarded-*). + trustedIPs: [] + insecure: false + proxyProtocol: + # -- Enable the Proxy Protocol header parsing for the entry point + trustedIPs: [] + insecure: false + # -- Set transport settings for the entrypoint; see also + # https://doc.traefik.io/traefik/routing/entrypoints/#transport + transport: + respondingTimeouts: + readTimeout: # @schema type:[string, integer, null] + writeTimeout: # @schema type:[string, integer, null] + idleTimeout: # @schema type:[string, integer, null] + lifeCycle: + requestAcceptGraceTimeout: # @schema type:[string, integer, null] + graceTimeOut: # @schema type:[string, integer, null] + keepAliveMaxRequests: # @schema type:[integer, null]; minimum:0 + keepAliveMaxTime: # @schema type:[string, integer, null] + websecure: + ## -- Enable this entrypoint as a default entrypoint. When a service doesn't explicitly set an entrypoint it will only use this entrypoint. + # asDefault: true + port: 8443 + hostPort: # @schema type:[integer, null]; minimum:0 + containerPort: # @schema type:[integer, null]; minimum:0 + expose: + default: true + exposedPort: 443 + ## -- Different target traefik port on the cluster, useful for IP type LB + targetPort: # @schema type:[string, integer, null]; minimum:0 + ## -- The port protocol (TCP/UDP) + protocol: TCP + # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) + nodePort: # @schema type:[integer, null]; minimum:0 + # -- See [upstream documentation](https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol) + appProtocol: # @schema type:[string, null] + # -- See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#allowacmebypass) + allowACMEByPass: false + http3: + ## -- Enable HTTP/3 on the entrypoint + ## Enabling it will also enable http3 experimental feature + ## https://doc.traefik.io/traefik/routing/entrypoints/#http3 + ## There are known limitations when trying to listen on same ports for + ## TCP & UDP (Http3). There is a workaround in this chart using dual Service. + ## https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741 + enabled: false + advertisedPort: # @schema type:[integer, null]; minimum:0 + forwardedHeaders: + # -- Trust forwarded headers information (X-Forwarded-*). + trustedIPs: [] + insecure: false + proxyProtocol: + # -- Enable the Proxy Protocol header parsing for the entry point + trustedIPs: [] + insecure: false + # -- See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#transport) + transport: + respondingTimeouts: + readTimeout: # @schema type:[string, integer, null] + writeTimeout: # @schema type:[string, integer, null] + idleTimeout: # @schema type:[string, integer, null] + lifeCycle: + requestAcceptGraceTimeout: # @schema type:[string, integer, null] + graceTimeOut: # @schema type:[string, integer, null] + keepAliveMaxRequests: # @schema type:[integer, null]; minimum:0 + keepAliveMaxTime: # @schema type:[string, integer, null] + # -- See [upstream documentation](https://doc.traefik.io/traefik/routing/entrypoints/#tls) + tls: + enabled: true + options: "" + certResolver: "" + domains: [] + # -- One can apply Middlewares on an entrypoint + # https://doc.traefik.io/traefik/middlewares/overview/ + # https://doc.traefik.io/traefik/routing/entrypoints/#middlewares + # -- /!\ It introduces here a link between your static configuration and your dynamic configuration /!\ + # It follows the provider naming convention: https://doc.traefik.io/traefik/providers/overview/#provider-namespace + # - namespace-name1@kubernetescrd + # - namespace-name2@kubernetescrd + middlewares: [] + metrics: + # -- When using hostNetwork, use another port to avoid conflict with node exporter: + # https://github.com/prometheus/prometheus/wiki/Default-port-allocations + port: 9100 + # -- You may not want to expose the metrics port on production deployments. + # If you want to access it from outside your cluster, + # use `kubectl port-forward` or create a secure ingress + expose: + default: false + # -- The exposed port for this service + exposedPort: 9100 + # -- The port protocol (TCP/UDP) + protocol: TCP + +# -- TLS Options are created as [TLSOption CRDs](https://doc.traefik.io/traefik/https/tls/#tls-options) +# When using `labelSelector`, you'll need to set labels on tlsOption accordingly. +# See EXAMPLE.md for details. +tlsOptions: {} + +# -- TLS Store are created as [TLSStore CRDs](https://doc.traefik.io/traefik/https/tls/#default-certificate). This is useful if you want to set a default certificate. See EXAMPLE.md for details. +tlsStore: {} + +service: + enabled: true + ## -- Single service is using `MixedProtocolLBService` feature gate. + ## -- When set to false, it will create two Service, one for TCP and one for UDP. + single: true + type: LoadBalancer + # -- Additional annotations applied to both TCP and UDP services (e.g. for cloud provider specific config) + annotations: {} + # -- Additional annotations for TCP service only + annotationsTCP: {} + # -- Additional annotations for UDP service only + annotationsUDP: {} + # -- Additional service labels (e.g. for filtering Service by custom labels) + labels: {} + # -- Additional entries here will be added to the service spec. + # -- Cannot contain type, selector or ports entries. + spec: {} + # externalTrafficPolicy: Cluster + # loadBalancerIP: "1.2.3.4" + # clusterIP: "2.3.4.5" + loadBalancerSourceRanges: [] + # - 192.168.0.1/32 + # - 172.16.0.0/16 + ## -- Class of the load balancer implementation + # loadBalancerClass: service.k8s.aws/nlb + externalIPs: [] + # - 1.2.3.4 + ## One of SingleStack, PreferDualStack, or RequireDualStack. + # ipFamilyPolicy: SingleStack + ## List of IP families (e.g. IPv4 and/or IPv6). + ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + # ipFamilies: + # - IPv4 + # - IPv6 + ## + additionalServices: {} + ## -- An additional and optional internal Service. + ## Same parameters as external Service + # internal: + # type: ClusterIP + # # labels: {} + # # annotations: {} + # # spec: {} + # # loadBalancerSourceRanges: [] + # # externalIPs: [] + # # ipFamilies: [ "IPv4","IPv6" ] + +autoscaling: + # -- Create HorizontalPodAutoscaler object. + # See EXAMPLES.md for more details. + enabled: false + +persistence: + # -- Enable persistence using Persistent Volume Claims + # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/. + # It can be used to store TLS certificates along with `certificatesResolvers..acme.storage` option + enabled: false + name: data + existingClaim: "" + accessMode: ReadWriteOnce + size: 128Mi + storageClass: "" + volumeName: "" + path: /data + annotations: {} + # -- Only mount a subpath of the Volume into the pod + subPath: "" + +# -- Certificates resolvers configuration. +# Ref: https://doc.traefik.io/traefik/https/acme/#certificate-resolvers +# See EXAMPLES.md for more details. +certificatesResolvers: {} + +# -- If hostNetwork is true, runs traefik in the host network namespace +# To prevent unschedulabel pods due to port collisions, if hostNetwork=true +# and replicas>1, a pod anti-affinity is recommended and will be set if the +# affinity is left as default. +hostNetwork: false + +# -- Whether Role Based Access Control objects like roles and rolebindings should be created +rbac: # @schema additionalProperties: false + enabled: true + # When set to true: + # 1. It switches respectively the use of `ClusterRole` and `ClusterRoleBinding` to `Role` and `RoleBinding`. + # 2. It adds `disableIngressClassLookup` on Kubernetes Ingress with Traefik Proxy v3 until v3.1.4 + # 3. It adds `disableClusterScopeResources` on Ingress and CRD (Kubernetes) providers with Traefik Proxy v3.1.2+ + # **NOTE**: `IngressClass`, `NodePortLB` and **Gateway** provider cannot be used with namespaced RBAC. + # See [upstream documentation](https://doc.traefik.io/traefik/providers/kubernetes-ingress/#disableclusterscoperesources) for more details. + namespaced: false + # Enable user-facing roles + # https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + aggregateTo: [] + # List of Kubernetes secrets that are accessible for Traefik. If empty, then access is granted to every secret. + secretResourceNames: [] + +# -- Enable to create a PodSecurityPolicy and assign it to the Service Account via RoleBinding or ClusterRoleBinding +podSecurityPolicy: + enabled: false + +# -- The service account the pods will use to interact with the Kubernetes API +serviceAccount: # @schema additionalProperties: false + # If set, an existing service account is used + # If not set, a service account is created automatically using the fullname template + name: "" + +# -- Additional serviceAccount annotations (e.g. for oidc authentication) +serviceAccountAnnotations: {} + +# -- [Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for `traefik` container. +resources: {} + +# -- This example pod anti-affinity forces the scheduler to put traefik pods +# -- on nodes where no other traefik pods are scheduled. +# It should be used when hostNetwork: true to prevent port conflicts +affinity: {} +# podAntiAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: '{{ template "traefik.name" . }}' +# app.kubernetes.io/instance: '{{ .Release.Name }}-{{ .Release.Namespace }}' +# topologyKey: kubernetes.io/hostname + +# -- nodeSelector is the simplest recommended form of node selection constraint. +nodeSelector: {} +# -- Tolerations allow the scheduler to schedule pods with matching taints. +tolerations: [] +# -- You can use topology spread constraints to control +# how Pods are spread across your cluster among failure-domains. +topologySpreadConstraints: [] +# This example topologySpreadConstraints forces the scheduler to put traefik pods +# on nodes where no other traefik pods are scheduled. +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: '{{ template "traefik.name" . }}' +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule + +# -- [Pod Priority and Preemption](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) +priorityClassName: "" + +# -- [SecurityContext](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1) +# @default -- See _values.yaml_ +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ALL] + readOnlyRootFilesystem: true + +# -- [Pod Security Context](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context) +# @default -- See _values.yaml_ +podSecurityContext: + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + +# +# -- Extra objects to deploy (value evaluated as a template) +# +# In some cases, it can avoid the need for additional, extended or adhoc deployments. +# See #595 for more details and traefik/tests/values/extra.yaml for example. +extraObjects: [] + +# -- This field override the default Release Namespace for Helm. +# It will not affect optional CRDs such as `ServiceMonitor` and `PrometheusRules` +namespaceOverride: "" + +## -- This field override the default app.kubernetes.io/instance label for all Objects. +instanceLabelOverride: "" + +# Traefik Hub configuration. See https://doc.traefik.io/traefik-hub/ +hub: + # -- Name of `Secret` with key 'token' set to a valid license token. + # It enables API Gateway. + token: "" + apimanagement: + # -- Set to true in order to enable API Management. Requires a valid license token. + enabled: false + admission: + # -- WebHook admission server listen address. Default: "0.0.0.0:9943". + listenAddr: "" + # -- Certificate of the WebHook admission server. Default: "hub-agent-cert". + secretName: "" + + redis: + # -- Enable Redis Cluster. Default: true. + cluster: # @schema type:[boolean, null] + # -- Database used to store information. Default: "0". + database: # @schema type:[string, null] + # -- Endpoints of the Redis instances to connect to. Default: "". + endpoints: "" + # -- The username to use when connecting to Redis endpoints. Default: "". + username: "" + # -- The password to use when connecting to Redis endpoints. Default: "". + password: "" + sentinel: + # -- Name of the set of main nodes to use for main selection. Required when using Sentinel. Default: "". + masterset: "" + # -- Username to use for sentinel authentication (can be different from endpoint username). Default: "". + username: "" + # -- Password to use for sentinel authentication (can be different from endpoint password). Default: "". + password: "" + # -- Timeout applied on connection with redis. Default: "0s". + timeout: "" + tls: + # -- Path to the certificate authority used for the secured connection. + ca: "" + # -- Path to the public certificate used for the secure connection. + cert: "" + # -- Path to the private key used for the secure connection. + key: "" + # -- When insecureSkipVerify is set to true, the TLS connection accepts any certificate presented by the server. Default: false. + insecureSkipVerify: false + # Enable export of errors logs to the platform. Default: true. + sendlogs: # @schema type:[boolean, null] diff --git a/utils/assets/cmd b/utils/assets/cmd new file mode 100755 index 0000000..28d36cb Binary files /dev/null and b/utils/assets/cmd differ diff --git a/utils/assets/main b/utils/assets/main new file mode 100755 index 0000000..52879ef Binary files /dev/null and b/utils/assets/main differ diff --git a/utils/assets/templates/argo.yaml b/utils/assets/templates/argo.yaml new file mode 100644 index 0000000..cbbe967 --- /dev/null +++ b/utils/assets/templates/argo.yaml @@ -0,0 +1,73 @@ +{{- if index .Values "argo-workflows" "enabled" }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: argo-workflow + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: custom-argo-clusterrole +rules: + # Default Argo permissions + - apiGroups: [""] + resources: ["configmaps", "pods", "pods/log", "secrets", "persistentvolumeclaims", "serviceaccounts"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch"] + - apiGroups: ["argoproj.io"] + resources: ["workflows", "workflowtemplates", "cronworkflows", "workflowtasksets", "workfloweventbindings", "clusterworkflowtemplates"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create", "delete", "get", "list", "update"] + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["create", "delete", "get", "list", "watch"] + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["create", "get"] + # Full power activated + - apiGroups: [""] + resources: ["bindings", "endpoints", "events", "limitranges", "namespaces", "nodes", "persistentvolumes", "replicationcontrollers", "resourcequotas"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["apps"] + resources: ["daemonsets", "deployments", "replicasets", "statefulsets"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["autoscaling"] + resources: ["horizontalpodautoscalers"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["batch"] + resources: ["cronjobs"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["networking.k8s.io"] + resources: ["networkpolicies", "ingresses"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["policy"] + resources: ["poddisruptionbudgets"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["rbac.authorization.k8s.io"] + resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses", "volumeattachments"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] + - apiGroups: ["argoproj.io"] + resources: ["workflowtaskresults"] + verbs: ["create", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: custom-argo-clusterrolebinding +subjects: + - kind: ServiceAccount + name: argo-workflow + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: custom-argo-clusterrole +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/hydra.yaml b/utils/assets/templates/hydra.yaml new file mode 100644 index 0000000..463c9b0 --- /dev/null +++ b/utils/assets/templates/hydra.yaml @@ -0,0 +1,31 @@ +{{- if index .Values "hydra" "enabled" }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: hydra-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/hydra`) + priority: 10 + services: + - kind: Service + name: {{ .Release.Name }}-hydra-public.{{ .Release.Namespace }} + passHostHeader: true + port: 4444 +--- +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: hydra-secret +data: + dsn: bWVtb3J5 + secretsCookie: U0prcFlUeDFZZWhPMFEyc3UweWlwcDdmZ1BaRmc2ajA= + secretsSystem: M3FwWnlpemIzbXc2cE80Q1l3Q1MyUVFmbXdOeVFpRzE= + + + +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/ldapUserManager.yaml b/utils/assets/templates/ldapUserManager.yaml new file mode 100644 index 0000000..02fa89a --- /dev/null +++ b/utils/assets/templates/ldapUserManager.yaml @@ -0,0 +1,113 @@ +{{- if .Values.ldapUserManager.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: ldap-user-manager + name: {{ .Release.Name }}-ldap-user-manager +spec: + replicas: 1 + selector: + matchLabels: + app: ldap-user-manager + strategy: {} + template: + metadata: + labels: + app: ldap-user-manager + spec: + containers: + - image: wheelybird/ldap-user-manager:v1.8 + name: ldap-user-manager + env: + - name: SERVER_HOSTNAME + value: "{{ .Values.ldapUserManager.env.SERVER_HOSTNAME }}" + - name: LDAP_URI + value: "ldap://{{ .Release.Name }}-openldap.{{ .Release.Namespace }}.svc.cluster.local" + - name: LDAP_BASE_DN + value: "{{ .Values.ldapUserManager.env.LDAP_BASE_DN }}" + - name: LDAP_REQUIRE_STARTTLS + value: "{{ .Values.ldapUserManager.env.LDAP_REQUIRE_STARTTLS }}" + - name: LDAP_ADMINS_GROUP + value: "{{ .Values.ldapUserManager.env.LDAP_ADMINS_GROUP }}" + - name: LDAP_ADMIN_BIND_DN + value: "{{ .Values.ldapUserManager.env.LDAP_ADMIN_BIND_DN }}" + - name: LDAP_ADMIN_BIND_PWD + value: "{{ .Values.ldapUserManager.env.LDAP_ADMIN_BIND_PWD }}" + - name: LDAP_IGNORE_CERT_ERRORS + value: "{{ .Values.ldapUserManager.env.LDAP_IGNORE_CERT_ERRORS }}" + - name: NO_HTTPS + value: "{{ .Values.ldapUserManager.env.NO_HTTPS }}" + - name: EMAIL_DOMAIN + value: "{{ .Values.ldapUserManager.env.EMAIL_DOMAIN }}" + - name: ORGANISATION_NAME + value: "{{ .Values.ldapUserManager.env.ORGANISATION_NAME }}" + - name: LDAP_USER_OU + value: "{{ .Values.ldapUserManager.env.LDAP_USER_OU }}" + - name: LDAP_GROUP_OU + value: "{{ .Values.ldapUserManager.env.LDAP_GROUP_OU }}" + - name: SERVER_PATH + value: "{{ .Values.ldapUserManager.env.SERVER_PATH }}" + - name: LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES + value: "{{ .Values.ldapUserManager.env.LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES }}" + - name: LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES + value: "{{ .Values.ldapUserManager.env.LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES }}" + - name: LDAP_GROUP_ADDITIONAL_OBJECTCLASSES + value: "{{ .Values.ldapUserManager.env.LDAP_GROUP_ADDITIONAL_OBJECTCLASSES }}" + - name: LDAP_GROUP_ADDITIONAL_ATTRIBUTES + value: "{{ .Values.ldapUserManager.env.LDAP_GROUP_ADDITIONAL_ATTRIBUTES }}" + - name: ACCEPT_WEAK_PASSWORDS + value: "{{ .Values.ldapUserManager.env.ACCEPT_WEAK_PASSWORDS }}" + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: https + containerPort: 443 + protocol: TCP + resources: + limits: + cpu: "{{ .Values.ldapUserManager.resources.limits.cpu }}" + memory: "{{ .Values.ldapUserManager.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ldapUserManager.resources.requests.cpu }}" + memory: "{{ .Values.ldapUserManager.resources.requests.memory }}" + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-ldap-user-manager-svc + labels: + app: ldap-user-manager-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 80 + - name: https + port: 8443 + protocol: TCP + targetPort: 443 + selector: + app: ldap-user-manager + type: ClusterIP +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: ldap-user-manager-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/users`) + priority: 10 + services: + - kind: Service + name: {{ .Release.Name }}-ldap-user-manager-svc + passHostHeader: true + port: 8080 +{{- end }} diff --git a/utils/assets/templates/loki.yaml b/utils/assets/templates/loki.yaml new file mode 100644 index 0000000..c143cac --- /dev/null +++ b/utils/assets/templates/loki.yaml @@ -0,0 +1,16 @@ +{{- if index .Values.loki.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.loki.singleBinary.persistence.claimName }} + namespace: {{ .Release.Namespace }} + annotations: + helm.sh/resource-policy: keep +spec: + accessModes: + - {{ .Values.loki.singleBinary.persistence.accessMode }} + resources: + requests: + storage: {{ .Values.loki.singleBinary.persistence.size }} + storageClassName: {{ .Values.loki.singleBinary.persistence.storageClassName }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/mongo.yaml b/utils/assets/templates/mongo.yaml new file mode 100644 index 0000000..1c5e3d9 --- /dev/null +++ b/utils/assets/templates/mongo.yaml @@ -0,0 +1,15 @@ +{{- if index .Values.mongodb.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ index .Values.mongodb.persistence.existingClaim }} + namespace: {{ .Release.Namespace }} + annotations: + helm.sh/resource-policy: keep +spec: + accessModes: {{ index .Values.mongodb.persistence.accessModes }} + resources: + requests: + storage: {{ .Values.mongodb.persistence.size }} + storageClassName: {{ .Values.mongodb.persistence.storageClass }} +{{- end }} diff --git a/utils/assets/templates/mongoExpress.yaml b/utils/assets/templates/mongoExpress.yaml new file mode 100644 index 0000000..7352f9a --- /dev/null +++ b/utils/assets/templates/mongoExpress.yaml @@ -0,0 +1,18 @@ +{{- if index .Values "mongo-express" "enabled" }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: mongo-express-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/mongoexpress`) + priority: 10 + services: + - kind: Service + name: {{ .Release.Name }}-mongo-express.{{ .Release.Namespace }} + passHostHeader: true + port: 8081 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/nats.yaml b/utils/assets/templates/nats.yaml new file mode 100644 index 0000000..adcc72c --- /dev/null +++ b/utils/assets/templates/nats.yaml @@ -0,0 +1,13 @@ +{{- if index .Values.nats.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: nats-config +data: + nats.conf: | + port: 4222 + http_port: 8222 + + max_connections: 200000 # optional but recommended + max_subscriptions: 200000 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-auth/deployment.yaml b/utils/assets/templates/oc-auth/deployment.yaml new file mode 100644 index 0000000..cc40cc0 --- /dev/null +++ b/utils/assets/templates/oc-auth/deployment.yaml @@ -0,0 +1,60 @@ +{{- if .Values.ocAuth.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-auth + name: {{ .Release.Name }}-oc-auth +spec: + replicas: {{ .Values.ocAuth.replicas }} + selector: + matchLabels: + app: oc-auth + template: + metadata: + labels: + app: oc-auth + spec: + volumes: + - name: public-key-volume + secret: + secretName: public-key-secret + - name: private-key-volume + secret: + secretName: private-key-secret + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocAuth.image }}" + name: oc-auth + #command: ["tail", "-f", "/dev/null"] + volumeMounts: + - name: public-key-volume + mountPath: /keys/public/public.pem + subPath: public.pem + - name: private-key-volume + mountPath: /keys/private/private.pem + subPath: private.pem + envFrom: + - configMapRef: + name: opencloud-config + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: "{{ .Values.ocAuth.resources.limits.cpu }}" + memory: "{{ .Values.ocAuth.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocAuth.resources.requests.cpu }}" + memory: "{{ .Values.ocAuth.resources.requests.memory }}" + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-auth/ingress.yaml b/utils/assets/templates/oc-auth/ingress.yaml new file mode 100644 index 0000000..fa60206 --- /dev/null +++ b/utils/assets/templates/oc-auth/ingress.yaml @@ -0,0 +1,31 @@ +{{- if index .Values.ocAuth.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-auth-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/auth`) + priority: 10 + services: + - kind: Service + name: oc-auth-svc + port: 8080 + middlewares: + #{{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + #- name: forward-auth + #{{- end }} + - name: strip-auth-prefix +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-auth-prefix +spec: + replacePathRegex: + regex: ^/auth(.*) + replacement: /oc$1 +{{- end }} diff --git a/utils/assets/templates/oc-auth/openCloudOauth2.yaml b/utils/assets/templates/oc-auth/openCloudOauth2.yaml new file mode 100644 index 0000000..6129a93 --- /dev/null +++ b/utils/assets/templates/oc-auth/openCloudOauth2.yaml @@ -0,0 +1,36 @@ +{{- if index .Values.ocAuth.enabled }} +apiVersion: hydra.ory.sh/v1alpha1 +kind: OAuth2Client +metadata: + name: open-cloud-client +spec: + grantTypes: + - refresh_token + - authorization_code + - client_credentials + - implicit + responseTypes: + - id_token + - token + - code + scope: openid profile email roles + secretName: oc-oauth2-client-secret + redirectUris: + - https://{{ .Values.host }}/auth/callback + postLogoutRedirectUris: + - https://{{ .Values.host }}/auth/logout/ + tokenEndpointAuthMethod: client_secret_post + allowedCorsOrigins: + - "http://0.0.0.0" +#--- +#apiVersion: v1 +#kind: Secret +#metadata: +# name: oc-auth-got-secret +# namespace: dev +#stringData: +# CLIENT_ID: {{ .Values.ocAuth.hydra.clientId }} +# CLIENT_SECRET: {{ .Values.ocAuth.hydra.clientSecret }} + +{{- end }} + \ No newline at end of file diff --git a/utils/assets/templates/oc-auth/pem.yaml b/utils/assets/templates/oc-auth/pem.yaml new file mode 100644 index 0000000..33d0125 --- /dev/null +++ b/utils/assets/templates/oc-auth/pem.yaml @@ -0,0 +1,21 @@ +{{- if index .Values.ocAuth.enabled }} +# peer public key: public-key-secret.yaml +apiVersion: v1 +kind: Secret +metadata: + name: public-key-secret +type: Opaque +data: + public.pem: | + LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUNDZ0tDQWdFQXcycGRHNndNdHVMY1AwK2sxTEZ2SWIwRFFvL29IVzJ1TkphRUpLNzRwbFhxcDR6dHoyZFIKYitSUUhGTGVMdXFrNGkvemMzYjRLM2ZLUFhTbHduVlBKQ3d6UHJueVQ4allHT1pWbFdsRVRpVjl4ZUpodTZzLwpCaDZnMVBXejc1WGpqd1Y1MGl2L0NFaUxOQlQyM2YvM0o0NHdyUXp5Z3FOUUNpUVNBTGR4V0xBRWw0bDVrSFNhCjlvTXlWNzAvVXFsOTQvYXlNQVJac0hncDladnFRS2JrWlB3Nnl6Vk1mQ0J4UW96bE5sbzMxNU9IZXZ1ZGhuaHAKRFJqTjVJN3pXbXFZdDZyYlhKSkM3WTNJemR2em43UUk4OFJxalNSU1Q1SS83S3ozbmRDcXJPbkkrT1FVRTVOVApSRXlRZWJwaHZRZlREVEtsUlBYa2R5a3RkSzJESDI4Wmo2WkYzeWpRdk4zNVE0emhPemxxNzdkTzVJaGhvcEk3CmN0OGRaSDFUMW5Za3ZkeUNBL0VWTXRRc0FTbUJPaXRIMFkwQUNvWFFLNUtiNm5tL1RjTS85WlNKVU5pRU11eTUKZ0JaM1lLRTlvYTRjcFRwUFh3Y0ErUy9jVTdIUE5uUUFzdkQzaUppOEdUVzl1SnM4NHBuNC9XaHBRcW1YZDRydgpoS1dFQ0NOM2ZIeTAxZlVzL1UwUGFTajJqRFkva1FWZVhvaWtOTXpQVWpkWmQ5bTgxNlRJQmgzdjNhVlhDSC8wCmlUSEhBeGN0dkRnTVJiMmZwdlJKL3d3bllqRkc5UnBhbVZGRE12QzlOZmZ1WXpXQUE5SVJJWTRjcWdlcmZIclYKWjJISGlQVEREdkRBSXN2SW1YWmMvaDdtWE42bTNSQ1E0UXl3eTk5M3dkOWdVZGdnL3FueW5IY0NBd0VBQVE9PQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCg== +--- +# peer private key: private-key-secret.yaml +apiVersion: v1 +kind: Secret +metadata: + name: private-key-secret +type: Opaque +data: + private.pem: | + LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS1FJQkFBS0NBZ0VBdzJwZEc2d010dUxjUDArazFMRnZJYjBEUW8vb0hXMnVOSmFFSks3NHBsWHFwNHp0CnoyZFJiK1JRSEZMZUx1cWs0aS96YzNiNEszZktQWFNsd25WUEpDd3pQcm55VDhqWUdPWlZsV2xFVGlWOXhlSmgKdTZzL0JoNmcxUFd6NzVYamp3VjUwaXYvQ0VpTE5CVDIzZi8zSjQ0d3JRenlncU5RQ2lRU0FMZHhXTEFFbDRsNQprSFNhOW9NeVY3MC9VcWw5NC9heU1BUlpzSGdwOVp2cVFLYmtaUHc2eXpWTWZDQnhRb3psTmxvMzE1T0hldnVkCmhuaHBEUmpONUk3eldtcVl0NnJiWEpKQzdZM0l6ZHZ6bjdRSTg4UnFqU1JTVDVJLzdLejNuZENxck9uSStPUVUKRTVOVFJFeVFlYnBodlFmVERUS2xSUFhrZHlrdGRLMkRIMjhaajZaRjN5alF2TjM1UTR6aE96bHE3N2RPNUloaApvcEk3Y3Q4ZFpIMVQxbllrdmR5Q0EvRVZNdFFzQVNtQk9pdEgwWTBBQ29YUUs1S2I2bm0vVGNNLzlaU0pVTmlFCk11eTVnQlozWUtFOW9hNGNwVHBQWHdjQStTL2NVN0hQTm5RQXN2RDNpSmk4R1RXOXVKczg0cG40L1docFFxbVgKZDRydmhLV0VDQ04zZkh5MDFmVXMvVTBQYVNqMmpEWS9rUVZlWG9pa05NelBVamRaZDltODE2VElCaDN2M2FWWApDSC8waVRISEF4Y3R2RGdNUmIyZnB2Ukovd3duWWpGRzlScGFtVkZETXZDOU5mZnVZeldBQTlJUklZNGNxZ2VyCmZIclZaMkhIaVBURER2REFJc3ZJbVhaYy9oN21YTjZtM1JDUTRReXd5OTkzd2Q5Z1VkZ2cvcW55bkhjQ0F3RUEKQVFLQ0FnQlNSYzI5Z01vNWxYbTFEZ3NQb1VSd3ArdGZjc2IrM05halBWdVZOalZwa25LZzZDeVhUYUJ6dzJRWApDS3lTaENlM013a0VhK3BBSXNiNjZNbUEvWEs4Zi85elFVWkxZUHZhUDk5NGNFRlp4VjhXbVNFY3FoUjJ0eDV2CmlxS2ZGRFFpV3VQWElMN1c5ZlBsa1kzK0dXNHRNU2c5TTE1R3NndFl1YWI2dGtENlhlRVJDOGdxa1cxTXJCL2QKNE1kd1BmdktwbXFPM01ZR0RoRmNYckJaVitxQXVkRG5EU0dPZ1BvdVVyT09GcDI4SFZqRTVucUR5dDR2clduQgorSTFzVzhUQVR5YmI2cGhTKzRhM1pRdEZDYjliSWk3YURaaTU5NUVDVERCVU9TNGlicXMyWHBBMVRhbVk3OE5ECi9MeDVvWG14N01pNEorNXdYTjNPYWQ3eXRRdkZPZE90dElMTnBBTUZiTFU1eUtzeGYrRURqQ0JjUjVmYU5BdHUKd0FNSDlUa3pGcG1ocDVOQndRZEFrQ0ZuaHlsYTM2M2xqbWxHQVdQdUcvRDliVlowcXRCZjNOQUY0aEVKL0w0bgp2WVFGRXJkNjR0UGFzQWdXUG93MkxMdnFpM2pUMjMyYURnYWhqMWxYMWVuSG9SNlRiUUU0cjN6eThEZUE3aTBDCmhBOEdGQXZNc3FJY2VlOVhpNHlEOFFGRUgwUHJKaDZ6UDFQV0tYUjRBUVZFeG5GR2FuejBzNk8xR1JxTFBySUsKMzFOaVJUd0lWcDB4YmV0OS9Hc0p4V3hxclRLUHFkNXlKdlVHRzNBNEVMOGUzUmRXUk01dlRIYk5DVkdpOUxoUwozT0lYVjkvWU9RSnRXeHpXVWpGTjNIcGFOdVdIVlNSMTQ5R0FZcFR4ZWgrL1pHb0FRUUtDQVFFQTlSekcwTHJCCi9vblNuemZBWEQ1SXdHVy9qU2I0ZThWTENaLzdXMENpRDFodDIzUTFwQVI0Ym9mU1lYZHgvcmhWaFJ0eSszOHEKR3p1Z0JQY2VqR2VHWXlLSVZpTzFlOFBzcmQ2ZHlkWW9hQTlmWDNZemNaMG9uazl0K3RZTnhWaHN0b2xmSUdnYwpLVzFxd0ROclYxUFAwTi9vUVU0UVB4TG13Y2YvQlNTbDNzZjUzbVZNemNuSGtqQ0Y1U2dFTjFydElBT1VaYU04CkI0dXJTU01aTUxwd21oWEY5ckFVUFhXZ0xTKzBma3JRem9hQlMyWmZxRWNGTnMxbG44c1RCZW9YQXo2a3laZW0KMFRvMW9ZaFRlTitUZzExcXVXaEpLaVRNWW1TR1QzQjduVnQyNW4wQnlwRGt0ZmFVVStMTVk5L0Jld1d3RTZ4eAppWDk3YmxkZ3Y2eTR1d0tDQVFFQXpCaDVJWWEwOXVKVHdyeFkwSUtWZmtYUnAyUys4ZnFoSjVxaEVQeWtDRis0CkpKQktQcDdJQTdyaGNmNXR3M05WcGEvWUUxaDJIMVA1WjRFUWt6Z0VURXhWb3RCbE9ZWU5ta0JrZDlldFVSR3MKb21BUEhwcm52VDdxK2RSL3JjOC9sUXQzWHp2ZWo0UDR6U1JibnpnL3EySzBJMXFzM3ZPd25aeU8zR1hrNmVuaQpRNTlrMHk4em9zS2RkZTdtMVlKK0tBajVNWmMzUGVIVGZiTGFMY2ZYblRTVVg2eHduWCtKczhrcjJQVlArd1NqCnNFeGFrUDZpZU51L1p6RmNZdjZhaVBneVhJV08vNXBqd0x0L0dUcVVQUWNPOVc3Nm0wdzI0bFduWUN4MWl5U3cKYWxybDJpckwycm5sWEppbjdxNEZ0dEhUV2JlSDkwUlZ0MzA1MG04ZGRRS0NBUUVBa2d5bGduWGxaYytsaW0xagoxeExkc3BadC9xTTc2RFAwdERWNVJqUkszQzNxdDVxVTQ3Z3VNbDRId3oreTB2M3ZKekxsM21rMUk2anhma1BwCkZld1JyVHhFVkY5T29nSnFJbWZGU1NDc1R1VHFCUzJmRlpGNVJHczdzdnljay94T09xMjcyc2x1RGxrK0JHd2YKQjVmTytqeVFYV2t3VVFUb0xvc0dyMy9ZdmRnV1VLZTNqZDh2WlRJNGRnVFVEay9GZncvaStuUzdMaHZRNGZGaAo3eUVJT3lmQ0gyMW5nZjkyZzdZckxCMVVNZHIvYTNnQ2czaGQ2UHVXRkJLaXNTRjh1Tmc0eEUzeWZqVGJBL2NCCkZjTFNXTEh2QjY3VithQ1hrQUVwN21ldG9HT0JnM0QxQWtnM254emY0T1FBdVhuNEJWK3NQT3pCY2haZDY2OXcKM0lVRVJRS0NBUUJ4UEU3UWpCV1JPS2N5VHgrVHFDL2JIRStpNlNHTHpmdGxwc1FnVVp1TXpkYXo2cDVXdWUvTgpLZjExS3EycG1DNzN1MlZON25HekZmczFNd1dJT0xjaHdlUnRiZVFMazFXdXRIVkpqSThyZ0h2Z3B4MGNaT09ZCk92VlI0VlZwa0tmOVFKeGRhVEVsUFJwb2J2aXFrU0c2TEF3MzVWSXViTlFiemtYeEFGT09lR1pDRUloM0p5UWwKOUlZNmJXOERIT0J6dys3R1ZkaWZhOURVVjh2M1JINWJTVlhjOHlhVUs3T3gzVGFIckN0UTRSVVVkbmgxSStIdQozalVHd3ZzNExYeDk2LzY5R0pqck5iU010VHBpTy84TkVRSjZwN1ZCUG5yZy9wYmJwQzhmSVI4RUV5U2Q4OHFnCnN5MFBQOTlFYktiYzlQT25QazJnb2ZoUTBwaW5LV0VWQW9JQkFRQzBoOEozbEdTRzlLaTlRSnZBT2RNcW5zU2cKdW9xakkweTZSbWVSN0xwWVgxQVNLTk5JbWpHMWh3THlaOFFnNWhDTmp5U0VxQkFHR2QzTUJOZklDNnd6QkRyVgp6U0pJcnhqdnUrMnNmejFuVUdkWVdqUWZoeDNjVCt5R3FUNk5FUXVwbXN0TnVreGl1MkhEdTc2cGk5NkFYMm1rClRYWVhsdWJJcGZMNTBkV1owd2lqMExpdkg2VFBhdnZqYlJablhOVnRoMXFsWk9VdHVCR3lFd2NYYjRDT3RxUnEKK25QOEFFZ3pLeGJNSkZWeTNQWTVFNUp5akI1ZDFaUFEyT2VZVVZiZkRFRVlxemtvcmpCeUNjTGR2N08xQ0hOcQpWalV5SnNkOEYxdHVDR1B4YmNiZ3lDZUlxZ0RNMUp4TzR6VE1TUCtDODJBcjdWWGtyNlE4aEFzQ2dIUS8KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-auth/rbac.yaml b/utils/assets/templates/oc-auth/rbac.yaml new file mode 100644 index 0000000..400a0c9 --- /dev/null +++ b/utils/assets/templates/oc-auth/rbac.yaml @@ -0,0 +1,31 @@ +{{- if .Values.ocAuth.enabled }} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: secret-reader-role +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: secret-reader-binding + namespace: default +subjects: + - kind: ServiceAccount + name: ocauth-sa + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: secret-reader-role + apiGroup: rbac.authorization.k8s.io +--- +kind: ServiceAccount +apiVersion: v1 +metadata: + name: ocauth-sa +{{- end }} + diff --git a/utils/assets/templates/oc-auth/service.yaml b/utils/assets/templates/oc-auth/service.yaml new file mode 100644 index 0000000..9fe7d60 --- /dev/null +++ b/utils/assets/templates/oc-auth/service.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ocAuth.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-auth-svc + labels: + app: oc-auth-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-auth + type: ClusterIP +{{- end }} + +{{- if and .Values.ocAuth.enabled .Values.ocAuth.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-auth +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-auth + minReplicas: {{ .Values.ocAuth.hpa.minReplicas }} + maxReplicas: {{ .Values.ocAuth.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocAuth.hpa.targetCPUUtilizationPercentage }} +{{- end }} diff --git a/utils/assets/templates/oc-catalog/deployment.yaml b/utils/assets/templates/oc-catalog/deployment.yaml new file mode 100644 index 0000000..647d8b8 --- /dev/null +++ b/utils/assets/templates/oc-catalog/deployment.yaml @@ -0,0 +1,45 @@ +{{- if .Values.ocCatalog.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-catalog + name: {{ .Release.Name }}-oc-catalog +spec: + replicas: {{ .Values.ocCatalog.replicas }} + selector: + matchLabels: + app: oc-catalog + template: + metadata: + labels: + app: oc-catalog + spec: + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocCatalog.image }}" + name: oc-catalog + envFrom: + - configMapRef: + name: opencloud-config + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: "{{ .Values.ocCatalog.resources.limits.cpu }}" + memory: "{{ .Values.ocCatalog.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocCatalog.resources.requests.cpu }}" + memory: "{{ .Values.ocCatalog.resources.requests.memory }}" + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-catalog/ingress.yaml b/utils/assets/templates/oc-catalog/ingress.yaml new file mode 100644 index 0000000..d6dc1b5 --- /dev/null +++ b/utils/assets/templates/oc-catalog/ingress.yaml @@ -0,0 +1,32 @@ +{{- if index .Values.ocCatalog.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-catalog-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/catalog`) + priority: 10 + services: + - kind: Service + name: oc-catalog-svc + port: 8080 + middlewares: + {{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + - name: forward-auth + {{- end }} + - name: strip-catalog-prefix + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-catalog-prefix +spec: + replacePathRegex: + regex: ^/catalog(.*) + replacement: /oc$1 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-catalog/service.yaml b/utils/assets/templates/oc-catalog/service.yaml new file mode 100644 index 0000000..3a8dc4d --- /dev/null +++ b/utils/assets/templates/oc-catalog/service.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ocCatalog.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-catalog-svc + labels: + app: oc-catalog-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-catalog + type: ClusterIP +{{- end }} + +{{- if and .Values.ocCatalog.enabled .Values.ocCatalog.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-catalog +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-catalog + minReplicas: {{ .Values.ocCatalog.hpa.minReplicas }} + maxReplicas: {{ .Values.ocCatalog.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocCatalog.hpa.targetCPUUtilizationPercentage }} +{{- end }} diff --git a/utils/assets/templates/oc-datacenter/deployment.yaml b/utils/assets/templates/oc-datacenter/deployment.yaml new file mode 100644 index 0000000..c2ec0fc --- /dev/null +++ b/utils/assets/templates/oc-datacenter/deployment.yaml @@ -0,0 +1,45 @@ +{{- if .Values.ocDatacenter.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-datacenter + name: {{ .Release.Name }}-oc-datacenter +spec: + replicas: {{ .Values.ocDatacenter.replicas }} + selector: + matchLabels: + app: oc-datacenter + template: + metadata: + labels: + app: oc-datacenter + spec: + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocDatacenter.image }}" + name: oc-datacenter + envFrom: + - configMapRef: + name: opencloud-config + ports: + - name: http + containerPort: 8080 + protocol: TCP + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 + resources: + limits: + cpu: "{{ .Values.ocDatacenter.resources.limits.cpu }}" + memory: "{{ .Values.ocDatacenter.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocDatacenter.resources.requests.cpu }}" + memory: "{{ .Values.ocDatacenter.resources.requests.memory }}" + {{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-datacenter/ingress.yaml b/utils/assets/templates/oc-datacenter/ingress.yaml new file mode 100644 index 0000000..d91cbe0 --- /dev/null +++ b/utils/assets/templates/oc-datacenter/ingress.yaml @@ -0,0 +1,32 @@ +{{- if index .Values.ocDatacenter.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-datacenter-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/datacenter`) + priority: 10 + services: + - kind: Service + name: oc-datacenter-svc + port: 8080 + middlewares: + - name: strip-datacenter-prefix + {{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + - name: forward-auth + {{- end }} + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-datacenter-prefix +spec: + replacePathRegex: + regex: ^/datacenter(.*) + replacement: /oc$1 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-datacenter/service.yaml b/utils/assets/templates/oc-datacenter/service.yaml new file mode 100644 index 0000000..9b762ec --- /dev/null +++ b/utils/assets/templates/oc-datacenter/service.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ocDatacenter.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-datacenter-svc + labels: + app: oc-datacenter-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-datacenter + type: ClusterIP +{{- end }} + + +{{- if and .Values.ocDatacenter.enabled .Values.ocDatacenter.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-datacenter +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-datacenter + minReplicas: {{ .Values.ocDatacenter.hpa.minReplicas }} + maxReplicas: {{ .Values.ocDatacenter.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocDatacenter.hpa.targetCPUUtilizationPercentage }} +{{- end }} diff --git a/utils/assets/templates/oc-front/deployment.yaml b/utils/assets/templates/oc-front/deployment.yaml new file mode 100644 index 0000000..948fd23 --- /dev/null +++ b/utils/assets/templates/oc-front/deployment.yaml @@ -0,0 +1,50 @@ +{{- if .Values.ocFront.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-front + name: {{ .Release.Name }}-oc-front +spec: + replicas: {{ .Values.ocFront.replicas }} + selector: + matchLabels: + app: oc-front + template: + metadata: + labels: + app: oc-front + spec: + volumes: + - name: config-volume + configMap: + name: front-config + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocFront.image }}" + name: oc-front + ports: + - name: http + containerPort: 80 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 10 + periodSeconds: 30 + resources: + limits: + cpu: "{{ .Values.ocFront.resources.limits.cpu }}" + memory: "{{ .Values.ocFront.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocFront.resources.requests.cpu }}" + memory: "{{ .Values.ocFront.resources.requests.memory }}" + volumeMounts: + - name: config-volume + mountPath: /usr/share/nginx/html/assets/assets/config/front.json + subPath: config.json +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-front/ingress.yaml b/utils/assets/templates/oc-front/ingress.yaml new file mode 100644 index 0000000..550df7b --- /dev/null +++ b/utils/assets/templates/oc-front/ingress.yaml @@ -0,0 +1,17 @@ +{{- if index .Values.ocFront.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-front-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/`) + priority: 5 + services: + - kind: Service + name: oc-front-svc + port: 8080 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-front/service.yaml b/utils/assets/templates/oc-front/service.yaml new file mode 100644 index 0000000..a090def --- /dev/null +++ b/utils/assets/templates/oc-front/service.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ocFront.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-front-svc + labels: + app: oc-front-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 80 + selector: + app: oc-front + type: ClusterIP +{{- end }} + +{{- if and .Values.ocFront.enabled .Values.ocFront.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-front +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-front + minReplicas: {{ .Values.ocFront.hpa.minReplicas }} + maxReplicas: {{ .Values.ocFront.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocFront.hpa.targetCPUUtilizationPercentage }} +{{- end }} diff --git a/utils/assets/templates/oc-peer/deployment.yaml b/utils/assets/templates/oc-peer/deployment.yaml new file mode 100644 index 0000000..c7dd390 --- /dev/null +++ b/utils/assets/templates/oc-peer/deployment.yaml @@ -0,0 +1,45 @@ +{{- if .Values.ocPeer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-peer + name: {{ .Release.Name }}-oc-peer +spec: + replicas: {{ .Values.ocPeer.replicas }} + selector: + matchLabels: + app: oc-peer + template: + metadata: + labels: + app: oc-peer + spec: + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocPeer.image }}" + name: oc-peer + envFrom: + - configMapRef: + name: opencloud-config + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: "{{ .Values.ocPeer.resources.limits.cpu }}" + memory: "{{ .Values.ocPeer.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocPeer.resources.requests.cpu }}" + memory: "{{ .Values.ocPeer.resources.requests.memory }}" + {{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-peer/ingress.yaml b/utils/assets/templates/oc-peer/ingress.yaml new file mode 100644 index 0000000..72b376f --- /dev/null +++ b/utils/assets/templates/oc-peer/ingress.yaml @@ -0,0 +1,33 @@ +{{- if index .Values.ocPeer.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-peer-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/peer`) + priority: 10 + services: + - kind: Service + name: oc-peer-svc + port: 8080 + middlewares: + {{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + - name: forward-auth + {{- end }} + - name: strip-peer-prefix + + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-peer-prefix +spec: + replacePathRegex: + regex: ^/peer(.*) + replacement: /oc$1 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-peer/service.yaml b/utils/assets/templates/oc-peer/service.yaml new file mode 100644 index 0000000..ef85005 --- /dev/null +++ b/utils/assets/templates/oc-peer/service.yaml @@ -0,0 +1,40 @@ +{{- if index .Values.ocPeer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-peer-svc + labels: + app: oc-peer-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-peer + type: ClusterIP +{{- end }} + +{{- if and .Values.ocPeer.enabled .Values.ocPeer.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-peer +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-peer + minReplicas: {{ .Values.ocPeer.hpa.minReplicas }} + maxReplicas: {{ .Values.ocPeer.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocPeer.hpa.targetCPUUtilizationPercentage }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-scheduler/deployment.yaml b/utils/assets/templates/oc-scheduler/deployment.yaml new file mode 100644 index 0000000..2eb91ae --- /dev/null +++ b/utils/assets/templates/oc-scheduler/deployment.yaml @@ -0,0 +1,46 @@ +{{- if index .Values.ocScheduler.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-scheduler + name: {{ .Release.Name }}-oc-scheduler +spec: + replicas: {{ .Values.ocScheduler.replicas }} + selector: + matchLabels: + app: oc-scheduler + template: + metadata: + labels: + app: oc-scheduler + spec: + serviceAccountName: scheduler-sa + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocScheduler.image }}" + name: oc-scheduler + envFrom: + - configMapRef: + name: opencloud-config + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: "{{ .Values.ocScheduler.resources.limits.cpu }}" + memory: "{{ .Values.ocScheduler.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocScheduler.resources.requests.cpu }}" + memory: "{{ .Values.ocScheduler.resources.requests.memory }}" + {{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-scheduler/ingress.yaml b/utils/assets/templates/oc-scheduler/ingress.yaml new file mode 100644 index 0000000..03e8c4f --- /dev/null +++ b/utils/assets/templates/oc-scheduler/ingress.yaml @@ -0,0 +1,33 @@ +{{- if index .Values.ocScheduler.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-scheduler-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/scheduler`) + priority: 10 + services: + - kind: Service + name: oc-scheduler-svc + port: 8080 + middlewares: + - name: strip-scheduler-prefix + {{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + - name: forward-auth + {{- end }} + + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-scheduler-prefix +spec: + replacePathRegex: + regex: ^/scheduler(.*) + replacement: /oc$1 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-scheduler/sa.yaml b/utils/assets/templates/oc-scheduler/sa.yaml new file mode 100644 index 0000000..ea7c5f5 --- /dev/null +++ b/utils/assets/templates/oc-scheduler/sa.yaml @@ -0,0 +1,41 @@ +{{- if index .Values.ocScheduler.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: scheduler-sa + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: scheduler-sa-clusterrole +rules: + # Permissions for Argo Workflow resources + - apiGroups: ["argoproj.io"] + resources: + - workflows + - workflowtemplates + - cronworkflows + - clusterworkflowtemplates + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: scheduler-sa-clusterrolebinding +subjects: + - kind: ServiceAccount + name: scheduler-sa + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: scheduler-sa-clusterrole +{{- end }} diff --git a/utils/assets/templates/oc-scheduler/service.yaml b/utils/assets/templates/oc-scheduler/service.yaml new file mode 100644 index 0000000..b37909a --- /dev/null +++ b/utils/assets/templates/oc-scheduler/service.yaml @@ -0,0 +1,40 @@ +{{- if index .Values.ocScheduler.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-scheduler-svc + labels: + app: oc-scheduler-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-scheduler + type: ClusterIP +{{- end }} + +{{- if and .Values.ocScheduler.enabled .Values.ocScheduler.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-scheduler +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-scheduler + minReplicas: {{ .Values.ocScheduler.hpa.minReplicas }} + maxReplicas: {{ .Values.ocScheduler.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocScheduler.hpa.targetCPUUtilizationPercentage }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-schedulerd/deployment.yaml b/utils/assets/templates/oc-schedulerd/deployment.yaml new file mode 100644 index 0000000..c0e347b --- /dev/null +++ b/utils/assets/templates/oc-schedulerd/deployment.yaml @@ -0,0 +1,35 @@ +{{- if index .Values.ocSchedulerd.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-schedulerd + name: {{ .Release.Name }}-oc-schedulerd +spec: + replicas: {{ .Values.ocSchedulerd.replicas }} + selector: + matchLabels: + app: oc-schedulerd + template: + metadata: + labels: + app: oc-schedulerd + spec: + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocSchedulerd.image }}" + name: oc-schedulerd + envFrom: + - configMapRef: + name: opencloud-config + resources: + limits: + cpu: "{{ .Values.ocSchedulerd.resources.limits.cpu }}" + memory: "{{ .Values.ocSchedulerd.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocSchedulerd.resources.requests.cpu }}" + memory: "{{ .Values.ocSchedulerd.resources.requests.memory }}" + {{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-schedulerd/service.yaml b/utils/assets/templates/oc-schedulerd/service.yaml new file mode 100644 index 0000000..2e8073b --- /dev/null +++ b/utils/assets/templates/oc-schedulerd/service.yaml @@ -0,0 +1,40 @@ +{{- if index .Values.ocSchedulerd.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-schedulerd-svc + labels: + app: oc-schedulerd-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-scheduler + type: ClusterIP +{{- end }} + +{{- if and .Values.ocSchedulerd.enabled .Values.ocSchedulerd.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-schedulerd +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-schedulerd + minReplicas: {{ .Values.ocSchedulerd.hpa.minReplicas }} + maxReplicas: {{ .Values.ocSchedulerd.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocSchedulerd.hpa.targetCPUUtilizationPercentage }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-shared/deployment.yaml b/utils/assets/templates/oc-shared/deployment.yaml new file mode 100644 index 0000000..2ed533d --- /dev/null +++ b/utils/assets/templates/oc-shared/deployment.yaml @@ -0,0 +1,45 @@ +{{- if .Values.ocShared.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-shared + name: {{ .Release.Name }}-oc-shared +spec: + replicas: {{ .Values.ocShared.replicas }} + selector: + matchLabels: + app: oc-shared + template: + metadata: + labels: + app: oc-shared + spec: + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocShared.image }}" + name: oc-shared + envFrom: + - configMapRef: + name: opencloud-config + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: "{{ .Values.ocShared.resources.limits.cpu }}" + memory: "{{ .Values.ocShared.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocShared.resources.requests.cpu }}" + memory: "{{ .Values.ocShared.resources.requests.memory }}" + {{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-shared/ingress.yaml b/utils/assets/templates/oc-shared/ingress.yaml new file mode 100644 index 0000000..83c956e --- /dev/null +++ b/utils/assets/templates/oc-shared/ingress.yaml @@ -0,0 +1,32 @@ +{{- if index .Values.ocShared.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-shared-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/shared`) + priority: 10 + services: + - kind: Service + name: oc-shared-svc + port: 8080 + middlewares: + - name: strip-shared-prefix + {{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + - name: forward-auth + {{- end }} + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-shared-prefix +spec: + replacePathRegex: + regex: ^/shared(.*) + replacement: /oc$1 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-shared/service.yaml b/utils/assets/templates/oc-shared/service.yaml new file mode 100644 index 0000000..1125733 --- /dev/null +++ b/utils/assets/templates/oc-shared/service.yaml @@ -0,0 +1,40 @@ +{{- if index .Values.ocShared.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-shared-svc + labels: + app: oc-shared-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-shared + type: ClusterIP +{{- end }} + +{{- if and .Values.ocShared.enabled .Values.ocShared.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-shared +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-shared + minReplicas: {{ .Values.ocShared.hpa.minReplicas }} + maxReplicas: {{ .Values.ocShared.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocShared.hpa.targetCPUUtilizationPercentage }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-workflow/deployment.yaml b/utils/assets/templates/oc-workflow/deployment.yaml new file mode 100644 index 0000000..230f431 --- /dev/null +++ b/utils/assets/templates/oc-workflow/deployment.yaml @@ -0,0 +1,45 @@ +{{- if .Values.ocWorkflow.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-workflow + name: {{ .Release.Name }}-oc-workflow +spec: + replicas: {{ .Values.ocWorkflow.replicas }} + selector: + matchLabels: + app: oc-workflow + template: + metadata: + labels: + app: oc-workflow + spec: + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + containers: + - image: "{{ .Values.ocWorkflow.image }}" + name: oc-shared + envFrom: + - configMapRef: + name: opencloud-config + ports: + - name: http + containerPort: 8080 + protocol: TCP + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 + resources: + limits: + cpu: "{{ .Values.ocWorkflow.resources.limits.cpu }}" + memory: "{{ .Values.ocWorkflow.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocWorkflow.resources.requests.cpu }}" + memory: "{{ .Values.ocWorkflow.resources.requests.memory }}" + {{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-workflow/ingress.yaml b/utils/assets/templates/oc-workflow/ingress.yaml new file mode 100644 index 0000000..fc0e85e --- /dev/null +++ b/utils/assets/templates/oc-workflow/ingress.yaml @@ -0,0 +1,33 @@ +{{- if index .Values.ocWorkflow.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-workflow-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/workflow`) + priority: 10 + services: + - kind: Service + name: oc-workflow-svc + port: 8080 + middlewares: + - name: strip-workflow-prefix + {{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + - name: forward-auth + {{- end }} + + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-workflow-prefix +spec: + replacePathRegex: + regex: ^/workflow(.*) + replacement: /oc$1 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-workflow/service.yaml b/utils/assets/templates/oc-workflow/service.yaml new file mode 100644 index 0000000..479f81b --- /dev/null +++ b/utils/assets/templates/oc-workflow/service.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ocWorkflow.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-workflow-svc + labels: + app: oc-workflow-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-workflow + type: ClusterIP +{{- end }} + +{{- if and .Values.ocWorkflow.enabled .Values.ocWorkflow.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-workflow +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-workflow + minReplicas: {{ .Values.ocWorkflow.hpa.minReplicas }} + maxReplicas: {{ .Values.ocWorkflow.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocWorkflow.hpa.targetCPUUtilizationPercentage }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-workspace/deployment.yaml b/utils/assets/templates/oc-workspace/deployment.yaml new file mode 100644 index 0000000..f3a4d09 --- /dev/null +++ b/utils/assets/templates/oc-workspace/deployment.yaml @@ -0,0 +1,46 @@ +{{- if index .Values.ocWorkspace.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-workspace + name: {{ .Release.Name }}-oc-workspace +spec: + replicas: {{ .Values.ocWorkspace.replicas }} + selector: + matchLabels: + app: oc-workspace + template: + metadata: + labels: + app: oc-workspace + spec: + containers: + - image: "{{ .Values.ocWorkspace.image }}" + name: oc-workspace + envFrom: + - configMapRef: + name: opencloud-config + ports: + - name: http + containerPort: 8080 + protocol: TCP + livenessProbe: + httpGet: + path: /oc/version + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 30 + resources: + limits: + cpu: "{{ .Values.ocWorkspace.resources.limits.cpu }}" + memory: "{{ .Values.ocWorkspace.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ocWorkspace.resources.requests.cpu }}" + memory: "{{ .Values.ocWorkspace.resources.requests.memory }}" + {{- if or (eq .Values.env "prod") (eq .Values.env "staging") }} + imagePullSecrets: + - name: regcred + {{- end }} + + {{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-workspace/ingress.yaml b/utils/assets/templates/oc-workspace/ingress.yaml new file mode 100644 index 0000000..015b0a5 --- /dev/null +++ b/utils/assets/templates/oc-workspace/ingress.yaml @@ -0,0 +1,32 @@ +{{- if index .Values.ocWorkspace.enabled }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: oc-workspace-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/workspace`) + priority: 10 + services: + - kind: Service + name: oc-workspace-svc + port: 8080 + middlewares: + - name: strip-workspace-prefix + {{- if index .Values.ocAuth.enableTraefikProxyIntegration }} + - name: forward-auth + {{- end }} + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-workspace-prefix +spec: + replacePathRegex: + regex: ^/workspace(.*) + replacement: /oc$1 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/oc-workspace/service.yaml b/utils/assets/templates/oc-workspace/service.yaml new file mode 100644 index 0000000..09552d7 --- /dev/null +++ b/utils/assets/templates/oc-workspace/service.yaml @@ -0,0 +1,40 @@ +{{- if index .Values.ocWorkspace.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: oc-workspace-svc + labels: + app: oc-workspace-svc +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: oc-workspace + type: ClusterIP +{{- end }} + +{{- if and .Values.ocWorkspace.enabled .Values.ocWorkspace.hpa.enabled }} +--- +# Horizontal Pod Autoscaler +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Release.Name }}-oc-workspace +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Release.Name }}-oc-workspace + minReplicas: {{ .Values.ocWorkspace.hpa.minReplicas }} + maxReplicas: {{ .Values.ocWorkspace.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ocWorkspace.hpa.targetCPUUtilizationPercentage }} +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/openCloudConf.yaml b/utils/assets/templates/openCloudConf.yaml new file mode 100644 index 0000000..0a5963e --- /dev/null +++ b/utils/assets/templates/openCloudConf.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: opencloud-config +data: + OC_NAMESPACE: "{{ .Release.Namespace }}" + OC_ADMIN_ROLE: "{{ .Values.ocAuth.keto.adminRole }}" + OC_PUBLIC_KEY_PATH: "/keys/public/public.pem" + OC_PRIVATE_KEY_PATH: "/keys/private/private.pem" + OC_OAUTH2_CLIENT_SECRET_NAME: "{{ .Values.ocAuth.hydra.openCloudOauth2ClientSecretName }}" + OC_AUTH: "{{ .Values.ocAuth.authType }}" + OC_AUTH_CONNECTOR_HOST: "{{ .Release.Name }}-hydra-admin.{{ .Release.Namespace }}" + OC_AUTH_CONNECTOR_PUBLIC_HOST: "{{ .Release.Name }}-hydra-public.{{ .Release.Namespace }}" + OC_AUTH_CONNECTOR_PORT: "4444" + OC_AUTH_CONNECTOR_ADMIN_PORT: "4445/admin" + OC_PERMISSION_CONNECTOR_READ_HOST: "{{ .Release.Name }}-keto-read.{{ .Release.Namespace }}" + OC_PERMISSION_CONNECTOR_WRITE_HOST: "{{ .Release.Name }}-keto-write.{{ .Release.Namespace }}" + OC_PERMISSION_CONNECTOR_PORT: "80" + OC_PERMISSION_CONNECTOR_ADMIN_PORT: "80/admin" + OC_LDAP_ENDPOINTS: "{{ .Release.Name }}-openldap.{{ .Release.Namespace }}.svc.cluster.local:389" + OC_LDAP_BINDDN: "{{ index .Values.ocAuth.ldap.bindDn }}" + OC_LDAP_BINDPW: "{{ index .Values.ocAuth.ldap.binPwd }}" + OC_LDAP_BASEDN: "{{ index .Values.ocAuth.ldap.baseDn }}" + OC_LDAP_ROLE_BASEDN: "{{ index .Values.ocAuth.ldap.roleBaseDn }}" + OC_MONGO_URL: "mongodb://{{ index .Values.mongodb.auth.rootUser }}:{{ index .Values.mongodb.auth.rootPassword }}@{{ .Release.Name }}-mongodb.{{ .Release.Namespace }}:27017/{{ index .Values.mongodb.auth.databases 0 }}" + OC_MONGO_DATABASE: "{{ index .Values.mongodb.auth.databases 0 }}" + OC_NATS_URL: "nats://{{ .Release.Name }}-nats.{{ .Release.Namespace }}.svc.cluster.local:4222" + OC_LOKI_URL: "http://loki-headless.{{ .Release.Namespace }}.svc.cluster.local:3100" + OC_PROMETHEUS_URL: "http://{{ .Release.Name }}-monitor.{{ .Release.Namespace }}:9090" \ No newline at end of file diff --git a/utils/assets/templates/openldap.yaml b/utils/assets/templates/openldap.yaml new file mode 100644 index 0000000..5daf178 --- /dev/null +++ b/utils/assets/templates/openldap.yaml @@ -0,0 +1,27 @@ +{{- if .Values.openldap.externalLDAP.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: oc-openldap + name: {{ .Release.Name }}-oc-openldap +spec: + replicas: 1 + template: + spec: + containers: + - name: oc-openldap + image: {{ .Values.openldap.image.repository }} + env: + - name: LDAP_ORGANISATION + value: {{ .Values.openldap.env.LDAP_ORGANISATION }} + - name: LDAP_DOMAIN + value: {{ .Values.openldap.env.LDAP_DOMAIN }} + volumeMounts: + - name: ldif + mountPath: /container/service/slapd/assets/config/bootstrap/ldif/external + volumes: + - name: ldif + configMap: + name: openldap-ldif +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/prometheus.yaml b/utils/assets/templates/prometheus.yaml new file mode 100644 index 0000000..93aa59f --- /dev/null +++ b/utils/assets/templates/prometheus.yaml @@ -0,0 +1,18 @@ +{{- if index .Values "prometheus" "enabled" }} +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: prometheus-ingress +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.host }}`) && PathPrefix(`/monitor`) + priority: 10 + services: + - kind: Service + name: {{ .Release.Name }}-monitor.{{ .Release.Namespace }} + passHostHeader: true + port: 9090 +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/registry/docker-registry.yaml b/utils/assets/templates/registry/docker-registry.yaml new file mode 100644 index 0000000..08e7b7a --- /dev/null +++ b/utils/assets/templates/registry/docker-registry.yaml @@ -0,0 +1,86 @@ +{{- if index .Values "docker-registry-ui" "enabled" }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ index .Values "docker-registry-ui" "registry" "dataVolume" "persistentVolumeClaim" "claimName" }} + namespace: {{ .Release.Namespace }} + annotations: + helm.sh/resource-policy: keep +spec: + accessModes: + - {{ index .Values "docker-registry-ui" "registry" "persistence" "accessMode" }} + resources: + requests: + storage: {{ index .Values "docker-registry-ui" "registry" "persistence" "storage" }} + storageClassName: {{ index .Values "docker-registry-ui" "registry" "persistence" "storageClassName" }} +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: registry-ingress + namespace: {{ .Release.Namespace }} +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.registryHost }}`) + priority: 5 + services: + - kind: Service + name: {{ .Values.env }}-docker-registry-ui-registry-server + namespace: {{ .Release.Namespace }} + port: 5000 +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: registry-ingress-ui + namespace: {{ .Release.Namespace }} +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`{{ .Values.registryHost }}`) && PathPrefix(`/ui`) + priority: 10 + services: + - kind: Service + name: {{ .Values.env }}-docker-registry-ui-user-interface + namespace: {{ .Release.Namespace }} + port: 80 + middlewares: + - name: strip-ui-prefix + +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: strip-ui-prefix + namespace: {{ .Release.Namespace }} +spec: + stripPrefix: + prefixes: + - "/ui" +--- +#for htpasswd: +#htpasswd -nbB opencloud_registry Cei9phee | tr -d '\n' | base64 -w 0 +#for password in dockerconfigjson: +#echo "opencloud_registry:Cei9phee" | tr -d '\n' | base64 -w 0 +apiVersion: v1 +kind: Secret +metadata: + name: registry-basic-auth-secret #To configure docker server authentication + namespace: {{ .Release.Namespace }} +data: + htpasswd: b3BlbmNsb3VkX3JlZ2lzdHJ5OiQyeSQwNSQ0cjFtV0h0Q3IzTmNPLjhqZjV2TkNPdkUvcFBkTDBmd1NFMkJ6bnI2azlmLjZhaVRHLzE1cQ== +--- +apiVersion: v1 +kind: Secret +type: kubernetes.io/dockerconfigjson +metadata: + name: {{ index .Values "docker-registry-ui" "registry" "secretName" }} #To configure docker client authentication against the server + namespace: {{ .Release.Namespace }} +data: + .dockerconfigjson: ewoJImF1dGhzIjogewoJCSJyZWdpc3RyeS12YWFzLnBmLmlydC1zYWludGV4dXBlcnkuY29tIjogewoJCQkiYXV0aCI6ICJkbUZoYzE5eVpXZHBjM1J5ZVRva01ua2tNRFVrYjJFeFRFaERjVGw2TWs1WE55NVJjMlZFYVZjMFpUQjVSSGxsTDIxTFp5NUxValJPYkVGR1pqTlpkbnBaZW0weVdFRXlNaTQ9IgoJCX0KCX0KfQ== +{{- end }} diff --git a/utils/assets/templates/registry/dockerconfigjson b/utils/assets/templates/registry/dockerconfigjson new file mode 100644 index 0000000..e9b9bf6 --- /dev/null +++ b/utils/assets/templates/registry/dockerconfigjson @@ -0,0 +1,7 @@ +{ + "auths": { + "registry-vaas.pf.irt-saintexupery.com": { + "auth": "dmFhc19yZWdpc3RyeTokMnkkMDUkb2ExTEhDcTl6Mk5XNy5Rc2VEaVc0ZTB5RHllL21LZy5LUjRObEFGZjNZdnpZem0yWEEyMi4=" + } + } +} \ No newline at end of file diff --git a/utils/assets/templates/sc-longhorn-nor1.yaml b/utils/assets/templates/sc-longhorn-nor1.yaml new file mode 100644 index 0000000..37e5c69 --- /dev/null +++ b/utils/assets/templates/sc-longhorn-nor1.yaml @@ -0,0 +1,10 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: longhorn-nor1 +provisioner: driver.longhorn.io +parameters: + numberOfReplicas: "2" # set 1 for single-node testing +reclaimPolicy: Retain +allowVolumeExpansion: true +volumeBindingMode: Immediate diff --git a/utils/assets/templates/storageClass.yaml b/utils/assets/templates/storageClass.yaml new file mode 100644 index 0000000..06ac3e8 --- /dev/null +++ b/utils/assets/templates/storageClass.yaml @@ -0,0 +1,11 @@ +{{- if eq .Values.env "dev" }} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: kind-sc + annotations: + helm.sh/resource-policy: keep +provisioner: rancher.io/local-path +reclaimPolicy: Retain +volumeBindingMode: WaitForFirstConsumer +{{- end }} \ No newline at end of file diff --git a/utils/assets/templates/traefik.yaml b/utils/assets/templates/traefik.yaml new file mode 100644 index 0000000..24b7c92 --- /dev/null +++ b/utils/assets/templates/traefik.yaml @@ -0,0 +1,8 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: forward-auth +spec: + forwardAuth: + address: "http://oc-auth-svc.{{ .Release.Namespace }}:8080/oc/forward" + trustForwardHeader: true diff --git a/utils/assets/values.yaml.template b/utils/assets/values.yaml.template new file mode 100644 index 0000000..fb0898f --- /dev/null +++ b/utils/assets/values.yaml.template @@ -0,0 +1,613 @@ +env: ${RELEASE:-prod} # For storage class provisioning +clusterName: ${CLUSTER_NAME:-opencloud} +host: ${HOST:-beta.opencloud.com} +registryHost: ${REGISTRY_HOST:-oc} # For reverse proxy rule +scheme: https # For reverse proxy rule + +mongo-express: + enabled: ${OC_MONGOEXPRESS_ENABLED:-true} + mongodbServer: "${RELEASE:-prod}-mongodb.${RELEASE:-prod}" # TO LOOK AFTER + mongodbPort: 27017 + mongodbEnableAdmin: true + mongodbAdminUsername: ${OC_MONGO_ADMIN:-admin} + mongodbAdminPassword: ${OC_MONGO_PWD:-admin} + siteBaseUrl: /mongoexpress + basicAuthUsername: ${OC_MONGOEXPRESS_ADMIN:-admin} + basicAuthPassword: ${OC_MONGOEXPRESS_PWD:-admin} + mongodb: + enabled: false + +mongodb: + enabled: ${OC_MONGO_ENABLED:-true} + global: + defaultStorageClass: ${OC_MONGO_STORAGE:-""} + storageClass: ${OC_MONGO_STORAGE:-""} + architecture: standalone + useStatefulSet: false + auth: + enabled: true + rootUser: ${OC_MONGO_ADMIN_USERNAME:-admin} + rootPassword: ${OC_MONGO_ADMIN_PWD:-admin} + databases: [ ${OC_MONGO_DATABASE:-opencloud} ] + usernames: [ ${OC_MONGO_USERNAME:-admin} ] + passwords: [ ${OC_MONGO_PWD:-admin} ] + resourcesPreset: "small" + replicaCount: 1 + persistence: + enabled: true + create: false # do not auto-create + existingClaim: ${OC_MONGO_PVC:-mongo-pvc} + storageClassName: ${OC_MONGO_STORAGE:-""} + accessModes: + - ReadWriteOnce + size: ${OC_MONGO_SIZE:-5000Mi} + persistentVolumeClaimRetentionPolicy: + enabled: true + whenDeleted: Retain + whenScaled: Retain + arbiter: + enabled: false + livenessProbe: + enabled: true + readinessProbe: + enabled: true + +nats: + enabled: ${OC_NATS_ENABLED:-true} + extraEnv: + - name: NATS_MAX_FILE_DESCRIPTORS + value: "65536" + extraVolumeMounts: + - name: nats-config + mountPath: /etc/nats + config: + jetstream: + enabled: true + fileStore: + enabled: true + dir: /data/jetstream # mountPath used by template + # pvc block must live here + pvc: + enabled: true + # if you already created the claim, set existingClaim: + existingClaim: nats-pvc + # storageClassName: local-path or standard (use the SC in your cluster) + storageClassName: ${OC_NATS_STORAGE:-""} + size: ${OC_NATS_SIZE:-50Gi} + # name is the volume name used in volumeMounts; keep it simple + name: nats-jetstream + +openldap: + enabled: ${OC_LDAP_ENABLED:-true} + test: + enabled: false + ltb-passwd: + enabled: false + replicaCount: 1 + image: + repository: ${OC_LDAP_IMAGE:-osixia/openldap} + tls: + enabled: false + env: + LDAP_ORGANISATION: ${OC_LDAP_ORGANISATION:-Opencloud} + LDAP_DOMAIN: ${OC_LDAP_DOMAIN:-opencloud.com} + LDAP_BACKEND: "mdb" + LDAP_TLS: "${OC_LDAP_TLS:-false}" + LDAP_TLS_ENFORCE: "${OC_LDAP_TLS:-false}" + LDAP_REMOVE_CONFIG_AFTER_SETUP: "true" + adminPassword: ${OC_LDAP_ADMIN_PWD:-admin} + configPassword: "${OC_LDAP_CONFIG_PWD:-config}" + phpldapadmin: + enabled: false + persistence: + enabled: true + create: false # do not auto-create + existingClaim: openldap-pvc + accessMode: ReadWriteOnce + size: ${OC_LDAP_SIZE:-10Mi} + storageClassName: ${OC_LDAP_STORAGE:-""} + replication: + enabled: false + externalLDAP: + enabled: ${OC_LDAP_EXTERNAL:-false} + url: ${OC_LDAP_EXTERNAL_ENDPOINT} + bindDN: ${OC_LDAP_EXTERNAL_DN:-cn=admin,dc=example,dc=com} + bindPassword: ${OC_LDAP_EXTERNAL_PWD:-admin} + customLdifFiles: + 01-schema.ldif: |- + dn: ou=${OC_LDAP_GROUPS_OU:-groups},${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: organizationalUnit + ou: ${OC_LDAP_GROUPS_OU:-groups} + + dn: ou=${OC_LDAP_USERS_OU:-users},${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: organizationalUnit + ou: ${OC_LDAP_USERS_OU:-users} + + dn: cn=lastGID,${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: device + objectClass: top + description: Records the last GID used to create a Posix group. This prevents the re-use of a GID from a deleted group. + cn: lastGID + serialNumber: 2001 + + dn: cn=lastUID,${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: device + objectClass: top + serialNumber: 2001 + description: Records the last UID used to create a Posix account. This prevents the re-use of a UID from a deleted account. + cn: lastUID + + dn: cn=everybody,ou=${OC_LDAP_GROUPS_OU:-groups},${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: top + objectClass: posixGroup + cn: everybody + memberUid: admin + gidNumber: 2003 + + 02-ldapadmin.ldif : |- + dn: cn=${OC_LDAP_MNGT_ADMIN_GROUP:-ldapadmin},ou=${OC_LDAP_GROUPS_OU:-groups},${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: top + objectClass: posixGroup + cn: ${OC_LDAP_MNGT_ADMIN_GROUP:-ldapadmin} + memberUid: ${OC_LDAP_MNGT_ADMIN_GROUP:-ldapadmin} + gidNumber: 2001 + + dn: uid=${OC_LDAP_MNGT_ADMIN_GROUP:-ldapadmin},ou=${OC_LDAP_USERS_OU:-users},${OC_LDAP_MNGT_DN:-dc=example,dc=com} + givenName: ldap + sn: admin + uid: ${OC_LDAP_MNGT_ADMIN_GROUP:-ldapadmin} + cn: ${OC_LDAP_MNGT_ADMIN_GROUP:-ldapadmin} + mail: ldapadmin@example.com + objectClass: person + objectClass: inetOrgPerson + objectClass: posixAccount + userPassword: sai1yeiT + uidNumber: 2001 + gidNumber: 2001 + loginShell: /bin/bash + homeDirectory: /home/ldapadmin + + 03-opencloudadmin.ldif : |- + dn: uid=admin,ou=${OC_LDAP_USERS_OU:-users},${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: inetOrgPerson + cn: Admin + sn: Istrator + uid: ${OC_LDAP_ADMIN_USER:-admin} + userPassword: ${OC_LDAP_ADMIN_PWD:-admin} + mail: admin@example.com + ou: ${OC_LDAP_USERS_OU:-users} + + dn: ou=AppRoles,${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: organizationalunit + ou: AppRoles + description: AppRoles + + dn: ou=App1,ou=AppRoles,${OC_LDAP_MNGT_DN:-dc=example,dc=com} + objectClass: organizationalunit + ou: App1 + description: App1 + +prometheus: + enabled: ${OC_PROMETHEUS_ENABLED:-true} + enableTraefikProxyIntegration: true + server: + persistentVolume: + enabled: true + size: ${OC_PROMETHEUS_SIZE:-5Gi} + service: + type: ClusterIP + resources: + limits: + cpu: ${OC_PROMETHEUS_LIMITS_CPU:-500m} + memory: ${OC_PROMETHEUS_LIMITS_MEMORY:-512Mi} + requests: + cpu: ${OC_PROMETHEUS_REQUESTS_CPU:-128m} + memory: ${OC_PROMETHEUS_REQUESTS_MEMORY:-256Mi} + +# ldap user manager configuration +ldapUserManager: + enabled: true + env: + SERVER_HOSTNAME: ${OC_LDAP_MNGT_HOST:-ldap.exemple.com} + LDAP_BASE_DN: ${OC_LDAP_MNGT_DN:-dc=example,dc=com} + LDAP_REQUIRE_STARTTLS: "${OC_LDAP_MNGT_REQUIRE_TLS:-false}" + LDAP_ADMINS_GROUP: ${OC_LDAP_MNGT_ADMIN_GROUP:-ldapadmin} + LDAP_ADMIN_BIND_DN: ${OC_LDAP_MNGT_ADMIN_DN:-cn=admin,dc=example,dc=com} + LDAP_ADMIN_BIND_PWD: ${OC_LDAP_MNGT_ADMIN_PWD:-admin} + LDAP_IGNORE_CERT_ERRORS: "${OC_LDAP_MNGT_IGNORE_CERTS_ERRORS:-true}" + EMAIL_DOMAIN: ${OC_LDAP_MNGT_EMAIL_DOMAIN:-""} + NO_HTTPS: "${OC_LDAP_MNGT_NO_HTTPS:-true}" + SERVER_PATH: "/users" + ORGANISATION_NAME: ${OC_LDAP_ORGANISATION:-Opencloud} + LDAP_USER_OU: ${OC_LDAP_USERS_OU:-users} + LDAP_GROUP_OU: ${OC_LDAP_GROUPS_OU:-groups} + ACCEPT_WEAK_PASSWORDS: "true" + resources: + limits: + cpu: ${OC_FRONT_LIMITS_CPU:-128m} + memory: ${OC_FRONT_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_FRONT_REQUESTS_CPU:-128m} + memory: ${OC_FRONT_REQUESTS_MEMORY:-256Mi} + +traefik: + enabled: ${OC_TRAEFIK_ENABLED:-true} + service: + type: NodePort + ingressRoute: + dashboard: + enabled: true + matchRule: Host(`localhost`) && PathPrefix(`/api`) || PathPrefix(`/dashboard`) + entryPoints: [web] + ports: + web: + nodePort: 30950 + +hydra: + enabled: ${OC_HYDRA_ENABLED:-true} + maester: + enabled: true + secret: + enabled: false + nameOverride: hydra-secret + hashSumEnabled: false + hydra: + dev: true + existingSecret: hydra-secret + config: + dsn: memory + urls: + # login: https://localhost-login/authentication/login + # consent: https://localhost-consent/consent/consent + # logout: https://localhost-logout/authentication/logout + self: + issuer: "http://${RELEASE:-prod}-hydra-public.${RELEASE:-prod}:4444/" + +keto: + enabled: ${OC_KETO_ENABLED:-true} + keto: + config: + serve: + read: + port: 4466 + write: + port: 4467 + metrics: + port: 4468 + namespaces: + - id: 0 + name: open-cloud + dsn: memory + + +loki: + enabled: ${OC_LOKI_ENABLED:-true} + loki: + auth_enabled: false + commonConfig: + replication_factor: 1 + storage: + type: filesystem + filesystem: + chunks_directory: /var/loki/chunks + rules_directory: /var/loki/rules + admin_api_directory: /var/loki/admin + storage_config: + boltdb_shipper: + active_index_directory: /var/loki/index + filesystem: + directory: /var/loki/chunks + limits_config: + allow_structured_metadata: false + schemaConfig: + configs: + - from: "2020-01-01" + store: boltdb-shipper + object_store: filesystem + schema: v11 + index: + prefix: index_ + period: 24h + ingester: + chunk_encoding: snappy + tracing: + enabled: true + querier: + max_concurrent: 2 + + deploymentMode: SingleBinary + singleBinary: + extraVolumes: + - name: loki-storage + persistentVolumeClaim: + claimName: loki-pvc + persistence: + enabled: false # Deactivate loki auto provisioning, rely on existing PVC + accessMode: ReadWriteOnce + size: ${OC_LOKI_SIZE:-1Gi} + storageClassName: ${OC_LOKI_STORAGE:-""} + create: false + claimName: ${OC_LOKI_PVC:-loki-pvc} + + extraVolumeMounts: + - name: loki-storage + mountPath: /var/loki + replicas: 1 + resources: + limits: + cpu: ${OC_LOKI_LIMITS_CPU:-3} + memory: ${OC_LOKI_LIMITS_MEMORY:-4Gi} + requests: + cpu: ${OC_LOKI_REQUESTS_CPU:-1} + memory: ${OC_LOKI_REQUESTS_MEMORY:-0.5Gi} + extraEnv: + - name: GOMEMLIMIT + value: 3750MiB + + chunksCache: + # default is 500MB, with limited memory keep this smaller + writebackSizeLimit: 10MB + + # Enable minio for storage + minio: + enabled: ${OC_MINIO_ENABLED:-false} + # Zero out replica counts of other deployment modes + backend: + replicas: 0 + read: + replicas: 0 + write: + replicas: 0 + ingester: + replicas: 0 + querier: + replicas: 0 + queryFrontend: + replicas: 0 + queryScheduler: + replicas: 0 + distributor: + replicas: 0 + compactor: + replicas: 0 + indexGateway: + replicas: 0 + bloomCompactor: + replicas: 0 + bloomGateway: + replicas: 0 + +grafana: + enabled: ${OC_GRAFANA_ENABLED:-true} + adminUser: ${OC_GRAFANA_ADMIN_USER:-admin} + adminPassword: ${OC_GRAFANA_ADMIN_PWD:-admin} + persistence: + enabled: true + size: ${OC_GRAFANA_SIZE:-1Gi} + service: + type: ClusterIP + +argo-workflows: + enabled: ${OC_ARGO_ENABLED:-false} + workflow: + serviceAccount: + create: false + name: argo-workflow + rbac: + create: false # Manual provisioning + controller: + workflowNamespaces: [] #All of them + controller: + workflowDefaults: + spec: + serviceAccountName: argo-workflow + +ocAuth: + enabled: ${OC_AUTH_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_AUTH_IMAGE:-oc-auth:0.0.1}" + authType: hydra + keto: + adminRole: admin + hydra: + openCloudOauth2ClientSecretName: oc-oauth2-client-secret + ldap: + bindDn: ${OC_LDAP_MNGT_ADMIN_DN:-cn=admin,dc=example,dc=com} + binPwd: ${OC_LDAP_ADMIN_PWD:-admin} + baseDn: ${OC_LDAP_MNGT_DN:-dc=example,dc=com} + roleBaseDn: ${OC_LDAP_ROLE_DN:-ou=AppRoles,dc=example,dc=com} + resources: + limits: + cpu: ${OC_AUTH_LIMITS_CPU:-128m} + memory: ${AUTH_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${AUTH_REQUESTS_CPU:-128m} + memory: ${AUTH_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_AUTH_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_AUTH_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_AUTH_REPLICAS_USAGE:-80} + +ocFront: + enabled: ${OC_FRONT_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_FRONT_IMAGE:-oc-front:0.0.1}" + resources: + limits: + cpu: ${OC_FRONT_LIMITS_CPU:-128m} + memory: ${OC_FRONT_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_FRONT_REQUESTS_CPU:-128m} + memory: ${OC_FRONT_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_FRONT_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_FRONT_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_FRONT_REPLICAS_USAGE:-80} + +ocWorkspace: + enabled: ${OC_WORKSPACE_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_WORKSPACE_IMAGE:-oc-workspace:0.0.1}" + resources: + limits: + cpu: ${OC_WORKSPACE_LIMITS_CPU:-128m} + memory: ${OC_WORKSPACE_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_WORKSPACE_REQUESTS_CPU:-128m} + memory: ${OC_WORKSPACE_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_WORKSPACE_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_WORKSPACE_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_WORKSPACE_REPLICAS_USAGE:-80} + + +ocShared: + enabled: ${OC_SHARED_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_SHARED_IMAGE:-oc-shared:0.0.1}" + resources: + limits: + cpu: ${OC_SHARED_LIMITS_CPU:-128m} + memory: ${OC_SHARED_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_SHARED_REQUESTS_CPU:-128m} + memory: ${OC_SHARED_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_SHARED_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_SHARED_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_SHARED_REPLICAS_USAGE:-80} + +ocWorkflow: + enabled: ${OC_WORKFLOW_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_WORKFLOW_IMAGE:-oc-workflow:0.0.1}" + resources: + limits: + cpu: ${OC_WORKFLOW_LIMITS_CPU:-128m} + memory: ${WORKFLOW_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_WORKFLOW_REQUESTS_CPU:-128m} + memory: ${OC_WORKFLOW_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_WORKFLOW_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_WORKFLOW_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_WORKFLOW_REPLICAS_USAGE:-80} + +ocCatalog: + enabled: ${OC_CATALOG_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_CATALOG_IMAGE:-oc-catalog:0.0.1}" + resources: + limits: + cpu: ${OC_CATALOG_LIMITS_CPU:-128m} + memory: ${OC_CATALOG_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_CATALOG_REQUESTS_CPU:-128m} + memory: ${OC_CATALOG_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_CATALOG_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_CATALOG_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_CATALOG_REPLICAS_USAGE:-80} + +ocPeer: + enabled: ${OC_PEER_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_PEER_IMAGE:-oc-peer:0.0.1}" + resources: + limits: + cpu: ${OC_PEER_LIMITS_CPU:-128m} + memory: ${OC_PEER_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_PEER_REQUESTS_CPU:-128m} + memory: ${OC_PEER_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_CATALOG_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_CATALOG_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_CATALOG_REPLICAS_USAGE:-80} + +ocDatacenter: + enabled: ${OC_DATACENTER_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_DATACENTER_IMAGE:-oc-datacenter:0.0.1}" + resources: + limits: + cpu: ${OC_DATACENTER_LIMITS_CPU:-128m} + memory: ${OC_DATACENTER_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_DATACENTER_REQUESTS_CPU:-128m} + memory: ${OC_DATACENTER_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_DATACENTER_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_DATACENTER_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_DATACENTER_REPLICAS_USAGE:-80} + +ocSchedulerd: + enabled: ${OC_SCHEDULERD_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_SCHEDULERD_IMAGE:-oc-schedulerd:0.0.1}" + resources: + limits: + cpu: ${OC_SCHEDULERD_LIMITS_CPU:-128m} + memory: ${SCHEDULERD_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_SCHEDULERD_REQUESTS_CPU:-128m} + memory: ${OC_SCHEDULERD_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_SCHEDULERD_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_SCHEDULERD_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_SCHEDULERD_REPLICAS_USAGE:-80} + +ocScheduler: + enabled: ${OC_SCHEDULER_ENABLED:-true} + enableTraefikProxyIntegration: true + image: "${REGISTRY_HOST:-oc}/${OC_SCHEDULER_IMAGE:-oc-scheduler:0.0.1}" + resources: + limits: + cpu: ${OC_SCHEDULER_LIMITS_CPU:-128m} + memory: ${OC_SCHEDULER_LIMITS_MEMORY:-256Mi} + requests: + cpu: ${OC_SCHEDULER_REQUESTS_CPU:-128m} + memory: ${OC_SCHEDULER_REQUESTS_MEMORY:-256Mi} + replicas: 1 + hpa: + enabled: ${OC_SCHEDULER_REPLICAS_ENABLED:-true} + minReplicas: 1 + maxReplicas: ${OC_SCHEDULER_REPLICAS_MAX:-5} + targetCPUUtilizationPercentage: ${OC_SCHEDULER_REPLICAS_USAGE:-80} + +docker-registry-ui: + enabled: true + ui: + title: "opencloud docker registry" + proxy: true + dockerRegistryUrl: "http://${RELEASE:-prod}-docker-registry-ui-registry-server.${RELEASE:-prod}.svc.cluster.local:5000" + registry: + secretName: regcred + enabled: true + dataVolume: + persistentVolumeClaim: + claimName: docker-registry-pvc + persistence: + create: false + existingClaim: docker-registry-pvc + accessMode: ReadWriteOnce + storage: ${OC_DOCKER_REGISTRY_SIZE:-5Gi} + storageClassName: ${OC_DOCKER_REGISTRY_STORAGE:-""} diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..132b6f2 --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,47 @@ +package utils + +import ( + "embed" + "os" + "os/exec" + "strings" +) + +//go:embed assets/* +var FS embed.FS + +func Exec(args ...string) error { + fArgs := []string{"-c"} + if len(args) > 0 { + fArgs = append(fArgs, args...) + } + cmd := exec.Command("bash", fArgs...) + cmd.Stdin = os.Stdin + cmd.Stderr = os.Stderr + + return cmd.Run() +} + +func ReadFS(filePath string) (string, error) { + b, err := FS.ReadFile(filePath) + return string(b), err +} + +func Extract(content string, key string) (string, bool) { + key = key + ": " + idx := strings.Index(content, key) + if idx == -1 { + return "", false + } + + // start right after "host: " + start := idx + len(key) + + // stop at end of line + end := strings.Index(content[start:], "\n") + if end == -1 { + return strings.TrimSpace(content[start:]), true + } + + return strings.TrimSpace(content[start : start+end]), true +}