Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[deckhouse] check kernel versions for enabled modules #2709

Merged
merged 44 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
6002371
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
64bae56
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
e70a2f9
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
bec16e4
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
999675e
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
00e0852
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
d654ea7
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
39079c9
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
8e2c953
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
6aa2930
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
d823ead
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
9607aae
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
8bc6eda
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
5689189
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 11, 2022
5a81e1b
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 12, 2022
0a41cf9
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
557388b
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
71e583c
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
9713375
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
65da8b2
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
4bf5666
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
7c1f6f5
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
30b077d
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
a299ce7
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
7894d16
[deckhouse] check kernel versions for enabled modules
RomanenkoDenys Oct 13, 2022
336bb64
Update ee/modules/110-istio/templates/control-plane/iop.yaml
RomanenkoDenys Oct 14, 2022
afcd4f4
Update ee/modules/110-istio/templates/control-plane/iop.yaml
RomanenkoDenys Oct 14, 2022
5e3fac9
++
RomanenkoDenys Oct 18, 2022
4a7ce01
++
RomanenkoDenys Oct 18, 2022
b0df04b
++
RomanenkoDenys Oct 19, 2022
40367b8
Update helm_lib/templates/_module_init_container.tpl
RomanenkoDenys Oct 19, 2022
a65ea07
++
RomanenkoDenys Oct 19, 2022
85321f1
Apply suggestions from code review
RomanenkoDenys Oct 21, 2022
b255adf
++
RomanenkoDenys Oct 21, 2022
c65463d
++
RomanenkoDenys Oct 21, 2022
cc17e08
++
RomanenkoDenys Oct 21, 2022
a6c30f4
Update modules/340-monitoring-deckhouse/monitoring/prometheus-rules/k…
RomanenkoDenys Oct 31, 2022
7293f5d
Update modules/340-monitoring-deckhouse/monitoring/prometheus-rules/k…
RomanenkoDenys Oct 31, 2022
42872d6
Update modules/340-monitoring-deckhouse/monitoring/prometheus-rules/k…
RomanenkoDenys Oct 31, 2022
20ee3de
++
RomanenkoDenys Oct 31, 2022
168dd91
added constraint for node-local-dns
RomanenkoDenys Nov 8, 2022
9585034
++
RomanenkoDenys Nov 8, 2022
9b0e8b0
++
RomanenkoDenys Nov 8, 2022
dff95db
++
RomanenkoDenys Nov 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ee/modules/110-istio/template_tests/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func Test(t *testing.T) {

const globalValues = `
highAvailability: true
enabledModules: ["operator-prometheus-crd","cert-manager","vertical-pod-autoscaler-crd"]
enabledModules: ["operator-prometheus-crd","cert-manager","vertical-pod-autoscaler-crd","cni-cilium"]
modules:
publicDomainTemplate: "%s.example.com"
placement:
Expand Down
10 changes: 9 additions & 1 deletion ee/modules/110-istio/templates/control-plane/iop.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,19 @@ spec:
enabled: true
v2:
enabled: true

sidecarInjectorWebhook:
injectedAnnotations:
istio.deckhouse.io/version: "{{ $fullVersion }}"
{{- if ($.Values.global.enabledModules | has "cni-cilium") }}
defaultTemplates: ["sidecar", "d8-check-kernel-version"]
{{- end }}
templates:
{{- if ($.Values.global.enabledModules | has "cni-cilium") }}
d8-check-kernel-version: |
spec:
initContainers:
{{- include "helm_lib_module_init_container_check_linux_kernel" (tuple $ ">= 5.7") | nindent 12 }}
{{- end }}
d8-hold-istio-proxy-termination-until-application-stops: |
spec:
containers:
Expand Down
16 changes: 16 additions & 0 deletions helm_lib/templates/_module_init_container.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,19 @@
requests:
{{- include "helm_lib_module_ephemeral_storage_only_logs" . | nindent 6 }}
{{- end }}

{{- /* Usage: {{ include "helm_lib_module_init_container_check_linux_kernel" (list . ">= 4.9.17") }} */ -}}
{{- /* returns initContainer which checks the kernel version on the node for compliance to semver constraint */ -}}
{{- define "helm_lib_module_init_container_check_linux_kernel" }}
{{- $context := index . 0 -}}
{{- $semver_constraint := index . 1 -}}
- name: check-linux-kernel
image: {{ include "helm_lib_module_common_image" (list $context "checkKernelVersion") }}
{{- include "helm_lib_module_container_security_context_read_only_root_filesystem" . | nindent 2 }}
env:
- name: KERNEL_CONSTRAINT
value: {{ $semver_constraint | quote }}
resources:
requests:
{{- include "helm_lib_module_ephemeral_storage_only_logs" $context | nindent 6 }}
{{- end }}
11 changes: 11 additions & 0 deletions modules/000-common/images/check-kernel-version/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ARG BASE_SCRATCH
ARG BASE_GOLANG_17_ALPINE
FROM $BASE_GOLANG_17_ALPINE as artifact
WORKDIR /src
COPY src /src/

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o check-kernel-version check-kernel-version.go

FROM $BASE_SCRATCH
COPY --from=artifact /src/check-kernel-version /
ENTRYPOINT [ "/check-kernel-version" ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright 2022 Flant JSC

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.
*/

package main

import (
"log"
"os"
"strings"

"github.com/Masterminds/semver/v3"
"golang.org/x/sys/unix"
)

func main() {
kernelConstraint := os.Getenv("KERNEL_CONSTRAINT")
if kernelConstraint == "" {
log.Fatal("ENV variable KERNEL_CONSTRAINT must be set")
}
c, err := semver.NewConstraint(kernelConstraint)
if err != nil {
log.Fatal(err)
}

utsname := unix.Utsname{}
unix.Uname(&utsname)
kernelVersion := string(utsname.Release[:])
/* Kernel version should be splitted to parts because versions `5.15.0-52-generic`
parses by semver as prerelease version. Prerelease versions by default come before stable versions
in the order of precedence, so in semver terms `5.15.0-52-generic` less than `5.15`.
More info - https://github.com/Masterminds/semver#working-with-prerelease-versions */
v, err := semver.NewVersion(strings.Split(kernelVersion, "-")[0])
nabokihms marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
log.Fatal(err)
}

if !c.Check(v) {
log.Fatalf("the kernel %s does not meet the requirements: %s", kernelVersion, kernelConstraint)
}
log.Printf("the kernel %s meets the requirements: %s", kernelVersion, kernelConstraint)
}
8 changes: 8 additions & 0 deletions modules/000-common/images/check-kernel-version/src/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module check-kernel-version

go 1.18

require (
github.com/Masterminds/semver/v3 v3.1.1
golang.org/x/sys v0.0.0-20221010170243-090e33056c14
)
4 changes: 4 additions & 0 deletions modules/000-common/images/check-kernel-version/src/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
169 changes: 169 additions & 0 deletions modules/002-deckhouse/hooks/check_kernel_versions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
Copyright 2022 Flant JSC

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.
*/

/*
This hook checks nodes kernel requirements and set internal flag stopMainQueue.
This flag used in another hook, stop_main_queue.go, which stops main queue if flag is true.
We cannot stop queue in this hook, because we loose metrics if hook fails.
*/

package hooks

import (
"fmt"
"strings"

"github.com/Masterminds/semver/v3"
"github.com/flant/addon-operator/pkg/module_manager/go_hook"
"github.com/flant/addon-operator/pkg/module_manager/go_hook/metrics"
"github.com/flant/addon-operator/sdk"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"github.com/deckhouse/deckhouse/go_lib/set"
)

type nodeKernelVersion struct {
Name string
KernelVersion string
SemverVersion *semver.Version
}

type nodeConstraint struct {
KernelVersionConstraint string
ModulesListInUse []string
}

var constraints = []nodeConstraint{
{
KernelVersionConstraint: ">= 4.9.17",
ModulesListInUse: []string{"cni-cilium"},
},
{
KernelVersionConstraint: ">= 5.7",
ModulesListInUse: []string{"cni-cilium", "istio"},
},
{
KernelVersionConstraint: ">= 5.7",
ModulesListInUse: []string{"cni-cilium", "openvpn"},
},
{
KernelVersionConstraint: ">= 5.7",
ModulesListInUse: []string{"cni-cilium", "node-local-dns"},
},
}

const (
nodeKernelCheckMetricsGroup = "node_kernel_check"
nodeKernelCheckMetricName = "d8_node_kernel_does_not_satisfy_requirements"
)

var _ = sdk.RegisterFunc(&go_hook.HookConfig{
Kubernetes: []go_hook.KubernetesConfig{
{
Name: "nodes",
ApiVersion: "v1",
Kind: "Node",
LabelSelector: &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "node.deckhouse.io/group",
Operator: metav1.LabelSelectorOpExists,
},
},
},
FilterFunc: filterNodes,
},
},
}, handleNodes)

func filterNodes(obj *unstructured.Unstructured) (go_hook.FilterResult, error) {
var node corev1.Node

err := sdk.FromUnstructured(obj, &node)
if err != nil {
return nil, err
}
/* Kernel version should be splitted to parts because versions `5.15.0-52-generic`
parses by semver as prerelease version. Prerelease versions by default come before stable versions
in the order of precedence, so in semver terms `5.15.0-52-generic` less than `5.15`.
More info - https://github.com/Masterminds/semver#working-with-prerelease-versions */
v, err := semver.NewVersion(strings.Split(node.Status.NodeInfo.KernelVersion, "-")[0])
nabokihms marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, fmt.Errorf("cannot parse kernel version %s for node %s: %v", node.Status.NodeInfo.KernelVersion, node.Name, err)
}

return nodeKernelVersion{
Name: node.Name,
KernelVersion: node.Status.NodeInfo.KernelVersion,
SemverVersion: v,
}, nil
}

func handleNodes(input *go_hook.HookInput) error {
var hasAffectedNodes bool

input.MetricsCollector.Expire(nodeKernelCheckMetricsGroup)

snap := input.Snapshots["nodes"]
if len(snap) == 0 {
return nil
}

enabledModules := set.NewFromValues(input.Values, "global.enabledModules")

for _, constrant := range constraints {
// check modules in use
check := true
for _, m := range constrant.ModulesListInUse {
if !enabledModules.Has(m) {
check = false
break
}
}
if !check {
continue
}

c, err := semver.NewConstraint(constrant.KernelVersionConstraint)
if err != nil {
return err
}

for _, n := range snap {
node := n.(nodeKernelVersion)

if !c.Check(node.SemverVersion) {
modulesListInUse := strings.Join(constrant.ModulesListInUse, ",")
input.MetricsCollector.Set(nodeKernelCheckMetricName, 1, map[string]string{
"node": node.Name,
"kernel_version": node.KernelVersion,
"affected_module": modulesListInUse,
"constraint": constrant.KernelVersionConstraint,
}, metrics.WithGroup(nodeKernelCheckMetricsGroup))
input.LogEntry.Debugf("kernel %s on node %s does not satisfy kernel constraint %s for modules [%s]", node.KernelVersion, node.Name, constrant.KernelVersionConstraint, modulesListInUse)
hasAffectedNodes = true
}
}
}

if hasAffectedNodes {
input.LogEntry.Error("some nodes have unmet kernel constraints. To observe affected nodes use the expr `d8_node_kernel_does_not_satisfy_requirements == 1` in Prometheus")
}

return nil
}
Loading