@@ -17,8 +17,11 @@ limitations under the License.
17
17
package pod
18
18
19
19
import (
20
- "k8s.io/api/core/v1"
21
- "k8s.io/apimachinery/pkg/api/errors"
20
+ "errors"
21
+ "fmt"
22
+
23
+ v1 "k8s.io/api/core/v1"
24
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
22
25
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23
26
"k8s.io/apimachinery/pkg/types"
24
27
clientset "k8s.io/client-go/kubernetes"
@@ -39,16 +42,28 @@ type MirrorClient interface {
39
42
DeleteMirrorPod (podFullName string , uid * types.UID ) (bool , error )
40
43
}
41
44
45
+ // nodeGetter is a subset a NodeLister, simplified for testing.
46
+ type nodeGetter interface {
47
+ // Get retrieves the Node for a given name.
48
+ Get (name string ) (* v1.Node , error )
49
+ }
50
+
42
51
// basicMirrorClient is a functional MirrorClient. Mirror pods are stored in
43
52
// the kubelet directly because they need to be in sync with the internal
44
53
// pods.
45
54
type basicMirrorClient struct {
46
55
apiserverClient clientset.Interface
56
+ nodeGetter nodeGetter
57
+ nodeName string
47
58
}
48
59
49
60
// NewBasicMirrorClient returns a new MirrorClient.
50
- func NewBasicMirrorClient (apiserverClient clientset.Interface ) MirrorClient {
51
- return & basicMirrorClient {apiserverClient : apiserverClient }
61
+ func NewBasicMirrorClient (apiserverClient clientset.Interface , nodeName string , nodeGetter nodeGetter ) MirrorClient {
62
+ return & basicMirrorClient {
63
+ apiserverClient : apiserverClient ,
64
+ nodeName : nodeName ,
65
+ nodeGetter : nodeGetter ,
66
+ }
52
67
}
53
68
54
69
func (mc * basicMirrorClient ) CreateMirrorPod (pod * v1.Pod ) error {
@@ -64,8 +79,25 @@ func (mc *basicMirrorClient) CreateMirrorPod(pod *v1.Pod) error {
64
79
}
65
80
hash := getPodHash (pod )
66
81
copyPod .Annotations [kubetypes .ConfigMirrorAnnotationKey ] = hash
82
+
83
+ // With the MirrorPodNodeRestriction feature, mirror pods are required to have an owner reference
84
+ // to the owning node.
85
+ // See http://git.k8s.io/enhancements/keps/sig-auth/20190916-noderestriction-pods.md
86
+ nodeUID , err := mc .getNodeUID ()
87
+ if err != nil {
88
+ return fmt .Errorf ("failed to get node UID: %v" , err )
89
+ }
90
+ controller := true
91
+ copyPod .OwnerReferences = []metav1.OwnerReference {{
92
+ APIVersion : v1 .SchemeGroupVersion .String (),
93
+ Kind : "Node" ,
94
+ Name : mc .nodeName ,
95
+ UID : nodeUID ,
96
+ Controller : & controller ,
97
+ }}
98
+
67
99
apiPod , err := mc .apiserverClient .CoreV1 ().Pods (copyPod .Namespace ).Create (& copyPod )
68
- if err != nil && errors .IsAlreadyExists (err ) {
100
+ if err != nil && apierrors .IsAlreadyExists (err ) {
69
101
// Check if the existing pod is the same as the pod we want to create.
70
102
if h , ok := apiPod .Annotations [kubetypes .ConfigMirrorAnnotationKey ]; ok && h == hash {
71
103
return nil
@@ -94,7 +126,7 @@ func (mc *basicMirrorClient) DeleteMirrorPod(podFullName string, uid *types.UID)
94
126
var GracePeriodSeconds int64
95
127
if err := mc .apiserverClient .CoreV1 ().Pods (namespace ).Delete (name , & metav1.DeleteOptions {GracePeriodSeconds : & GracePeriodSeconds , Preconditions : & metav1.Preconditions {UID : uid }}); err != nil {
96
128
// Unfortunately, there's no generic error for failing a precondition
97
- if ! (errors .IsNotFound (err ) || errors .IsConflict (err )) {
129
+ if ! (apierrors .IsNotFound (err ) || apierrors .IsConflict (err )) {
98
130
// We should return the error here, but historically this routine does
99
131
// not return an error unless it can't parse the pod name
100
132
klog .Errorf ("Failed deleting a mirror pod %q: %v" , podFullName , err )
@@ -104,6 +136,17 @@ func (mc *basicMirrorClient) DeleteMirrorPod(podFullName string, uid *types.UID)
104
136
return true , nil
105
137
}
106
138
139
+ func (mc * basicMirrorClient ) getNodeUID () (types.UID , error ) {
140
+ node , err := mc .nodeGetter .Get (mc .nodeName )
141
+ if err != nil {
142
+ return "" , err
143
+ }
144
+ if node .UID == "" {
145
+ return "" , errors .New ("node UID unset" )
146
+ }
147
+ return node .UID , nil
148
+ }
149
+
107
150
// IsStaticPod returns true if the passed Pod is static.
108
151
func IsStaticPod (pod * v1.Pod ) bool {
109
152
source , err := kubetypes .GetPodSource (pod )
0 commit comments