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