diff --git a/CHANGELOG.md b/CHANGELOG.md index 018b85295..2ef2a76ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A) - (Feature) Define Actions PlaceHolder - (Feature) Add Member Update helpers +- (Feature) Active Member condition ## [1.2.17](https://github.com/arangodb/kube-arangodb/tree/1.2.17) (2022-09-22) - (Feature) Add new field to DeploymentReplicationStatus with details on DC2DC sync status= diff --git a/pkg/apis/deployment/v1/conditions.go b/pkg/apis/deployment/v1/conditions.go index 34168efd0..dd7b25436 100644 --- a/pkg/apis/deployment/v1/conditions.go +++ b/pkg/apis/deployment/v1/conditions.go @@ -43,6 +43,8 @@ const ( ConditionTypeReachable ConditionType = "Reachable" // ConditionTypeServing indicates that the member core services are running. ConditionTypeServing ConditionType = "Serving" + // ConditionTypeActive indicates that the member server container started. + ConditionTypeActive ConditionType = "Active" // ConditionTypeTerminated indicates that the member has terminated and will not restart. ConditionTypeTerminated ConditionType = "Terminated" // ConditionTypeAutoUpgrade indicates that the member has to be started with `--database.auto-upgrade` once. diff --git a/pkg/apis/deployment/v2alpha1/conditions.go b/pkg/apis/deployment/v2alpha1/conditions.go index 4ccd91fa2..1906abf4c 100644 --- a/pkg/apis/deployment/v2alpha1/conditions.go +++ b/pkg/apis/deployment/v2alpha1/conditions.go @@ -43,6 +43,8 @@ const ( ConditionTypeReachable ConditionType = "Reachable" // ConditionTypeServing indicates that the member core services are running. ConditionTypeServing ConditionType = "Serving" + // ConditionTypeActive indicates that the member server container started. + ConditionTypeActive ConditionType = "Active" // ConditionTypeTerminated indicates that the member has terminated and will not restart. ConditionTypeTerminated ConditionType = "Terminated" // ConditionTypeAutoUpgrade indicates that the member has to be started with `--database.auto-upgrade` once. diff --git a/pkg/deployment/member/phase_updates.go b/pkg/deployment/member/phase_updates.go index 0566adc82..94c01b857 100644 --- a/pkg/deployment/member/phase_updates.go +++ b/pkg/deployment/member/phase_updates.go @@ -82,6 +82,7 @@ var phase = phaseMap{ func removeMemberConditionsMapFunc(m *api.MemberStatus) { // Clean conditions m.Conditions.Remove(api.ConditionTypeReady) + m.Conditions.Remove(api.ConditionTypeActive) m.Conditions.Remove(api.ConditionTypeStarted) m.Conditions.Remove(api.ConditionTypeReachable) m.Conditions.Remove(api.ConditionTypeServing) diff --git a/pkg/deployment/resources/pod_inspector.go b/pkg/deployment/resources/pod_inspector.go index 75cd5ed4a..7a951a667 100644 --- a/pkg/deployment/resources/pod_inspector.go +++ b/pkg/deployment/resources/pod_inspector.go @@ -30,6 +30,7 @@ import ( meta "k8s.io/apimachinery/pkg/apis/meta/v1" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" + "github.com/arangodb/kube-arangodb/pkg/apis/shared" "github.com/arangodb/kube-arangodb/pkg/deployment/agency" "github.com/arangodb/kube-arangodb/pkg/deployment/patch" "github.com/arangodb/kube-arangodb/pkg/metrics" @@ -288,6 +289,23 @@ func (r *Resources) InspectPods(ctx context.Context, cachedStatus inspectorInter } } + if k8sutil.IsContainerStarted(pod, shared.ServerContainerName) { + if memberStatus.Conditions.Update(api.ConditionTypeActive, true, "Core Pod Container started", "") { + updateMemberStatusNeeded = true + nextInterval = nextInterval.ReduceTo(recheckSoonPodInspectorInterval) + } + } + + if memberStatus.Conditions.IsTrue(api.ConditionTypeActive) { + if v, ok := pod.Labels[k8sutil.LabelKeyArangoActive]; !ok || v != k8sutil.LabelValueArangoActive { + pod.Labels[k8sutil.LabelKeyArangoActive] = k8sutil.LabelValueArangoActive + if err := r.context.ApplyPatchOnPod(ctx, pod, patch.ItemReplace(patch.NewPath("metadata", "labels"), pod.Labels)); err != nil { + log.Str("pod-name", pod.GetName()).Err(err).Error("Unable to update labels") + } + } + + } + if k8sutil.IsPodReady(pod) && k8sutil.AreContainersReady(pod, coreContainers) { // Pod is now ready if anyOf(memberStatus.Conditions.Update(api.ConditionTypeReady, true, "Pod Ready", ""), diff --git a/pkg/deployment/resources/services.go b/pkg/deployment/resources/services.go index 537f40239..a5c0c0bd9 100644 --- a/pkg/deployment/resources/services.go +++ b/pkg/deployment/resources/services.go @@ -129,7 +129,7 @@ func (r *Resources) EnsureServices(ctx context.Context, cachedStatus inspectorIn } ports := CreateServerServicePortsWithSidecars(podInspector, e.Member.PodName, e.Group) - selector := k8sutil.LabelsForMember(deploymentName, e.Group.AsRole(), e.Member.ID) + selector := k8sutil.LabelsForActiveMember(deploymentName, e.Group.AsRole(), e.Member.ID) if s, ok := cachedStatus.Service().V1().GetSimple(member.GetName()); !ok { s := r.createService(member.GetName(), member.GetNamespace(), member.AsOwner(), ports, selector) diff --git a/pkg/util/k8sutil/pods.go b/pkg/util/k8sutil/pods.go index 6ad38b6ea..f4af5c4e2 100644 --- a/pkg/util/k8sutil/pods.go +++ b/pkg/util/k8sutil/pods.go @@ -77,6 +77,18 @@ func IsPodReady(pod *core.Pod) bool { return condition != nil && condition.Status == core.ConditionTrue } +func IsContainerStarted(pod *core.Pod, container string) bool { + for _, c := range pod.Status.ContainerStatuses { + if c.Name != container { + continue + } + + return c.State.Terminated != nil || c.State.Running != nil + } + + return false +} + // AreContainersReady checks whether Pod is considered as ready. // Returns true if the PodReady condition on the given pod is set to true, // or all provided containers' names are running and are not in the list of failed containers. diff --git a/pkg/util/k8sutil/util.go b/pkg/util/k8sutil/util.go index 2bce2134b..0dbb668f4 100644 --- a/pkg/util/k8sutil/util.go +++ b/pkg/util/k8sutil/util.go @@ -46,6 +46,10 @@ const ( LabelKeyArangoTopology = "deployment.arangodb.com/topology" // LabelKeyArangoLeader is the key of the label used to store the current leader of a group instances. LabelKeyArangoLeader = "deployment.arangodb.com/leader" + // LabelKeyArangoActive is the key of the label used to mark members as active. + LabelKeyArangoActive = "deployment.arangodb.com/active" + // LabelValueArangoActive is the value of the label used to mark members as active. + LabelValueArangoActive = "true" // AppName is the fixed value for the "app" label AppName = "arangodb" ) @@ -133,6 +137,15 @@ func LabelsForMember(deploymentName, role, id string) map[string]string { return l } +// LabelsForActiveMember returns a map of labels, given to active members for given deployment name and member id +func LabelsForActiveMember(deploymentName, role, id string) map[string]string { + l := LabelsForMember(deploymentName, role, id) + + l[LabelKeyArangoActive] = LabelValueArangoActive + + return l +} + // LabelsForLeaderMember returns a map of labels for given deployment name and member id and role and leadership. func LabelsForLeaderMember(deploymentName, role, id string) map[string]string { l := LabelsForMember(deploymentName, role, id)