-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from werdes72/sidecar-manager
Sidecar manager
- Loading branch information
Showing
23 changed files
with
2,053 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.