Build a way

The construction methods of Kubernetes can be divided into three kinds, namely, local environment construction, container environment construction and Bazel environment construction.

Kubernetes build method:

  • Local Environment Construction
    1. make
    2. make all
  • Container environment construction
    1. make release
    2. make quick-release
  • Bazel environment build
    1. make bazel-build

The first two are described in detail below:

Local Environment Construction

Make or make all compiles all components of Kubernetes. The relative path of the component binary output is _output/bin. If we need to debug the execution of the Makefile, we can show a more detailed build by adding the -n argument to the make command to print but not execute all the execution commands. Suppose we want to build some valence separately, such as a Kubectl component, we need to specify the WHAT parameter. The following is an example command:

make WHAT=cmd/kubectl
Copy the code

Makefile is a very automatic build tool that can be used to build and test Go applications. Makefile is also suitable for most programming languages. In the source directory of Kubernetes, there are two Makefile related files, which are as follows:

  • Makefile: A top-level Makefile that describes the compilation order, compilation rules, and binary output of all code files in a project.
  • Makefile.generated_file: describes the logic for code generation.

Local build process

Start building components by calling the hack/make-rules/build.sh script, passing in the name of the component to build, and building all components without specifying a component name. The following is an example of the hack/make-rules/build.sh code:

kube::golang::build_binaries "$@"
Copy the code

Build_binaries takes the name of the built component, sets the environment required for the build and some Go flags options required at compile time, and then builds the component with Go Install:

go install "${build_args[@]}" "$@"
Copy the code

After the go install command is executed, the binary output directory is _output/bin. Finally, you can use the make clean command to clean up the build environment.

Container environment construction

Kubernetes is also very easy to build with containers (Docker). Kubernetes provides two ways to build with containers: make Release and make Quick-release.

  • Make release: Build all target platforms (Darwin, Linux, Windows), take a long time to build and unit test at the same time.
  • Make Quick-release: Build quickly, build only the current platform and skip the unit testing process. Kubernetes container environment construction process:
Build environment configuration and verification :kube::build:: verify_PREReqs Build container image :kube::build::build_image Build code :kube::build::run_build_command make cross Copy files from the container to the host :kube::build::copy_output Package :kube:: Release ::package_tarballsCopy the code

In the process of container environment construction, there are several container images involved, as follows:

  • Build container (kube-cross): A build container in which a build operation is performed on the code file, which is then deleted.
  • Data container: Storage container for all files needed during the build process.
  • Raync container: Synchronization container: Used to transfer data between the container and the host. It will be deleted after completion. Here is the Kubernetes container environment construction process.

1.kube::build::verfy_prereqs

Configure and verify the build environment. This procedure checks whether the Docker container environment is installed on the machine, and in the case of Darwin platforms, whether the Docker-Machine environment is installed on the machine.

2.kube::build::build_image

Build the container image from Dockerfile. The Dockerfile file is from build/build-image/Dockerfile. The code is as follows: The code path is build/common.sh

function kube::build::build_image() {
  mkdir -p "${LOCAL_OUTPUT_BUILD_CONTEXT}"
  ...
  cp "${KUBE_ROOT}/build/build-image/Dockerfile" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
  cp "${KUBE_ROOT}/build/build-image/rsyncd.sh" "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
  dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null > "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
  chmod go= "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"

  kube::build::update_dockerfile
  kube::build::set_proxy
  kube::build::docker_build "${KUBE_BUILD_IMAGE}" "${LOCAL_OUTPUT_BUILD_CONTEXT}" 'false'
  ...
  kube::build::ensure_data_container
  kube::build::sync_to_container
}
Copy the code

The process for building a container image is as follows:

  • Create the folder to build the image (that is, _output/images/…) with the mkdir command. .
  • Use the cp command to copy the files required for image construction, such as Dockerfile files and rsyncd synchronization scripts.
  • Build the container image using the kube::build::docker_build function.
  • Run the storage container and mount the Volume using the kube::build::ensure_data_container function.
  • Using the kube::build::sync_to_container function, run the synchronization container and mount the Volume of the storage container, and then use the rsnyc command to synchronize the Kubernetes source code to the Volume of the storage container.

3.kube::build::run_build_command make cross

Now that the container build environment is ready, run the build container and build Kubernetes source code inside the build container as shown in the following code path: build/common.sh

function kube::build::run_build_command_ex() {
  ...
  local detach=false
  ...
  "${docker_cmd[@]}" "${cmd[@]}"
  if [[ "${detach}" == false ]]; then
    kube::build::destroy_container "${container_name}"
  fi
}
Copy the code

In executing kube::build::run_build_command_ex, Dockercmd [@]””{docker_cmd[@]}””dockercmd[@]””{CMD [@]}} command to perform the build operation (that is, make cross within the container). The build process within the container is the same as the build process in the local environment. Where build platform has KUBE_SUPPORTED_SERVER_PLATFORMS variable control, code examples are as follows: code path: hack/lib/golang.sh

readonly KUBE_SUPPORTED_SERVER_PLATFORMS=(
  linux/amd64
  linux/arm
  linux/arm64
  linux/s390x
  linux/ppc64le
)
Copy the code

The build component is controlled by the KUBE_SERVER_TARGETS variable. The code is as follows: code path: hack/lib/golang.sh

kube::golang::server_targets() {
  local targets=(
    cmd/kube-proxy
    cmd/kube-apiserver
    cmd/kube-controller-manager
    cmd/kubelet
    cmd/kubeadm
    cmd/kube-scheduler
    vendor/k8s.io/kube-aggregator
    vendor/k8s.io/apiextensions-apiserver
    cluster/gce/gci/mounter
  )
  echo "${targets[@]}"
}

IFS=" " read -ra KUBE_SERVER_TARGETS <<< "$(kube::golang::server_targets)"
Copy the code

4.kube::build::copy_output

Use a synchronous container to copy the compiled code file to the host.

5.kube::release::package_tarballs

Package the binaries into the _output directory. Finally, the code file is exported as a tar.gz package to the _output/release-tars folder.