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 authored and mogren committed Dec 9, 2019
1 parent 6211e63 commit 88b52cc
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 102 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ docker:
@docker build --build-arg arch="$(ARCH)" -f scripts/dockerfiles/Dockerfile.release -t "$(IMAGE):$(VERSION)" .
@echo "Built Docker image \"$(IMAGE):$(VERSION)\""

docker-func-test: docker
docker run -it "$(IMAGE):$(VERSION)"

# unit-test
unit-test:
GOOS=linux CGO_ENABLED=1 go test -v -cover $(ALLPKGS)
Expand Down
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
91 changes: 91 additions & 0 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/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

# Check for all the required binaries before we go forward
if [ ! -x $(command -v aws-k8s-agent) ]; then
echo "Required aws-k8s-agent executable not found."
exit 1
fi
if [ ! -x $(command -v grp_health_probe) ]; then
echo "Required grp_health_probe executable not found."
exit 1
fi

AGENT_LOG_PATH=${AGENT_LOG_PATH:-aws-k8s-agent.log}
HOST_CNI_BIN_PATH=${HOST_CNI_BIN_PATH:-/host/opt/cni/bin}
HOST_CNI_CONFDIR_PATH=${HOST_CNI_CONFDIR_PATH:-/host/opt/cni/net.d}

# 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 $(./grpc_health_probe -addr 127.0.0.1:50051 >/dev/null 2>&1); then
return 0
fi
done
return 1
}

echo -n "starting IPAM daemon in background ... "
./aws-k8s-agent > $AGENT_LOG_PATH 2>&1 &
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 ... "

cp portmap $HOST_CNI_BIN_PATH
cp aws-cni $HOST_CNI_BIN_PATH$
cp aws-cni-support.sh $HOST_CNI_BIN_PATH

sed -i s/__VETHPREFIX__/"${AWS_VPC_K8S_CNI_VETHPREFIX:-"eni"}"/g 10-aws.conflist
sed -i s/__MTU__/"${AWS_VPC_ENI_MTU:-"9001"}"/g 10-aws.conflist
cp 10-aws.conflist $HOST_CNI_CONFDIR_PATH

echo " ok."

if [[ -f "$HOST_CNI_CONFDIR_PATH/aws.conf" ]]; then
rm "$HOST_CNI_CONFDIR_PATH/aws.conf"
fi

# bring the aws-k8s-agent process back into the foreground
echo "foregrounding IPAM daemon ... "
fg %1 >/dev/null 2>&1 || $(echo "failed (process terminated)" && cat $AGENT_LOG_PATH && exit 1)

# Best practice states we should send the container's CMD output to stdout, so
# let's tee back up the log file into stdout
cat $AGENT_LOG_PATH

0 comments on commit 88b52cc

Please sign in to comment.