Skip to content

Commit

Permalink
copy CNI plugin and config in entrypoint not agent
Browse files Browse the repository at this point in the history
Replaces the hard-coded copying of the CNI plugin binary and
configuration file from the main.go of the aws-k8s-agent (the IPAMd
daemon) into a new entrypoint.sh script that backgrounds the IPAM
daemon, waits for it to listen on port 50051 and then proceeds to copy
the CNI plugin binaries and configuration files into the well-known
directory for Kubelet to see them as ready.
  • Loading branch information
jaypipes committed Dec 3, 2019
1 parent 289812a commit 60aefaf
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 102 deletions.
4 changes: 4 additions & 0 deletions config/v1.5/aws-k8s-cni.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ spec:
env:
- name: AWS_VPC_K8S_CNI_LOGLEVEL
value: DEBUG
- name: AWS_VPC_K8S_CNI_VETHPREFIX
value: eni
- name: AWS_VPC_K8S_CNI_MTU
value: 9001
- name: MY_NODE_NAME
valueFrom:
fieldRef:
Expand Down
52 changes: 0 additions & 52 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
package main

import (
"io"
"os"

"github.com/aws/amazon-vpc-cni-k8s/pkg/utils/logger"
Expand Down Expand Up @@ -74,21 +73,6 @@ func _main() int {
// CNI introspection endpoints
go ipamContext.ServeIntrospection()

// Copy the CNI plugin and config. This will mark the node as Ready.
log.Info("Copying /app/aws-cni to /host/opt/cni/bin/aws-cni")
err = copyFileContents("/app/aws-cni", "/host/opt/cni/bin/aws-cni")
if err != nil {
log.Errorf("Failed to copy aws-cni: %v", err)
return 1
}

log.Info("Copying /app/10-aws.conflist to /host/etc/cni/net.d/10-aws.conflist")
err = copyFileContents("/app/10-aws.conflist", "/host/etc/cni/net.d/10-aws.conflist")
if err != nil {
log.Errorf("Failed to copy 10-aws.conflist: %v", err)
return 1
}

// Start the RPC listener
err = ipamContext.RunRPCHandler()
if err != nil {
Expand All @@ -97,39 +81,3 @@ func _main() int {
}
return 0
}

// copyFileContents copies a file
func copyFileContents(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer func() {
e := out.Close()
if err == nil {
err = e
}
}()
if _, err = io.Copy(out, in); err != nil {
return err
}
err = out.Sync()
if err != nil {
return err
}
si, err := os.Stat(src)
if err != nil {
return err
}
err = os.Chmod(dst, si.Mode())
if err != nil {
return err
}
log.Debugf("Copied file from %q to %q", src, dst)
return err
}
48 changes: 0 additions & 48 deletions main_test.go

This file was deleted.

4 changes: 2 additions & 2 deletions scripts/dockerfiles/Dockerfile.release
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ COPY --from=builder /go/src/github.com/aws/amazon-vpc-cni-k8s/aws-cni \
/go/src/github.com/aws/amazon-vpc-cni-k8s/aws-k8s-agent \
/go/src/github.com/aws/amazon-vpc-cni-k8s/grpc_health_probe \
/go/src/github.com/aws/amazon-vpc-cni-k8s/scripts/aws-cni-support.sh \
/go/src/github.com/aws/amazon-vpc-cni-k8s/scripts/install-aws.sh /app/
/go/src/github.com/aws/amazon-vpc-cni-k8s/scripts/entrypoint.sh /app/

ENTRYPOINT /app/install-aws.sh
ENTRYPOINT /app/entrypoint.sh
73 changes: 73 additions & 0 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash

# NOTE(jaypipes): Normally, we would prefer *not* to have an entrypoint script
# and instead just start the agent daemon as the container's CMD. However, the
# design of CNI is such that Kubelet looks for the presence of binaries and CNI
# configuration files in specific directories, and the presence of those files
# is the trigger to Kubelet that that particular CNI plugin is "ready".
#
# In the case of the AWS VPC CNI plugin, we have two components to the plugin.
# The first component is the actual CNI binary that is execve'd from Kubelet
# when a container is started or destroyed. The second component is the
# aws-k8s-agent daemon which houses the IPAM controller.
#
# As mentioned above, Kubelet considers a CNI plugin "ready" when it sees the
# binary and configuration file for the plugin in a well-known directory. For
# the AWS VPC CNI plugin binary, we only want to copy the CNI plugin binary
# into that well-known directory AFTER we have succeessfully started the IPAM
# daemon and know that it can connect to Kubernetes and the local EC2 metadata
# service. This is why this entrypoint script exists; we start the IPAM daemon
# and wait until we know it is up and running successfully before copying the
# CNI plugin binary and its configuration file to the well-known directory that
# Kubelet looks in.

# turn on bash's job control
set -m

# Checks for IPAM connectivity on localhost port 50051, retrying connectivity
# check with a timeout of 36 seconds
wait_for_ipam() {
local __sleep_time=0

until [ $__sleep_time -eq 8 ]; do
sleep $(( __sleep_time++ ))
if /app/grpc_health_probe -addr 127.0.0.1:50051 </dev/null; then
return 0
fi
done
return 1
}

echo -n "starting IPAM daemon in background ... "
./app/aws-k8s-agent &
echo "ok."

echo -n "checking for IPAM connectivity ... "

if ! wait_for_ipam; then
echo " failed."
echo "timed out waiting for IPAM daemon to start."
exit 1
fi

echo "ok."

echo -n "copying CNI plugin binaries and config files ... "

sed -i s/__VETHPREFIX__/"${AWS_VPC_K8S_CNI_VETHPREFIX:-"eni"}"/g /app/10-aws.conflist
sed -i s/__MTU__/"${AWS_VPC_ENI_MTU:-"9001"}"/g /app/10-aws.conflist
mv /app/10-aws.conflist /host/etc/cni/net.d/
mv /app/portmap /host/opt/cni/bin/
mv /app/aws-cni /host/opt/cni/bin/
mv /app/aws-cni-support.sh /host/opt/cni/bin/

echo " ok."

if [[ -f /host/etc/cni/net.d/aws.conf ]]; then
rm /host/etc/cni/net.d/aws.conf
fi

# bring the aws-k8s-agent process back into the foreground
echo -n "foregrounding IPAM daemon ... "
fg %1
echo "ok."

0 comments on commit 60aefaf

Please sign in to comment.