Skip to content

Commit

Permalink
Merge pull request #37 from werdes72/sidecar-manager
Browse files Browse the repository at this point in the history
Sidecar manager
  • Loading branch information
kyma-bot authored Dec 16, 2022
2 parents 0a1e205 + 95f015a commit 99f9b88
Show file tree
Hide file tree
Showing 23 changed files with 2,053 additions and 0 deletions.
10 changes: 10 additions & 0 deletions operator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ module github.com/kyma-project/istio/operator
go 1.19

require (
github.com/cucumber/godog v0.12.5
github.com/go-logr/logr v1.2.3
github.com/kyma-project/module-manager/operator v0.0.0-20221020113457-620af4f4b365
github.com/onsi/ginkgo/v2 v2.6.0
github.com/onsi/gomega v1.24.1
github.com/stretchr/testify v1.8.1
gitlab.com/rodrigoodhin/gocure v0.0.0-20220718065339-f14dfe79276a
golang.org/x/time v0.3.0
google.golang.org/protobuf v1.28.1
istio.io/api v0.0.0-20221021183946-6b7b70196148
Expand Down Expand Up @@ -38,6 +40,8 @@ require (
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa // indirect
github.com/containerd/containerd v1.6.6 // indirect
github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect
github.com/cucumber/messages-go/v16 v16.0.1 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d // indirect
Expand Down Expand Up @@ -65,6 +69,7 @@ require (
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.9.7 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
Expand All @@ -81,7 +86,10 @@ require (
github.com/gosuri/uitable v0.0.4 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
github.com/hashicorp/go-memdb v1.3.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/iancoleman/orderedmap v0.2.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
Expand Down Expand Up @@ -136,6 +144,8 @@ require (
github.com/spf13/cobra v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/tdewolff/minify/v2 v2.10.0 // indirect
github.com/tdewolff/parse/v2 v2.5.27 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
Expand Down
50 changes: 50 additions & 0 deletions operator/go.sum

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions operator/pkg/lib/sidecars/pods/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package pods

import (
v1 "k8s.io/api/core/v1"
)

const (
istioSidecarName = "istio-proxy"
)

func hasIstioSidecarStatusAnnotation(pod v1.Pod) bool {
_, exists := pod.Annotations["sidecar.istio.io/status"]
return exists
}

func isPodReady(pod v1.Pod) bool {
isMarkedForDeletion := pod.ObjectMeta.DeletionTimestamp != nil
return !isMarkedForDeletion && hasTrueStatusConditions(pod) && isPodRunning(pod)
}

func hasTrueStatusConditions(pod v1.Pod) bool {
for _, condition := range pod.Status.Conditions {
if condition.Status != v1.ConditionTrue {
return false
}
}
return true
}

func isPodRunning(pod v1.Pod) bool {
return pod.Status.Phase == v1.PodRunning
}

func hasSidecarContainerWithWithDifferentImage(pod v1.Pod, expectedImage SidecarImage) bool {

for _, container := range pod.Spec.Containers {
if isContainerIstioSidecar(container) && !expectedImage.matchesImageIn(container) {
return true
}
}
return false
}

func hasInitContainer(containers []v1.Container, initContainerName string) bool {
proxyImage := ""
for _, container := range containers {
if container.Name == initContainerName {
proxyImage = container.Image
}
}
return proxyImage != ""
}

func isContainerIstioSidecar(container v1.Container) bool {
return istioSidecarName == container.Name
}

func isPodInNamespaceList(pod v1.Pod, namespaceList []v1.Namespace) bool {
for _, namespace := range namespaceList {
if pod.ObjectMeta.Namespace == namespace.Name {
return true
}
}
return false
}

func isSystemNamespace(name string) bool {
switch name {
case "kube-system":
return true
case "kube-public":
return true
case "istio-system":
return true
}
return false
}
129 changes: 129 additions & 0 deletions operator/pkg/lib/sidecars/pods/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package pods

import (
"context"
"fmt"
"github.com/go-logr/logr"
"github.com/kyma-project/istio/operator/pkg/lib/sidecars/retry"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/fields"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
istioValidationContainerName = "istio-validation"
istioInitContainerName = "istio-init"
)

type SidecarImage struct {
Repository string
Tag string
}

func (r SidecarImage) String() string {
return fmt.Sprintf("%s:%s", r.Repository, r.Tag)
}

func (r SidecarImage) matchesImageIn(container v1.Container) bool {
return container.Image == r.String()
}

func getAllRunningPods(ctx context.Context, c client.Client) (*v1.PodList, error) {
podList := &v1.PodList{}

isRunning := fields.OneTermEqualSelector("status.phase", string(v1.PodRunning))

err := retry.RetryOnError(retry.DefaultRetry, func() error {
return c.List(ctx, podList, client.MatchingFieldsSelector{Selector: isRunning})
})
if err != nil {
return podList, err
}

return podList, nil
}

func getNamespacesWithIstioLabelsAndInjectionDisabled(ctx context.Context, c client.Client) (*v1.NamespaceList, *v1.NamespaceList, error) {
unfilteredLabeledList := &v1.NamespaceList{}
labeledList := &v1.NamespaceList{}
disabledList := &v1.NamespaceList{}

err := retry.RetryOnError(retry.DefaultRetry, func() error {
return c.List(ctx, unfilteredLabeledList, client.HasLabels{"istio-injection"})
})
if err != nil {
return labeledList, disabledList, err
}

unfilteredLabeledList.DeepCopyInto(labeledList)
labeledList.Items = []v1.Namespace{}
unfilteredLabeledList.DeepCopyInto(disabledList)
disabledList.Items = []v1.Namespace{}

for _, namespace := range unfilteredLabeledList.Items {
if isSystemNamespace(namespace.ObjectMeta.Name) {
continue
}
if namespace.Labels["istio-injection"] == "disabled" {
disabledList.Items = append(disabledList.Items, namespace)
}
labeledList.Items = append(labeledList.Items, namespace)
}

return labeledList, disabledList, err
}

func GetPodsWithDifferentSidecarImage(ctx context.Context, c client.Client, expectedImage SidecarImage, logger *logr.Logger) (outputPodsList v1.PodList, err error) {
podList, err := getAllRunningPods(ctx, c)
if err != nil {
return outputPodsList, err
}

podList.DeepCopyInto(&outputPodsList)
outputPodsList.Items = []v1.Pod{}

for _, pod := range podList.Items {
if hasIstioSidecarStatusAnnotation(pod) &&
isPodReady(pod) &&
hasSidecarContainerWithWithDifferentImage(pod, expectedImage) {
outputPodsList.Items = append(outputPodsList.Items, *pod.DeepCopy())
}
}

logger.Info("Pods with different istio proxy image", "number of pods", len(outputPodsList.Items), "expected image", expectedImage)
return outputPodsList, nil
}

func GetPodsForCNIChange(ctx context.Context, c client.Client, isCNIEnabled bool, logger *logr.Logger) (outputPodsList v1.PodList, err error) {
podList, err := getAllRunningPods(ctx, c)
if err != nil {
return outputPodsList, err
}

var containerName string
if isCNIEnabled {
containerName = istioInitContainerName
} else {
containerName = istioValidationContainerName
}

_, injectionDisabledNamespaceList, err := getNamespacesWithIstioLabelsAndInjectionDisabled(ctx, c)
if err != nil {
return outputPodsList, err
}

podList.DeepCopyInto(&outputPodsList)
outputPodsList.Items = []v1.Pod{}

for _, pod := range podList.Items {
if isPodReady(pod) && hasInitContainer(pod.Spec.InitContainers, containerName) &&
!isPodInNamespaceList(pod, injectionDisabledNamespaceList.Items) &&
!isSystemNamespace(pod.Namespace) {
outputPodsList.Items = append(outputPodsList.Items, *pod.DeepCopy())
}
}

logger.Info("Pods that need to adapt to CNI change", "number of pods", len(outputPodsList.Items))

return outputPodsList, nil
}
Loading

0 comments on commit 99f9b88

Please sign in to comment.