Skip to content

Commit 7160f5e

Browse files
authored
Merge pull request #3681 from luthermonson/cni-envvars
rework vpc cni envvar logic to drop the forced keys
2 parents 2f89d87 + 685b59b commit 7160f5e

File tree

3 files changed

+59
-122
lines changed

3 files changed

+59
-122
lines changed

docs/book/src/topics/eks/pod-networking.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,26 @@ When creating a EKS cluster the Amazon VPC CNI will be used by default for Pod N
77
## Using the VPC CNI Addon
88
You can use an explicit version of the Amazon VPC CNI by using the **vpc-cni** EKS addon. See the [addons](./addons.md) documentation for further details of how to use addons.
99

10+
## Using Custom VPC CNI Configuration
11+
If your use case demands [custom networking](https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html) VPC CNI configuration you might already be familiar with the [helm chart](https://github.com/aws/amazon-vpc-cni-k8s) which helps with the process. This gives you access to ENI Configs and you can set Environment Variables on the `aws-node` DaemonSet where the VPC CNI runs. CAPA is able to tune the same DaemonSet through Kubernetes.
1012

11-
## Increase node pod limit
13+
The following example shows how to turn on custom network config and set a [label definition](https://github.com/aws/amazon-vpc-cni-k8s#eni_config_label_def).
14+
15+
```yaml
16+
kind: AWSManagedControlPlane
17+
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
18+
metadata:
19+
name: "capi-managed-test-control-plane"
20+
spec:
21+
vpcCni:
22+
env:
23+
- name: AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG
24+
value: "true"
25+
- name: ENABLE_PREFIX_DELEGATION
26+
value: "true"
27+
```
28+
29+
### Increase node pod limit
1230
You can increase the pod limit per-node as [per the upstream AWS documentation](https://aws.amazon.com/blogs/containers/amazon-vpc-cni-increases-pods-per-node-limits/). You'll need to enable the `vpc-cni` plugin addon on your EKS cluster as well as enable prefix assignment mode through the `ENABLE_PREFIX_DELEGATION` environment variable.
1331

1432
```yaml
@@ -19,6 +37,8 @@ metadata:
1937
spec:
2038
vpcCni:
2139
env:
40+
- name: AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG
41+
value: "true"
2242
- name: ENABLE_PREFIX_DELEGATION
2343
value: "true"
2444
addons:

pkg/cloud/services/awsnode/cni.go

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ func (s *Service) ReconcileCNI(ctx context.Context) error {
7575
for i := range ds.Spec.Template.Spec.Containers {
7676
container := &ds.Spec.Template.Spec.Containers[i]
7777
if container.Name == "aws-node" {
78-
container.Env = s.filterEnv(container.Env)
7978
container.Env, needsUpdate = s.applyUserProvidedEnvironmentProperties(container.Env)
8079
}
8180
}
@@ -164,22 +163,7 @@ func (s *Service) ReconcileCNI(ctx context.Context) error {
164163
}
165164
}
166165

167-
s.scope.Info("updating containers", "cluster", klog.KRef(s.scope.Namespace(), s.scope.Name()))
168-
for i := range ds.Spec.Template.Spec.Containers {
169-
if ds.Spec.Template.Spec.Containers[i].Name == "aws-node" {
170-
ds.Spec.Template.Spec.Containers[i].Env = append(s.filterEnv(ds.Spec.Template.Spec.Containers[i].Env),
171-
corev1.EnvVar{
172-
Name: "AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG",
173-
Value: "true",
174-
},
175-
corev1.EnvVar{
176-
Name: "ENI_CONFIG_LABEL_DEF",
177-
Value: "failure-domain.beta.kubernetes.io/zone",
178-
},
179-
)
180-
}
181-
}
182-
166+
s.scope.Info("updating containers", "cluster-name", s.scope.Name(), "cluster-namespace", s.scope.Namespace())
183167
return remoteClient.Update(ctx, &ds, &client.UpdateOptions{})
184168
}
185169

@@ -199,18 +183,6 @@ func (s *Service) getSecurityGroups() ([]string, error) {
199183
return sgs, nil
200184
}
201185

202-
func (s *Service) filterEnv(env []corev1.EnvVar) []corev1.EnvVar {
203-
var i int
204-
for _, e := range env {
205-
if e.Name == "ENI_CONFIG_LABEL_DEF" || e.Name == "AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG" {
206-
continue
207-
}
208-
env[i] = e
209-
i++
210-
}
211-
return env[:i]
212-
}
213-
214186
// applyUserProvidedEnvironmentProperties takes a container environment and applies user provided values to it.
215187
func (s *Service) applyUserProvidedEnvironmentProperties(containerEnv []corev1.EnvVar) ([]corev1.EnvVar, bool) {
216188
var (

pkg/cloud/services/awsnode/cni_test.go

Lines changed: 37 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ func TestReconcileCniVpcCniValues(t *testing.T) {
5555
Kind: "DaemonSet",
5656
},
5757
ObjectMeta: metav1.ObjectMeta{
58-
Name: "aws-node",
59-
Namespace: "kube-system",
58+
Name: awsNodeName,
59+
Namespace: awsNodeNamespace,
6060
},
6161
Spec: v1.DaemonSetSpec{
6262
Template: corev1.PodTemplateSpec{
6363
ObjectMeta: metav1.ObjectMeta{},
6464
Spec: corev1.PodSpec{
6565
Containers: []corev1.Container{
6666
{
67-
Name: "aws-node",
67+
Name: awsNodeName,
6868
Env: []corev1.EnvVar{},
6969
},
7070
},
@@ -98,16 +98,16 @@ func TestReconcileCniVpcCniValues(t *testing.T) {
9898
Kind: "DaemonSet",
9999
},
100100
ObjectMeta: metav1.ObjectMeta{
101-
Name: "aws-node",
102-
Namespace: "kube-system",
101+
Name: awsNodeName,
102+
Namespace: awsNodeNamespace,
103103
},
104104
Spec: v1.DaemonSetSpec{
105105
Template: corev1.PodTemplateSpec{
106106
ObjectMeta: metav1.ObjectMeta{},
107107
Spec: corev1.PodSpec{
108108
Containers: []corev1.Container{
109109
{
110-
Name: "aws-node",
110+
Name: awsNodeName,
111111
Env: []corev1.EnvVar{},
112112
},
113113
},
@@ -141,16 +141,16 @@ func TestReconcileCniVpcCniValues(t *testing.T) {
141141
Kind: "DaemonSet",
142142
},
143143
ObjectMeta: metav1.ObjectMeta{
144-
Name: "aws-node",
145-
Namespace: "kube-system",
144+
Name: awsNodeName,
145+
Namespace: awsNodeNamespace,
146146
},
147147
Spec: v1.DaemonSetSpec{
148148
Template: corev1.PodTemplateSpec{
149149
ObjectMeta: metav1.ObjectMeta{},
150150
Spec: corev1.PodSpec{
151151
Containers: []corev1.Container{
152152
{
153-
Name: "aws-node",
153+
Name: awsNodeName,
154154
Env: []corev1.EnvVar{
155155
{
156156
Name: "NAME1",
@@ -184,7 +184,7 @@ func TestReconcileCniVpcCniValues(t *testing.T) {
184184
},
185185
}
186186
for _, tc := range tests {
187-
t.Run(tc.name, func(t *testing.T) {
187+
t.Run(tc.name+" without secondary cidr", func(t *testing.T) {
188188
mockCtrl := gomock.NewController(t)
189189
defer mockCtrl.Finish()
190190
g := NewWithT(t)
@@ -206,92 +206,37 @@ func TestReconcileCniVpcCniValues(t *testing.T) {
206206
g.Expect(ds.Spec.Template.Spec.Containers[0].Env).To(ConsistOf(tc.consistsOf))
207207
})
208208
}
209-
}
210209

211-
func TestReconcileCniVpcCniValuesWithSecondaryCidrBlock(t *testing.T) {
212-
mockCtrl := gomock.NewController(t)
213-
defer mockCtrl.Finish()
214-
g := NewWithT(t)
215-
daemonSet := &v1.DaemonSet{
216-
TypeMeta: metav1.TypeMeta{
217-
Kind: "DaemonSet",
218-
},
219-
ObjectMeta: metav1.ObjectMeta{
220-
Name: "aws-node",
221-
Namespace: "kube-system",
222-
},
223-
Spec: v1.DaemonSetSpec{
224-
Template: corev1.PodTemplateSpec{
225-
ObjectMeta: metav1.ObjectMeta{},
226-
Spec: corev1.PodSpec{
227-
Containers: []corev1.Container{
228-
{
229-
Name: "aws-node",
230-
Env: []corev1.EnvVar{
231-
{
232-
Name: "NAME1",
233-
Value: "OVERWRITE",
234-
},
235-
{
236-
Name: "NAME3",
237-
Value: "VALUE3",
238-
},
239-
},
240-
},
210+
for _, tc := range tests {
211+
t.Run(tc.name+" with secondary cidr", func(t *testing.T) {
212+
mockCtrl := gomock.NewController(t)
213+
defer mockCtrl.Finish()
214+
g := NewWithT(t)
215+
mockClient := &cachingClient{
216+
getValue: tc.daemonSet,
217+
}
218+
m := &mockScope{
219+
client: mockClient,
220+
cni: tc.cniValues,
221+
secondaryCidrBlock: aws.String("100.0.0.1/20"),
222+
securityGroups: map[infrav1.SecurityGroupRole]infrav1.SecurityGroup{
223+
"node": {
224+
ID: "sg-1234",
225+
Name: "node",
241226
},
242227
},
243-
},
244-
},
245-
}
246-
values := ekscontrolplanev1.VpcCni{
247-
Env: []corev1.EnvVar{
248-
{
249-
Name: "NAME1",
250-
Value: "VALUE1",
251-
},
252-
},
253-
}
254-
mockClient := &cachingClient{
255-
getValue: daemonSet,
256-
}
257-
m := &mockScope{
258-
client: mockClient,
259-
cni: values,
260-
secondaryCidrBlock: aws.String("100.0.0.1/20"),
261-
securityGroups: map[infrav1.SecurityGroupRole]infrav1.SecurityGroup{
262-
"node": {
263-
ID: "sg-1234",
264-
Name: "node",
265-
},
266-
},
267-
subnets: []infrav1.SubnetSpec{},
268-
}
269-
s := NewService(m)
228+
}
229+
s := NewService(m)
270230

271-
err := s.ReconcileCNI(context.Background())
272-
g.Expect(err).NotTo(HaveOccurred())
273-
g.Expect(mockClient.updateChain).NotTo(BeEmpty())
274-
ds, ok := mockClient.updateChain[0].(*v1.DaemonSet)
275-
g.Expect(ok).To(BeTrue())
276-
g.Expect(ds.Spec.Template.Spec.Containers).NotTo(BeEmpty())
277-
g.Expect(ds.Spec.Template.Spec.Containers[0].Env).To(ConsistOf([]corev1.EnvVar{
278-
{
279-
Name: "NAME1",
280-
Value: "VALUE1",
281-
},
282-
{
283-
Name: "NAME3",
284-
Value: "VALUE3",
285-
},
286-
{
287-
Name: "AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG",
288-
Value: "true",
289-
},
290-
{
291-
Name: "ENI_CONFIG_LABEL_DEF",
292-
Value: "failure-domain.beta.kubernetes.io/zone",
293-
},
294-
}))
231+
err := s.ReconcileCNI(context.Background())
232+
g.Expect(err).NotTo(HaveOccurred())
233+
g.Expect(mockClient.updateChain).NotTo(BeEmpty())
234+
ds, ok := mockClient.updateChain[0].(*v1.DaemonSet)
235+
g.Expect(ok).To(BeTrue())
236+
g.Expect(ds.Spec.Template.Spec.Containers).NotTo(BeEmpty())
237+
g.Expect(ds.Spec.Template.Spec.Containers[0].Env).To(ConsistOf(tc.consistsOf))
238+
})
239+
}
295240
}
296241

297242
type cachingClient struct {

0 commit comments

Comments
 (0)