When using kubernetes, you often have to modify the official k8s source code and recompile it due to certain needs. This article explains how to use GitHub Actions to compile and publish the generated binaries by modifying the kubeadm generation certificate to the default 10 years.

Build

clone repo

Fork the official kubernetes source code to your own repo

1
2
3
4
5
6
$ git clone https://github.com/k8sli/kubernetes.git
$ cd kubernetes
$ git remote add upstream https://github.com/kubernetes/kubernetes.git
$ git fetch --all
$ git checkout upstream/release-1.21
$ git checkout -B kubeadm-1.21

workflow

  • github/workflows/kubeadm.yaml

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    
    ---
    name: Build kubeadm binary
    
    on:
    push:
        tag:
        - 'v*'
    jobs:
    build:
        runs-on: ubuntu-20.04
        # Here we choose to trigger the job as a tag
        if: startsWith(github.ref, 'refs/tags/')
        steps:
        - name: Checkout
            uses: actions/checkout@v2
    
        - name: Build kubeadm binary
            shell: bash
            run: |
            # Run the build/run.sh build script to compile the binaries on the appropriate platform
            build/run.sh make kubeadm KUBE_BUILD_PLATFORMS=linux/amd64
            build/run.sh make kubeadm KUBE_BUILD_PLATFORMS=linux/arm64        
    
        # The built binaries are stored in _output/dockerized/bin/
        # We name the binary target file according to its system name + CPU architecture name
        - name: Prepare for upload
            shell: bash
            run: |
            mv _output/dockerized/bin/linux/amd64/kubeadm kubeadm-linux-amd64
            mv _output/dockerized/bin/linux/arm64/kubeadm kubeadm-linux-arm64
            sha256sum kubeadm-linux-{amd64,arm64} > sha256sum.txt        
    
        # Use softprops/action-gh-release to upload the build to the GitHub release
        - name: Release and upload packages
            uses: softprops/action-gh-release@v1
            env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
            with:
            files: |
                sha256sum.txt
                kubeadm-linux-amd64
                kubeadm-linux-arm64            
    
  • build/run.sh

    : Run a command in a build docker container. Common invocations:

    • build/run.sh make : Build just linux binaries in the container. Pass options and packages as necessary.
    • build/run.sh make cross : Build all binaries for all platforms. To build only a specific platform, add KUBE_BUILD_PLATFORMS=<os>/<arch>
    • build/run.sh make kubectl KUBE_BUILD_PLATFORMS=darwin/amd64 : Build the specific binary for the specific platform ( kubectl and darwin/amd64 respectively in this example)
    • build/run.sh make test : Run all unit tests
    • build/run.sh make test-integration : Run integration test
    • build/run.sh make test-cmd : Run CLI tests

