Skip to content

Commit

Permalink
Fix that pod spec's hash may be changed when new fields are added to …
Browse files Browse the repository at this point in the history
…the `PodSpec` (#6030)
  • Loading branch information
fgksgf authored Jan 16, 2025
1 parent 6676ae2 commit c8b17ac
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
_output
output
.idea/
coverage.txt
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ lint: bin/golangci-lint
unit:
go test $$(go list -e ./... | grep -v cmd | grep -v tools | grep -v tests | grep -v third_party) \
-cover -coverprofile=coverage.txt -covermode=atomic
sed -i.bak '/generated/d;/fake.go/d' coverage.txt && rm coverage.txt coverage.txt.bak
sed -i.bak '/generated/d;/fake.go/d' coverage.txt && rm coverage.txt.bak

.PHONY: check
check: lint unit verify
Expand Down
11 changes: 7 additions & 4 deletions pkg/controllers/pd/tasks/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ import (
"github.com/pingcap/tidb-operator/pkg/utils/task/v3"
)

const fakeVersion = "v1.2.3"
const (
fakeVersion = "v1.2.3"
expectedPodSpecHash = "7d4f6bf985"
)

func TestTaskPod(t *testing.T) {
cases := []struct {
Expand Down Expand Up @@ -283,7 +286,7 @@ func TestTaskPod(t *testing.T) {
pod: fake.FakeObj("aaa-pd-xxx", func(obj *corev1.Pod) *corev1.Pod {
obj.Labels = map[string]string{
v1alpha1.LabelKeyConfigHash: "newest",
v1alpha1.LabelKeyPodSpecHash: "6d6499ffc7",
v1alpha1.LabelKeyPodSpecHash: expectedPodSpecHash,
}
return obj
}),
Expand Down Expand Up @@ -331,7 +334,7 @@ func TestTaskPod(t *testing.T) {
pod: fake.FakeObj("aaa-pd-xxx", func(obj *corev1.Pod) *corev1.Pod {
obj.Labels = map[string]string{
v1alpha1.LabelKeyConfigHash: "newest",
v1alpha1.LabelKeyPodSpecHash: "6d6499ffc7",
v1alpha1.LabelKeyPodSpecHash: expectedPodSpecHash,
"xxx": "yyy",
}
return obj
Expand Down Expand Up @@ -382,7 +385,7 @@ func TestTaskPod(t *testing.T) {
obj.Labels = map[string]string{
v1alpha1.LabelKeyInstance: "aaa-xxx",
v1alpha1.LabelKeyConfigHash: "newest",
v1alpha1.LabelKeyPodSpecHash: "6d6499ffc7",
v1alpha1.LabelKeyPodSpecHash: expectedPodSpecHash,
}
return obj
}),
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/tidb/tasks/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (

const (
fakeVersion = "v1.2.3"
podSpecHash = "9bbf8897b"
podSpecHash = "fc445b4c6"
)

func TestTaskPod(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/tiflash/tasks/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (

const (
fakeVersion = "v1.2.3"
fakePodHash = "779dbdbdf4"
fakePodHash = "5bf69bf8f9"
)

func TestTaskPod(t *testing.T) {
Expand Down
15 changes: 9 additions & 6 deletions pkg/controllers/tikv/tasks/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ import (
"github.com/pingcap/tidb-operator/pkg/utils/task/v3"
)

const fakeVersion = "v1.2.3"
const (
fakeVersion = "v1.2.3"
podSpecHash = "5f7b88ffbd"
)

func TestTaskPod(t *testing.T) {
now := metav1.Now()
Expand Down Expand Up @@ -173,7 +176,7 @@ func TestTaskPod(t *testing.T) {
pod: fake.FakeObj("aaa-tikv-xxx", func(obj *corev1.Pod) *corev1.Pod {
obj.Labels = map[string]string{
v1alpha1.LabelKeyConfigHash: "newest",
v1alpha1.LabelKeyPodSpecHash: "59f798884b",
v1alpha1.LabelKeyPodSpecHash: podSpecHash,
}
return obj
}),
Expand All @@ -197,7 +200,7 @@ func TestTaskPod(t *testing.T) {
pod: fake.FakeObj("aaa-tikv-xxx", func(obj *corev1.Pod) *corev1.Pod {
obj.Labels = map[string]string{
v1alpha1.LabelKeyConfigHash: "old",
v1alpha1.LabelKeyPodSpecHash: "59f798884b",
v1alpha1.LabelKeyPodSpecHash: podSpecHash,
}
return obj
}),
Expand All @@ -221,7 +224,7 @@ func TestTaskPod(t *testing.T) {
pod: fake.FakeObj("aaa-tikv-xxx", func(obj *corev1.Pod) *corev1.Pod {
obj.Labels = map[string]string{
v1alpha1.LabelKeyConfigHash: "newest",
v1alpha1.LabelKeyPodSpecHash: "59f798884b",
v1alpha1.LabelKeyPodSpecHash: podSpecHash,
"xxx": "yyy",
}
return obj
Expand All @@ -246,7 +249,7 @@ func TestTaskPod(t *testing.T) {
pod: fake.FakeObj("aaa-tikv-xxx", func(obj *corev1.Pod) *corev1.Pod {
obj.Labels = map[string]string{
v1alpha1.LabelKeyConfigHash: "newest",
v1alpha1.LabelKeyPodSpecHash: "59f798884b",
v1alpha1.LabelKeyPodSpecHash: podSpecHash,
"xxx": "yyy",
}
return obj
Expand All @@ -272,7 +275,7 @@ func TestTaskPod(t *testing.T) {
obj.Labels = map[string]string{
v1alpha1.LabelKeyInstance: "aaa-xxx",
v1alpha1.LabelKeyConfigHash: "newest",
v1alpha1.LabelKeyPodSpecHash: "59f798884b",
v1alpha1.LabelKeyPodSpecHash: podSpecHash,
}
return obj
}),
Expand Down
33 changes: 28 additions & 5 deletions pkg/utils/k8s/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,54 @@
package k8s

import (
"bytes"
"fmt"
"hash/fnv"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
serializerjson "k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/client-go/kubernetes/scheme"

"github.com/pingcap/tidb-operator/apis/core/v1alpha1"
maputil "github.com/pingcap/tidb-operator/pkg/utils/map"
hashutil "github.com/pingcap/tidb-operator/third_party/kubernetes/pkg/util/hash"
)

var podEncoder = scheme.Codecs.EncoderForVersion(
serializerjson.NewSerializerWithOptions(
serializerjson.DefaultMetaFactory,
scheme.Scheme,
scheme.Scheme,
serializerjson.SerializerOptions{
Yaml: false,
Pretty: false,
Strict: true,
}),
corev1.SchemeGroupVersion,
)

// CalculateHashAndSetLabels calculate the hash of pod spec and set it to the pod labels.
func CalculateHashAndSetLabels(pod *corev1.Pod) {
hasher := fnv.New32a()
if pod.Labels == nil {
pod.Labels = map[string]string{}
}
spec := pod.Spec.DeepCopy()
for i := range spec.InitContainers {
c := &spec.InitContainers[i]
// ignores init containers image change to support hot reload image for sidecar
c.Image = ""
}
hashutil.DeepHashObject(hasher, spec)

// This prevents the hash from being changed when new fields are added to the `PodSpec` due to K8s version upgrades.
buf := bytes.Buffer{}
if err := podEncoder.Encode(&corev1.Pod{Spec: *spec}, &buf); err != nil {
panic(fmt.Errorf("failed to encode pod spec, %w", err))
}
hasher := fnv.New32a()
hashutil.DeepHashObject(hasher, buf.Bytes())

if pod.Labels == nil {
pod.Labels = map[string]string{}
}
pod.Labels[v1alpha1.LabelKeyPodSpecHash] = rand.SafeEncodeString(fmt.Sprint(hasher.Sum32()))
}

Expand Down
1 change: 1 addition & 0 deletions pkg/utils/k8s/revision/controller_revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ func getPatch(obj client.Object, gvk schema.GroupVersionKind) ([]byte, error) {
}),
gvk.GroupVersion(),
)
encoderMap[gvk.GroupVersion()] = encoder
}

buf := bytes.Buffer{}
Expand Down

0 comments on commit c8b17ac

Please sign in to comment.