Modify source code

  • cmd/kubeadm/app/constants/constants.go

    Find the CertificateValidity variable and add a 0 to it after 375 days to renew the certificate to 10 years.

    1
    2
    3
    4
    5
    6
    
        // CertificateValidity defines the validity for all the signed certificates generated by kubeadm
    -	CertificateValidity = time.Hour * 24 * 365
    +	CertificateValidity = time.Hour * 24 * 3650
    
        // CACertAndKeyBaseName defines certificate authority base name
        CACertAndKeyBaseName = "ca"
    
  • git diff

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    diff --git a/.github/workflows/kubeadm.yaml b/.github/workflows/kubeadm.yaml
    new file mode 100644
    index 00000000000..376f37c0edf
    --- /dev/null
    +++ b/.github/workflows/kubeadm.yaml
    @@ -0,0 +1,37 @@
    +---
    +name: Build kubeadm binary image
    +
    +on:
    +  push:
    +    tag:
    +      - 'v*'
    +jobs:
    +  build:
    +    runs-on: ubuntu-20.04
    +    if: startsWith(github.ref, 'refs/tags/')
    +    steps:
    +      - name: Checkout
    +        uses: actions/checkout@v2
    +
    +      - name: Build kubeadm binary
    +        shell: bash
    +        run: |
    +          build/run.sh make kubeadm KUBE_BUILD_PLATFORMS=linux/amd64
    +          build/run.sh make kubeadm KUBE_BUILD_PLATFORMS=linux/arm64
    +
    +      - name: Prepare for upload
    +        shell: bash
    +        run: |
    +          mv _output/dockerized/bin/linux/amd64/kubeadm kubeadm-linux-amd64
    +          mv _output/dockerized/bin/linux/arm64/kubeadm kubeadm-linux-arm64
    +          sha256sum kubeadm-linux-{amd64,arm64} > sha256sum.txt
    +
    +      - name: Release and upload packages
    +        uses: softprops/action-gh-release@v1
    +        env:
    +          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    +        with:
    +          files: |
    +            sha256sum.txt
    +            kubeadm-linux-amd64
    +            kubeadm-linux-arm64
    diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go
    index aed3a713020..08a24d237f8 100644
    --- a/cmd/kubeadm/app/constants/constants.go
    +++ b/cmd/kubeadm/app/constants/constants.go
    @@ -46,7 +46,7 @@ const (
        TempDirForKubeadm = "tmp"
    
        // CertificateValidity defines the validity for all the signed certificates generated by kubeadm
    -	CertificateValidity = time.Hour * 24 * 365
    +	CertificateValidity = time.Hour * 24 * 3650
    
        // CACertAndKeyBaseName defines certificate authority base name
        CACertAndKeyBaseName = "ca"
    

cherry-pick

After the changes are done on the branch, we will cherry-pick the changes to other tags, here is the example of v1.21.4: cherry-pick the above changes on top of the v1.21.4 tag and re-tag it with a new tag.

  • Get the commit id of the above modification

    1
    
    $ COMMIT_ID=$(git rev-parse HEAD)
    
  • checkout to v1.21.4 on this tag

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    $ git checkout v1.21.4
    Note: checking out 'v1.21.4'.
    
    You are in 'detached HEAD' state. You can look around, make experimental
    changes and commit them, and you can discard any commits you make in this
    state without impacting any branches by performing another checkout.
    
    If you want to create a new branch to retain commits you create, you may
    do so (now or later) by using -b with the checkout command again. Example:
    
    HEAD is now at 3cce4a82b44 Release commit for Kubernetes v1.21.4
    
  • Add the modification cherry-pick to the current tag

    1
    2
    3
    4
    5
    
    $ git cherry-pick $COMMIT_ID
    [detached HEAD baadbe03458] Update kubeadm CertificateValidity time to ten years
    Date: Tue Aug 24 16:32:49 2021 +0800
    2 files changed, 38 insertions(+), 1 deletion(-)
    create mode 100644 .github/workflows/kubeadm.yaml
    
  • Re-type the new tag, e.g. v1.21.4-patch-1.0

    1
    2
    
    $ git tag v1.21.4-patch-1.0 -f
    Updated tag 'v1.21.4-patch-1.0' (was 70bcbd6de6c)
    

  • Push tag to repo to trigger workflow

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    $ git push origin --tags -f
    Enumerating objects: 17, done.
    Counting objects: 100% (17/17), done.
    Delta compression using up to 4 threads
    Compressing objects: 100% (9/9), done.
    Writing objects: 100% (10/10), 1.13 KiB | 192.00 KiB/s, done.
    Total 10 (delta 7), reused 0 (delta 0)
    remote: Resolving deltas: 100% (7/7), completed with 7 local objects.
    To github.com:k8sli/kubernetes.git
    + c2a633e07ec...baadbe03458 v1.21.4-patch-1.0 -> v1.21.4-patch-1.0 (forced update)
    

  • The entire build process takes about 7 minutes, which is quite efficient.

Summary

The above only shows the process of building with one tag, if you want to build other versions of kubeadm, you can follow the same process and method. In fact, it is quite simple to write a shell script to handle this, as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash

set -o errexit
set -o nounset

# Define commit ID
: ${COMMIT:="48e4b4c7c62a84ab4ec363588721011b73ee77e6"}

# Define the version number that needs to be recompiled
: ${TAGS:="v1.22.1 v1.22.0 v1.21.4 v1.21.3 v1.20.10 v1.19.14 v1.18.10"}

for tag in ${TAGS}; do
    git reset --hard ${tag}
    git cherry-pick ${COMMIT}
    git tag ${tag}-patch-1.0
    git push origin ${tag}-patch-1.0
done

The advantage of using GitHub Actions is that it takes care of code management and product management for us. The built binaries are stored in the GitHub release and are easy to download and use, so you don’t have to get a separate machine or storage server, which saves you a lot of labor and maintenance costs.


Reference https://blog.k8s.li/build-k8s-binary-by-github-actions.html