├── .dockerignore ├── .github ├── .cr.yaml └── workflows │ ├── codeql-analysis.yml │ └── release.yaml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yml ├── .markdownlint.json ├── Dockerfile ├── Dockerfile.agent ├── LICENSE ├── Makefile ├── README.md ├── charts └── lxcfs-on-kubernetes │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── templates │ ├── _helpers.tpl │ ├── certificate.yaml │ ├── clusterrole.yaml │ ├── clusterrolebinding.yaml │ ├── daemonset.yaml │ ├── deployment.yaml │ ├── issuer.yaml │ ├── mutatingwebhookconfiguration.yaml │ └── service.yaml │ └── values.yaml ├── cmd └── manager │ └── main.go ├── config ├── certmanager │ ├── certificate.yaml │ ├── kustomization.yaml │ └── kustomizeconfig.yaml ├── default │ ├── daemonset_patch.yaml │ ├── deployment_patch.yaml │ ├── kustomization.yaml │ ├── manager_webhook_patch.yaml │ └── webhookcainjection_patch.yaml ├── helm │ ├── certificate │ │ ├── kustomization.yaml │ │ ├── patch_certificate_dns.yaml │ │ └── patch_certificate_secret.yaml │ ├── manager │ │ ├── kustomization.yaml │ │ ├── patch_daemonset_config.yaml │ │ ├── patch_daemonset_metadata.yaml │ │ ├── patch_daemonset_resources.yaml │ │ ├── patch_daemonset_security.yaml │ │ ├── patch_deployment_config.yaml │ │ ├── patch_deployment_metadata.yaml │ │ ├── patch_deployment_resources.yaml │ │ ├── patch_deployment_security.yaml │ │ ├── patch_deployment_spec.yaml │ │ └── patch_deployment_webhook.yaml │ ├── rbac │ │ ├── kustomization.yaml │ │ └── patch_clusterrolebinding.yaml │ └── webhook │ │ ├── kustomization.yaml │ │ ├── mutatingwebhook_endpoint_patch.yaml │ │ └── patch_mutatingwebhook_config.yaml ├── manager │ ├── daemonset_patch.yaml │ ├── deployment_patch.yaml │ ├── kustomization.yaml │ └── manifests.yaml ├── rbac │ ├── kustomization.yaml │ ├── role.yaml │ └── role_binding.yaml └── webhook │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ ├── manifests.yaml │ ├── mutatingwebhook_patch.yaml │ └── service.yaml ├── go.mod ├── go.sum ├── hack ├── boilerplate.go.txt └── boilerplate.txt ├── pkg └── admission │ └── mutate.go └── version └── version.go /.dockerignore: -------------------------------------------------------------------------------- 1 | # Git files 2 | .git** 3 | 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | bin 11 | node_modules 12 | 13 | # Test binary, build with `go test -c` 14 | *.test 15 | 16 | # Output of the go coverage tool, specifically when used with LiteIDE 17 | *.out 18 | 19 | # Kubernetes Generated files - skip generated files, except for vendored files 20 | **/zz_generated.* 21 | !vendor/**/zz_generated.* 22 | 23 | # editor and IDE paraphernalia 24 | .idea 25 | *.swp 26 | *.swo 27 | *~ 28 | 29 | ## Github 30 | .github 31 | 32 | ## KubeBuilder autogenerated files 33 | charts 34 | config/crd/bases 35 | config/rbac/role.yaml 36 | config/webhook/manifests.yaml 37 | 38 | ## goreleaser 39 | dist/ 40 | -------------------------------------------------------------------------------- /.github/.cr.yaml: -------------------------------------------------------------------------------- 1 | git-repo: lxcfs-on-kubernetes 2 | release-name-template: "v{{ .Version }}" 3 | skip-existing: true 4 | owner: cndoit18 5 | package-path: charts 6 | charts-repo: https://cndoit18.github.io/lxcfs-on-kubernetes/ 7 | index-path: index.yaml -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '34 9 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'go' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: Version 8 | required: true 9 | 10 | jobs: 11 | release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | with: 17 | fetch-depth: 0 18 | submodules: recursive 19 | 20 | - name: Set up Go 21 | uses: actions/setup-go@v2 22 | with: 23 | go-version: 1.17 24 | 25 | - name: Install Helm 26 | uses: azure/setup-helm@v1 27 | with: 28 | version: v3.6.0 29 | - name: Generate Helm 30 | run: | 31 | APP_VERSION=${{github.event.inputs.version}} make generate 32 | 33 | - name: Tag 34 | run: | 35 | git config user.name "$GITHUB_ACTOR" 36 | git config user.email "$GITHUB_ACTOR@outlook.com" 37 | git commit -am 'release ${{ github.event.inputs.version }}' || true 38 | git push -f origin master 39 | tag='${{ github.event.inputs.version }}' 40 | git tag --annotate --message "Tag for release $tag" "$tag" 41 | git push origin "refs/tags/$tag" 42 | 43 | - name: Docker Login 44 | uses: docker/login-action@v1 45 | with: 46 | registry: ghcr.io 47 | username: ${{ github.repository_owner }} 48 | password: ${{ secrets.GH_PAT }} 49 | 50 | - name: Check GoReleaser config 51 | uses: goreleaser/goreleaser-action@v2 52 | with: 53 | version: latest 54 | args: check 55 | 56 | - name: Run GoReleaser 57 | uses: goreleaser/goreleaser-action@v2 58 | with: 59 | distribution: goreleaser 60 | version: latest 61 | args: release --rm-dist 62 | env: 63 | GITHUB_TOKEN: ${{ secrets.GH_PAT }} 64 | 65 | - name: Push Charts 66 | run: | 67 | make helm-push 68 | env: 69 | CR_TOKEN: "${{ secrets.GH_PAT }}" 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/helm,macos,visualstudiocode,go 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=helm,macos,visualstudiocode,go 4 | 5 | ### Go ### 6 | # Binaries for programs and plugins 7 | *.exe 8 | *.exe~ 9 | *.dll 10 | *.so 11 | *.dylib 12 | 13 | # Test binary, built with `go test -c` 14 | *.test 15 | 16 | # Output of the go coverage tool, specifically when used with LiteIDE 17 | *.out 18 | 19 | # Dependency directories (remove the comment below to include it) 20 | # vendor/ 21 | 22 | ### Go Patch ### 23 | /vendor/ 24 | /Godeps/ 25 | 26 | ### Helm ### 27 | # Chart dependencies 28 | **/charts/*.tgz 29 | 30 | ### macOS ### 31 | # General 32 | .DS_Store 33 | .AppleDouble 34 | .LSOverride 35 | 36 | # Icon must end with two \r 37 | Icon 38 | 39 | 40 | # Thumbnails 41 | ._* 42 | 43 | # Files that might appear in the root of a volume 44 | .DocumentRevisions-V100 45 | .fseventsd 46 | .Spotlight-V100 47 | .TemporaryItems 48 | .Trashes 49 | .VolumeIcon.icns 50 | .com.apple.timemachine.donotpresent 51 | 52 | # Directories potentially created on remote AFP share 53 | .AppleDB 54 | .AppleDesktop 55 | Network Trash Folder 56 | Temporary Items 57 | .apdisk 58 | 59 | ### VisualStudioCode ### 60 | .vscode/* 61 | !.vscode/settings.json 62 | !.vscode/tasks.json 63 | !.vscode/launch.json 64 | !.vscode/extensions.json 65 | *.code-workspace 66 | 67 | # Local History for Visual Studio Code 68 | .history/ 69 | .bin/ 70 | dist/ 71 | 72 | ### VisualStudioCode Patch ### 73 | # Ignore all local history of files 74 | .history 75 | .ionide 76 | 77 | # End of https://www.toptal.com/developers/gitignore/api/helm,macos,visualstudiocode,go -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | dupl: 3 | threshold: 400 4 | gocyclo: 5 | min-complexity: 10 6 | govet: 7 | check-shadowing: true 8 | lll: 9 | line-length: 170 10 | tab-width: 4 11 | gofmt: 12 | simplify: false 13 | 14 | run: 15 | tests: false 16 | skip-dirs: 17 | - vendor 18 | skip-files: 19 | - zz_generated.*.go 20 | 21 | 22 | 23 | linters: 24 | presets: 25 | - bugs 26 | - unused 27 | - format 28 | - style 29 | - complexity 30 | - performance 31 | 32 | # we should re-enable them and make lint pass 33 | disable: 34 | - goimports 35 | - maligned 36 | - gochecknoglobals 37 | - whitespace 38 | - scopelint 39 | - wsl 40 | - gochecknoinits 41 | - godox 42 | - funlen 43 | - gci 44 | - stylecheck 45 | - gocritic 46 | - gomnd 47 | - gocognit 48 | 49 | issues: 50 | max-same-issues: 0 51 | exclude-use-default: false 52 | exclude: 53 | # gosec G104, about unhandled errors. We do that with errcheck already 54 | - "G104: Errors unhandled" 55 | exclude-rules: 56 | - linters: 57 | # Ignore package comments (ST1000) since most of the time are irrelevant 58 | - stylecheck 59 | text: "ST1000" 60 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # This is an example .goreleaser.yml file with some sane defaults. 2 | # Make sure to check the documentation at https://goreleaser.com 3 | builds: 4 | - skip: true 5 | 6 | 7 | dockers: 8 | - image_templates: 9 | - "ghcr.io/cndoit18/lxcfs-agent:{{ .Tag }}" 10 | - "ghcr.io/cndoit18/lxcfs-agent:latest" 11 | 12 | skip_push: false 13 | 14 | dockerfile: Dockerfile.agent 15 | 16 | - image_templates: 17 | - "ghcr.io/cndoit18/lxcfs-manager:{{ .Tag }}" 18 | - "ghcr.io/cndoit18/lxcfs-manager:latest" 19 | 20 | build_flag_templates: 21 | - --build-arg=GOLDFLAGS=-X 'github.com/cndoit18/lxcfs-on-kubernetes/version.AppVersion={{ .Version }}' -X 'github.com/cndoit18/lxcfs-on-kubernetes/version.GitCommit={{ .FullCommit }}' 22 | 23 | skip_push: false 24 | 25 | dockerfile: Dockerfile 26 | 27 | extra_files: 28 | - cmd/ 29 | - pkg/ 30 | - version/ 31 | - go.mod 32 | - go.sum 33 | 34 | 35 | changelog: 36 | sort: asc 37 | 38 | filters: 39 | exclude: 40 | - '^docs:' 41 | - typo 42 | - (?i)foo 43 | 44 | 45 | signs: 46 | - artifacts: checksum 47 | 48 | release: 49 | draft: false 50 | prerelease: auto 51 | 52 | extra_files: 53 | - glob: charts/*.tgz -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "line-length": false 4 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright Yinan Li 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM golang:1.21 as builder 15 | 16 | ENV UPX_VERSION 3.96 17 | RUN apt update \ 18 | && apt install -y xz-utils \ 19 | && wget -c https://github.com/upx/upx/releases/download/v$UPX_VERSION/upx-$UPX_VERSION-$(go env GOARCH)_$(uname -s | tr '[:upper:]' '[:lower:]').tar.xz -O - | \ 20 | tar xJf - --strip-components 1 upx-$UPX_VERSION-$(go env GOARCH)_$(uname -s | tr '[:upper:]' '[:lower:]')/upx \ 21 | && mv ./upx /usr/bin/upx 22 | 23 | WORKDIR /workspace 24 | # Copy the Go Modules manifests 25 | COPY go.mod go.mod 26 | COPY go.sum go.sum 27 | # cache deps before building and copying source so that we don't need to re-download as much 28 | # and so that source changes don't invalidate our downloaded layer 29 | RUN go mod download 30 | 31 | COPY . . 32 | 33 | ARG GOLDFLAGS 34 | RUN CGO_ENABLED=0 go build -ldflags="${GOLDFLAGS}" -a -o manager cmd/manager/main.go \ 35 | && upx -9 manager 36 | 37 | # Use distroless as minimal base image to package the manager binary 38 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 39 | FROM gcr.io/distroless/base@sha256:d8244d4756b5dc43f2c198bf4e37e6f8a017f13fdd7f6f64ec7ac7228d3b191e 40 | WORKDIR / 41 | COPY --from=builder /workspace/manager . 42 | 43 | ENTRYPOINT ["/manager"] 44 | -------------------------------------------------------------------------------- /Dockerfile.agent: -------------------------------------------------------------------------------- 1 | # Copyright Yinan Li 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:20.04 as builder 15 | 16 | ENV DEBIAN_FRONTEND noninteractive 17 | RUN apt-get update && apt-get install -y python3 python3-jinja2 python3-setuptools meson wget gcc cmake libfuse2 libfuse-dev uuid-runtime systemd help2man pkg-config 18 | 19 | ENV LXCFS 5.0.2 20 | RUN wget https://linuxcontainers.org/downloads/lxcfs/lxcfs-$LXCFS.tar.gz && \ 21 | mkdir /lxcfs && tar xzvf lxcfs-$LXCFS.tar.gz -C /lxcfs --strip-components=1 && \ 22 | cd /lxcfs && \ 23 | meson setup -Dinit-script=systemd --prefix=/usr build/ && \ 24 | meson compile && \ 25 | meson install -C build 26 | 27 | FROM gcr.io/distroless/base@sha256:d8244d4756b5dc43f2c198bf4e37e6f8a017f13fdd7f6f64ec7ac7228d3b191e 28 | 29 | COPY --from=builder /usr/bin/lxcfs /usr/bin/lxcfs 30 | COPY --from=builder /usr/lib64/lxcfs /usr/lib64/lxcfs 31 | COPY --from=builder /lib/x86_64-linux-gnu/libdl.so.2 /lib/x86_64-linux-gnu/libdl.so.2 32 | COPY --from=builder /lib/x86_64-linux-gnu/libfuse.so.2 /lib/x86_64-linux-gnu/libfuse.so.2 33 | COPY --from=builder /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libgcc_s.so.1 34 | COPY --from=builder /lib/x86_64-linux-gnu/libpthread.so.0 /lib/x86_64-linux-gnu/libpthread.so.0 35 | COPY --from=builder /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6 36 | COPY --from=builder /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 37 | 38 | ENTRYPOINT [ "lxcfs" ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright Yinan Li 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | REGISTRY := ghcr.io/cndoit18 15 | 16 | GIT_COMMIT ?= $(shell git rev-parse HEAD) 17 | APP_VERSION ?= $(shell git describe --abbrev=5 --dirty --tags --always) 18 | IMAGE_TAGS := $(APP_VERSION:v%=%) 19 | IMAGE_NAME := lxcfs-manager 20 | AGENT_IMAGE_NAME := lxcfs-agent 21 | BUILD_TAG := dev 22 | 23 | MANIFESTS_DIR ?= config 24 | RBAC_DIR ?= $(MANIFESTS_DIR)/rbac 25 | BOILERPLATE_FILE ?= ./hack/boilerplate.go.txt 26 | 27 | GEN_CRD_OPTIONS ?= crd:trivialVersions=true 28 | GEN_RBAC_OPTIONS ?= rbac:roleName=manager-role 29 | GEN_WEBHOOK_OPTIONS ?= webhook 30 | GEN_OBJECT_OPTIONS ?= object:headerFile=$(BOILERPLATE_FILE) 31 | GEN_OUTPUTS_OPTIONS ?= output:rbac:artifacts:config=$(RBAC_DIR) 32 | 33 | REPO = $(shell go list -m) 34 | GOLDFLAGS="-X '$(REPO)/version.AppVersion=$(APP_VERSION)' -X '$(REPO)/version.GitCommit=$(GIT_COMMIT)'" 35 | 36 | manifests: controller-gen 37 | $(CONTROLLER_GEN) paths="./..." $(GEN_RBAC_OPTIONS) $(GEN_WEBHOOK_OPTIONS) $(GEN_OBJECT_OPTIONS) $(GEN_OUTPUTS) 38 | 39 | fmt: 40 | go fmt ./... 41 | 42 | vet: 43 | go vet ./... 44 | 45 | lint: 46 | $(GOLANGCI_LINT) run --timeout 2m0s ./... 47 | 48 | # Generate code 49 | generate: manifests helm-generate ## Generate code, charts... 50 | 51 | .PHONY: docker-build 52 | docker-build: ## Build image 53 | docker build . -f Dockerfile --build-arg GOLDFLAGS=${GOLDFLAGS} -t $(REGISTRY)/$(IMAGE_NAME):$(BUILD_TAG) 54 | docker build . -f Dockerfile.agent -t $(REGISTRY)/$(AGENT_IMAGE_NAME):$(BUILD_TAG) 55 | set -e; \ 56 | for tag in $(IMAGE_TAGS); do \ 57 | docker tag $(REGISTRY)/$(IMAGE_NAME):$(BUILD_TAG) $(REGISTRY)/$(IMAGE_NAME):$${tag}; \ 58 | docker tag $(REGISTRY)/$(AGENT_IMAGE_NAME):$(BUILD_TAG) $(REGISTRY)/$(AGENT_IMAGE_NAME):$${tag}; \ 59 | done 60 | 61 | .PHONY: docker-push 62 | docker-push: ## Push image 63 | set -e; \ 64 | for tag in $(IMAGE_TAGS); do \ 65 | docker push $(REGISTRY)/$(IMAGE_NAME):$${tag}; \ 66 | docker push $(REGISTRY)/$(AGENT_IMAGE_NAME):$${tag}; \ 67 | done 68 | 69 | .PHONY: helm-push 70 | helm-push: cr 71 | $(CR) index --config .github/.cr.yaml --push 72 | 73 | BIN ?= $(CURDIR)/.bin 74 | 75 | $(BIN): 76 | mkdir -p "$(BIN)" 77 | 78 | .PHONY: dev-tools 79 | dev-tools: \ 80 | controller-gen \ 81 | golangci-lint \ 82 | kustomize \ 83 | helm-docs \ 84 | cr 85 | 86 | # find or download controller-gen 87 | # download controller-gen if necessary 88 | CONTROLLER_GEN_VERSION := 0.8.0 89 | CONTROLLER_GEN := $(BIN)/controller-gen 90 | 91 | .PHONY: controller-gen 92 | controller-gen: 93 | @$(CONTROLLER_GEN) --version 2>&1 \ 94 | | grep 'v$(CONTROLLER_GEN_VERSION)' \ 95 | || rm -f $(CONTROLLER_GEN) 96 | @$(MAKE) $(CONTROLLER_GEN) 97 | 98 | $(CONTROLLER_GEN): 99 | $(MAKE) $(BIN) 100 | # https://github.com/kubernetes-sigs/controller-tools/tree/master/cmd/controller-gen 101 | go get 'sigs.k8s.io/controller-tools/cmd/controller-gen@v$(CONTROLLER_GEN_VERSION)' 102 | go build -mod=readonly -o $(CONTROLLER_GEN) sigs.k8s.io/controller-tools/cmd/controller-gen 103 | go mod tidy 104 | 105 | # find or download helm-docs 106 | # download helm-docs if necessary 107 | HELM_DOCS_VERSION := 1.4.0 108 | HELM_DOCS := $(BIN)/helm-docs 109 | 110 | .PHONY: helm-docs 111 | helm-docs: 112 | @$(HELM_DOCS) --version 2>&1 \ 113 | | grep '$(HELM_DOCS_VERSION)' > /dev/null \ 114 | || rm -f $(HELM_DOCS) 115 | @$(MAKE) $(HELM_DOCS) 116 | 117 | $(HELM_DOCS): 118 | $(MAKE) $(BIN) 119 | # https://github.com/norwoodj/helm-docs/tree/master#installation 120 | curl -sL "https://github.com/norwoodj/helm-docs/releases/download/v$(HELM_DOCS_VERSION)/helm-docs_$(HELM_DOCS_VERSION)_$$(uname -s)_x86_64.tar.gz" \ 121 | | tar -xzC '$(BIN)' helm-docs 122 | 123 | # find or download golangci-lint 124 | # download golangci-lint if necessary 125 | GOLANGCI_LINT := $(BIN)/golangci-lint 126 | GOLANGCI_LINT_VERSION := 1.33.0 127 | 128 | .PHONY: golangci-lint 129 | golangci-lint: 130 | @$(GOLANGCI_LINT) version --format short 2>&1 \ 131 | | grep '$(GOLANGCI_LINT_VERSION)' > /dev/null \ 132 | || rm -f $(GOLANGCI_LINT) 133 | @$(MAKE) $(GOLANGCI_LINT) 134 | 135 | $(GOLANGCI_LINT): 136 | $(MAKE) $(BIN) 137 | # https://golangci-lint.run/usage/install/#linux-and-windows 138 | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh \ 139 | | sh -s -- -b $(BIN) 'v$(GOLANGCI_LINT_VERSION)' 140 | 141 | # find helm or raise an error 142 | .PHONY: helm 143 | helm: 144 | ifeq (, $(shell which helm 2> /dev/null)) 145 | $(error Helm not found. Please install it: https://helm.sh/docs/intro/install/#from-script) 146 | HELM=helm-not-found 147 | else 148 | HELM=$(shell which helm 2> /dev/null) 149 | endif 150 | 151 | # find or download kustomize 152 | # download kustomize if necessary 153 | KUSTOMIZE_VERSION := 3.8.7 154 | KUSTOMIZE := $(BIN)/kustomize 155 | 156 | .PHONY: kustomize 157 | kustomize: 158 | @$(KUSTOMIZE) version --short 2>&1 \ 159 | | grep 'kustomize/v$(KUSTOMIZE_VERSION)' > /dev/null \ 160 | || rm -f $(KUSTOMIZE) 161 | @$(MAKE) $(KUSTOMIZE) 162 | 163 | $(KUSTOMIZE): 164 | $(MAKE) $(BIN) 165 | # https://kubectl.docs.kubernetes.io/installation/kustomize/binaries/ 166 | curl -sSL "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v$(KUSTOMIZE_VERSION)/kustomize_v$(KUSTOMIZE_VERSION)_$$(go env GOOS)_$$(go env GOARCH).tar.gz" \ 167 | | tar -xzC '$(BIN)' kustomize 168 | 169 | # find or download kustomize 170 | # download kustomize if necessary 171 | CR_VERSION := 1.2.1 172 | CR := $(BIN)/cr 173 | 174 | .PHONY: cr 175 | cr: 176 | @$(CR) version --short 2>&1 \ 177 | | grep 'v$(CR_VERSION)' > /dev/null \ 178 | || rm -f $(CR) 179 | @$(MAKE) $(CR) 180 | 181 | $(CR): 182 | $(MAKE) $(BIN) 183 | curl -sSL "https://github.com/helm/chart-releaser/releases/download/v$(CR_VERSION)/chart-releaser_$(CR_VERSION)_$$(go env GOOS)_$$(go env GOARCH).tar.gz" \ 184 | | tar -xzC '$(BIN)' cr 185 | 186 | #################### 187 | # Helm chart # 188 | #################### 189 | 190 | RELEASE_VERSION ?= $(APP_VERSION:v%=%) 191 | CHARTS_DIRECTORY := charts 192 | CHART_PROJECT_PATH := $(CHARTS_DIRECTORY)/lxcfs-on-kubernetes 193 | CHART_TEMPLATE_PATH := $(CHART_PROJECT_PATH)/templates 194 | DO_NOT_EDIT := Code generated by make. DO NOT EDIT. 195 | 196 | $(CHART_TEMPLATE_PATH)/certificate.yaml: kustomize $(wildcard config/helm/certmanager/*) $(wildcard config/certmanager/*) 197 | echo '{{- /* $(DO_NOT_EDIT) */ -}}' > $(CHART_TEMPLATE_PATH)/certificate.yaml 198 | $(KUSTOMIZE) build --reorder legacy config/helm/certificate | \ 199 | $(KUSTOMIZE) cfg grep --annotate=false 'kind=Certificate' | \ 200 | sed "s/'\({{[^}}]*}}\)'/\1/g" \ 201 | >> $(CHART_TEMPLATE_PATH)/certificate.yaml 202 | 203 | $(CHART_TEMPLATE_PATH)/issuer.yaml: kustomize $(wildcard config/helm/certmanager/*) $(wildcard config/certmanager/*) 204 | echo '{{- /* $(DO_NOT_EDIT) */ -}}' > $(CHART_TEMPLATE_PATH)/issuer.yaml 205 | $(KUSTOMIZE) build --reorder legacy config/helm/certificate | \ 206 | $(KUSTOMIZE) cfg grep --annotate=false 'kind=Issuer' | \ 207 | sed "s/'\({{[^}}]*}}\)'/\1/g" \ 208 | >> $(CHART_TEMPLATE_PATH)/issuer.yaml 209 | 210 | $(CHART_TEMPLATE_PATH)/clusterrole.yaml: kustomize $(wildcard config/helm/rbac/*) $(wildcard config/rbac/*) 211 | echo '{{- /* $(DO_NOT_EDIT) */ -}}' > $(CHART_TEMPLATE_PATH)/clusterrole.yaml 212 | $(KUSTOMIZE) build --reorder legacy config/helm/rbac | \ 213 | $(KUSTOMIZE) cfg grep --annotate=false "kind=ClusterRole" | \ 214 | $(KUSTOMIZE) cfg grep --annotate=false --invert-match 'kind=ClusterRoleBinding' | \ 215 | sed "s/'\({{[^}}]*}}\)'/\1/g" \ 216 | >> $(CHART_TEMPLATE_PATH)/clusterrole.yaml 217 | 218 | $(CHART_TEMPLATE_PATH)/clusterrolebinding.yaml: kustomize $(wildcard config/helm/rbac/*) $(wildcard config/rbac/*) 219 | echo '{{- /* $(DO_NOT_EDIT) */ -}}' > $(CHART_TEMPLATE_PATH)/clusterrolebinding.yaml 220 | $(KUSTOMIZE) build --reorder legacy config/helm/rbac | \ 221 | $(KUSTOMIZE) cfg grep --annotate=false "kind=ClusterRoleBinding" | \ 222 | sed "s/'\({{[^}}]*}}\)'/\1/g" \ 223 | >> $(CHART_TEMPLATE_PATH)/clusterrolebinding.yaml 224 | 225 | $(CHART_TEMPLATE_PATH)/mutatingwebhookconfiguration.yaml: kustomize $(wildcard config/helm/webhook/*) $(wildcard config/webhook/*) 226 | echo '{{- /* $(DO_NOT_EDIT) */ -}}' > $(CHART_TEMPLATE_PATH)/mutatingwebhookconfiguration.yaml 227 | $(KUSTOMIZE) build --reorder legacy config/helm/webhook | \ 228 | $(KUSTOMIZE) cfg grep --annotate=false "kind=MutatingWebhookConfiguration" | \ 229 | sed "s/'\({{[^}}]*}}\)'/\1/g" \ 230 | >> $(CHART_TEMPLATE_PATH)/mutatingwebhookconfiguration.yaml 231 | 232 | $(CHART_TEMPLATE_PATH)/deployment.yaml: kustomize kustomize $(wildcard config/helm/manager/*) $(wildcard config/manager/*) 233 | echo '{{- /* $(DO_NOT_EDIT) */ -}}' > $(CHART_TEMPLATE_PATH)/deployment.yaml 234 | $(KUSTOMIZE) build --reorder legacy config/helm/manager | \ 235 | $(KUSTOMIZE) cfg grep --annotate=false "kind=Deployment" | \ 236 | sed "s/'\({{[^}}]*}}\)'/\1/g" | \ 237 | sed "s/affinity: {}/affinity: {{ if .Values.affinity }}{{ toYaml .Values.affinity | nindent 8 }}{{ else }}{}{{ end }}/g" \ 238 | >> $(CHART_TEMPLATE_PATH)/deployment.yaml 239 | 240 | $(CHART_TEMPLATE_PATH)/daemonset.yaml: kustomize kustomize $(wildcard config/helm/manager/*) $(wildcard config/manager/*) 241 | echo '{{- /* $(DO_NOT_EDIT) */ -}}' > $(CHART_TEMPLATE_PATH)/daemonset.yaml 242 | echo '{{- if .Values.lxcfs.useDaemonset -}}' >> $(CHART_TEMPLATE_PATH)/daemonset.yaml 243 | $(KUSTOMIZE) build --reorder legacy config/helm/manager | \ 244 | $(KUSTOMIZE) cfg grep --annotate=false "kind=DaemonSet" | \ 245 | sed "s/'\({{[^}}]*}}\)'/\1/g" \ 246 | >> $(CHART_TEMPLATE_PATH)/daemonset.yaml 247 | echo '{{- end -}}' >> $(CHART_TEMPLATE_PATH)/daemonset.yaml 248 | 249 | $(CHART_PROJECT_PATH)/README.md: helm-docs $(CHART_PROJECT_PATH)/values.yaml $(CHART_PROJECT_PATH)/Chart.yaml 250 | $(HELM_DOCS) $(CHART_PROJECT_PATH) 251 | 252 | define UPDATE_CHART_YAML 253 | s#version: .*#version: $(RELEASE_VERSION)# 254 | s#appVersion: .*#appVersion: $(RELEASE_VERSION)# 255 | endef 256 | 257 | define UPDATE_VALUES_YAML 258 | s#lxcfs-manager:.*#lxcfs-manager:v$(IMAGE_TAGS)# 259 | s#lxcfs-agent:.*#lxcfs-agent:v$(IMAGE_TAGS)# 260 | endef 261 | 262 | export UPDATE_CHART_YAML 263 | export UPDATE_VALUES_YAML 264 | $(CHARTS_DIRECTORY)/lxcfs-on-kubernetes-$(RELEASE_VERSION).tgz: helm $(CHART_TEMPLATE_PATH)/clusterrole.yaml \ 265 | $(CHART_TEMPLATE_PATH)/certificate.yaml $(CHART_TEMPLATE_PATH)/issuer.yaml \ 266 | $(CHART_TEMPLATE_PATH)/mutatingwebhookconfiguration.yaml \ 267 | $(CHART_TEMPLATE_PATH)/deployment.yaml \ 268 | $(CHART_TEMPLATE_PATH)/daemonset.yaml \ 269 | $(CHART_TEMPLATE_PATH)/clusterrolebinding.yaml 270 | 271 | sed -i.bak -E "$$UPDATE_CHART_YAML" ${CHART_PROJECT_PATH}/Chart.yaml 272 | sed -i.bak -E "$$UPDATE_VALUES_YAML" ${CHART_PROJECT_PATH}/values.yaml 273 | $(MAKE) $(CHART_PROJECT_PATH)/README.md 274 | $(HELM) package $(CHART_PROJECT_PATH) \ 275 | --version $(RELEASE_VERSION) \ 276 | --app-version $(RELEASE_VERSION) \ 277 | --destination $(CHARTS_DIRECTORY) 278 | -mv ${CHART_PROJECT_PATH}/values.yaml.bak ${CHART_PROJECT_PATH}/values.yaml 279 | -mv ${CHART_PROJECT_PATH}/Chart.yaml.bak ${CHART_PROJECT_PATH}/Chart.yaml 280 | .PHONY: helm-generate 281 | helm-generate: $(CHARTS_DIRECTORY)/lxcfs-on-kubernetes-$(RELEASE_VERSION).tgz 282 | 283 | .DEFAULT_GOAL := help 284 | .PHONY: help 285 | help: ## Show this help screen. 286 | @echo 'Usage: make ... ' 287 | @echo '' 288 | @echo 'Available targets are:' 289 | @echo '' 290 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-25s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lxcfs-on-kubernetes 2 | 3 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 4 | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/lxcfs-on-kubernetes)](https://artifacthub.io/packages/search?repo=lxcfs-on-kubernetes) 5 | [![CodeQL](https://github.com/cndoit18/lxcfs-on-kubernetes/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/cndoit18/lxcfs-on-kubernetes/actions/workflows/codeql-analysis.yml) 6 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcndoit18%2Flxcfs-on-kubernetes.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcndoit18%2Flxcfs-on-kubernetes?ref=badge_shield) 7 | 8 | 9 | This project will automatically deploy [LXCFS](https://github.com/lxc/lxcfs) while mounted to the container 10 | 11 | ## Introduction 12 | 13 | [LXCFS](https://github.com/lxc/lxcfs) is a small FUSE filesystem written with the intention of making Linux 14 | containers feel more like a virtual machine. It started as a side-project of 15 | `LXC` but is useable by any runtime. 16 | 17 | [LXCFS](https://github.com/lxc/lxcfs) will take care that the information provided by crucial files in `procfs` 18 | such as: 19 | 20 | ``` 21 | /proc/cpuinfo 22 | /proc/diskstats 23 | /proc/meminfo 24 | /proc/stat 25 | /proc/swaps 26 | 27 | /proc/uptime 28 | /proc/slabinfo 29 | /sys/devices/system/cpu 30 | /sys/devices/system/cpu/online 31 | ``` 32 | 33 | are container aware such that the values displayed (e.g. in `/proc/uptime`) 34 | really reflect how long the container is running and not how long the host is 35 | running. 36 | 37 | ## Prerequisites 38 | 39 | 1. `Kubernetes` cluster (v1.19+) is running. For local development purpose, check [Kind installation](https://kind.sigs.k8s.io/docs/user/quick-start/#installation). 40 | 1. `cert-manager` (v1.2+) is [installed](https://cert-manager.io/docs/installation/kubernetes/). 41 | 1. `helm` v3 is [installed](https://helm.sh/docs/intro/install/). 42 | 43 | ## Deploy 44 | 45 | Run the helm command to install the lxcfs-on-kubernetes to your cluster: 46 | 47 | ``` 48 | helm repo add lxcfs-on-kubernetes https://cndoit18.github.io/lxcfs-on-kubernetes/ 49 | ``` 50 | 51 | you can then do 52 | 53 | ``` 54 | helm upgrade --install lxcfs lxcfs-on-kubernetes/lxcfs-on-kubernetes -n lxcfs --create-namespace 55 | ``` 56 | 57 | For what settings you can override with `--set`, `--set-string`, `--set-file` or `--values`, you can refer to the [values.yaml](charts/lxcfs-on-kubernetes/README.md) file. 58 | 59 | you can enable the namespace for injection. 60 | 61 | ``` 62 | kubectl label namespace default mount-lxcfs=enabled 63 | ``` 64 | 65 | > You can change it by setting [matchLabels](charts/lxcfs-on-kubernetes/README.md) during installation 66 | 67 | 68 | ## License 69 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcndoit18%2Flxcfs-on-kubernetes.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcndoit18%2Flxcfs-on-kubernetes?ref=badge_large) 70 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *.tgz 19 | *~ 20 | # Various IDEs 21 | .project 22 | .idea/ 23 | *.tmproj 24 | .vscode/ -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: lxcfs-on-kubernetes 3 | description: |- 4 | `LXCFS` is a small FUSE filesystem written with the intention of making Linux containers feel more like a virtual machine. 5 | 6 | keywords: 7 | - lxcfs 8 | type: application 9 | 10 | sources: 11 | - https://github.com/cndoit18/lxcfs-on-kubernetes 12 | - https://github.com/lxc/lxcfs 13 | 14 | maintainers: 15 | - name: cndoit18 16 | email: cndoit18@outlook.com 17 | url: https://github.com/cndoit18 18 | 19 | # This is the chart version. This version number should be incremented each time you make changes 20 | # to the chart and its templates, including the app version. 21 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 22 | version: 0.1.0 23 | 24 | kubeVersion: '>= 1.16.0-0' 25 | 26 | # This is the version number of the application being deployed. This version number should be 27 | # incremented each time you make changes to the application. Versions are not expected to 28 | # follow Semantic Versioning. They should reflect the version the application is using. 29 | appVersion: 0.1.0 -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/README.md: -------------------------------------------------------------------------------- 1 | # lxcfs-on-kubernetes 2 | 3 | ![Version: 0.1.4](https://img.shields.io/badge/Version-0.1.4-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.4](https://img.shields.io/badge/AppVersion-0.1.4-informational?style=flat-square) 4 | 5 | `LXCFS` is a small FUSE filesystem written with the intention of making Linux containers feel more like a virtual machine. 6 | 7 | ## Maintainers 8 | 9 | | Name | Email | Url | 10 | | ---- | ------ | --- | 11 | | cndoit18 | cndoit18@outlook.com | https://github.com/cndoit18 | 12 | 13 | ## Source Code 14 | 15 | * 16 | * 17 | 18 | ## Requirements 19 | 20 | Kubernetes: `>= 1.16.0-0` 21 | 22 | ## Values 23 | 24 | | Key | Type | Default | Description | 25 | |-----|------|---------|-------------| 26 | | affinity | object | `{}` | Affinity to add to the controller Pods | 27 | | image.agent | string | `"ghcr.io/cndoit18/lxcfs-agent:v0.1.4"` | lxcfs-on-kubernetes agent image | 28 | | image.manager | string | `"ghcr.io/cndoit18/lxcfs-manager:v0.1.4"` | lxcfs-on-kubernetes controller image | 29 | | imagePullSecrets | list | `[]` | Reference to one or more secrets to be used when pulling images For example: `[ {"name":"image-pull-secret"} ]` | 30 | | leaderElection.enable | bool | `false` | Whether to enabled leaderElection | 31 | | leaderElection.id | string | `"lxcfs-on-kubernetes-leader-election"` | The id used to store the ConfigMap for leader election | 32 | | leaderElection.namespace | string | `"kube-system"` | The namespace used to store the ConfigMap for leader election | 33 | | logLevel | int | `4` | Set the verbosity of controller. Range of 0 - 6 with 6 being the most verbose. Info level is 4. | 34 | | lxcfs.args | list | `["-l","--enable-cfs","--enable-pidfd"]` | Adjusting the boot parameters of lxcfs | 35 | | lxcfs.matchLabels | object | `{"mount-lxcfs":"enabled"}` | For namespaces that match the labes, the Pods under it will mount lxcfs. | 36 | | lxcfs.mountPath | string | `"/var/lib/lxcfs"` | Specify the mount path of lxcfs on the host | 37 | | lxcfs.podAnnotations | object | `{}` | Additional annotations to add to the agent Pods | 38 | | lxcfs.resources | object | `{"limits":{"cpu":"500m","memory":"300Mi"},"requests":{"cpu":"300m","memory":"200M"}}` | Expects input structure as per specification | 39 | | lxcfs.useDaemonset | bool | `true` | Installing lxcfs with daemonset | 40 | | podAnnotations | object | `{}` | Additional annotations to add to the controller Pods | 41 | | pullPolicy | string | `"IfNotPresent"` | The image pull policy. | 42 | | replicas | int | `1` | Number of replicas for the controller | 43 | | resources | object | `{"limits":{"cpu":"500m","memory":"300Mi"},"requests":{"cpu":"300m","memory":"200Mi"}}` | Expects input structure as per specification | 44 | | service.port | int | `443` | Expose port for WebHook controller | 45 | | service.type | string | `"ClusterIP"` | Service type to use | 46 | 47 | ---------------------------------------------- 48 | Autogenerated from chart metadata using [helm-docs v1.4.0](https://github.com/norwoodj/helm-docs/releases/v1.4.0) 49 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "chart.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 7 | {{- end }} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "chart.fullname" -}} 15 | {{- if .Values.fullnameOverride }} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 17 | {{- else }} 18 | {{- $name := default .Chart.Name .Values.nameOverride }} 19 | {{- if contains $name .Release.Name }} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 21 | {{- else }} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 23 | {{- end }} 24 | {{- end }} 25 | {{- end }} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "chart.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 32 | {{- end }} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "chart.labels" -}} 38 | helm.sh/chart: {{ include "chart.chart" . }} 39 | {{ include "chart.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end }} 45 | 46 | {{/* 47 | lxcfs labels 48 | */}} 49 | {{- define "chart.lxcfs.labels" -}} 50 | helm.sh/chart: {{ include "chart.chart" . }} 51 | {{ include "chart.lxcfs.selectorLabels" . }} 52 | {{- if .Chart.AppVersion }} 53 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 54 | {{- end }} 55 | app.kubernetes.io/managed-by: {{ .Release.Service }} 56 | {{- end }} 57 | 58 | {{/* 59 | lxcfs args 60 | */}} 61 | {{- define "chart.lxcfs.args" -}} 62 | {{- if .Values.lxcfs.args }} 63 | {{- toYaml .Values.lxcfs.args }} 64 | {{- end }} 65 | - {{.Values.lxcfs.mountPath}} 66 | {{- end }} 67 | 68 | {{/* 69 | Selector labels 70 | */}} 71 | {{- define "chart.selectorLabels" -}} 72 | app.kubernetes.io/name: {{ include "chart.name" . }} 73 | app.kubernetes.io/instance: {{ .Release.Name }} 74 | app.kubernetes.io/compose: manager 75 | {{- end }} 76 | 77 | {{/* 78 | Selector labels 79 | */}} 80 | {{- define "chart.lxcfs.selectorLabels" -}} 81 | app.kubernetes.io/name: {{ include "chart.name" . }} 82 | app.kubernetes.io/instance: {{ .Release.Name }} 83 | app.kubernetes.io/compose: lxcfs 84 | {{- end }} 85 | 86 | {{/* 87 | Create the name of the service account to use 88 | */}} 89 | {{- define "chart.serviceAccountName" -}} 90 | {{- if .Values.serviceAccount.create }} 91 | {{- default (include "chart.fullname" .) .Values.serviceAccount.name }} 92 | {{- else }} 93 | {{- default "default" .Values.serviceAccount.name }} 94 | {{- end }} 95 | {{- end }} 96 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/certificate.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | apiVersion: cert-manager.io/v1 3 | kind: Certificate 4 | metadata: 5 | name: '{{ include "chart.fullname" . }}-serving-cert' 6 | namespace: {{ .Release.Namespace | quote }} 7 | spec: 8 | dnsNames: 9 | - '{{ include "chart.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc' 10 | - '{{ include "chart.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc.cluster.local' 11 | issuerRef: 12 | kind: Issuer 13 | name: '{{ include "chart.fullname" . }}-selfsigned-issuer' 14 | secretName: '{{ include "chart.fullname" . }}-certificate' 15 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: '{{ include "chart.fullname" . }}-manager-role' 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - configmaps 12 | - events 13 | verbs: 14 | - '*' 15 | - apiGroups: 16 | - coordination.k8s.io 17 | resources: 18 | - leases 19 | verbs: 20 | - '*' 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - pods 25 | verbs: 26 | - '*' 27 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: '{{ include "chart.fullname" . }}-manager-rolebinding' 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: '{{ include "chart.fullname" . }}-manager-role' 10 | subjects: 11 | - kind: ServiceAccount 12 | name: default 13 | namespace: {{ .Release.Namespace | quote }} 14 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/daemonset.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | {{- if .Values.lxcfs.useDaemonset -}} 3 | apiVersion: apps/v1 4 | kind: DaemonSet 5 | metadata: 6 | labels: {{- include "chart.lxcfs.labels" . | nindent 4 }} 7 | name: '{{ include "chart.fullname" . }}-controller-manager-daemonset' 8 | namespace: {{ .Release.Namespace | quote }} 9 | spec: 10 | selector: 11 | matchLabels: {{- include "chart.lxcfs.selectorLabels" . | nindent 6 }} 12 | template: 13 | metadata: 14 | annotations: {{- toYaml .Values.lxcfs.podAnnotations | nindent 8 }} 15 | labels: {{- include "chart.lxcfs.selectorLabels" . | nindent 8 }} 16 | spec: 17 | containers: 18 | - args: {{- include "chart.lxcfs.args" . | nindent 8 }} 19 | image: {{.Values.image.agent}} 20 | imagePullPolicy: {{ .Values.pullPolicy | quote }} 21 | name: agent 22 | resources: {{- toYaml .Values.lxcfs.resources | nindent 10 }} 23 | securityContext: 24 | privileged: true 25 | volumeMounts: 26 | - mountPath: {{.Values.lxcfs.mountPath}} 27 | mountPropagation: Bidirectional 28 | name: lxcfs 29 | - mountPath: /sys/fs/cgroup 30 | name: cgroup 31 | hostPID: true 32 | volumes: 33 | - hostPath: 34 | path: {{.Values.lxcfs.mountPath}} 35 | type: DirectoryOrCreate 36 | name: lxcfs 37 | - hostPath: 38 | path: /sys/fs/cgroup 39 | name: cgroup 40 | {{- end -}} 41 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | labels: {{- include "chart.labels" . | nindent 4 }} 6 | name: '{{ include "chart.fullname" . }}-controller-manager' 7 | namespace: {{ .Release.Namespace | quote }} 8 | spec: 9 | replicas: {{ .Values.replicas }} 10 | selector: 11 | matchLabels: {{- include "chart.selectorLabels" . | nindent 6 }} 12 | template: 13 | metadata: 14 | annotations: {{- toYaml .Values.podAnnotations | nindent 8 }} 15 | labels: {{- include "chart.selectorLabels" . | nindent 8 }} 16 | spec: 17 | affinity: {{ if .Values.affinity }}{{ toYaml .Values.affinity | nindent 8 }}{{ else }}{}{{ end }} 18 | containers: 19 | - args: 20 | - --lxcfs-path={{.Values.lxcfs.mountPath}} 21 | - --v={{.Values.logLevel}} 22 | - --leader-election={{.Values.leaderElection.enable}} 23 | - --leader-election-namespace={{.Values.leaderElection.namespace}} 24 | - --leader-election-id={{.Values.leaderElection.id}} 25 | image: {{.Values.image.manager}} 26 | imagePullPolicy: {{ .Values.pullPolicy | quote }} 27 | name: manager 28 | ports: 29 | - containerPort: 9443 30 | name: webhook-server 31 | protocol: TCP 32 | resources: {{- toYaml .Values.resources | nindent 10 }} 33 | volumeMounts: 34 | - mountPath: /tmp/k8s-webhook-server/serving-certs 35 | name: cert 36 | readOnly: true 37 | terminationGracePeriodSeconds: 10 38 | volumes: 39 | - name: cert 40 | secret: 41 | defaultMode: 420 42 | secretName: '{{ include "chart.fullname" . }}-certificate' 43 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/issuer.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | apiVersion: cert-manager.io/v1 3 | kind: Issuer 4 | metadata: 5 | name: '{{ include "chart.fullname" . }}-selfsigned-issuer' 6 | namespace: {{ .Release.Namespace | quote }} 7 | spec: 8 | selfSigned: {} 9 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/mutatingwebhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: '{{.Release.Namespace}}/{{. | include "chart.fullname"}}-serving-cert' 7 | name: '{{ include "chart.fullname" . }}-mutating-webhook-configuration' 8 | webhooks: 9 | - admissionReviewVersions: 10 | - v1 11 | clientConfig: 12 | service: 13 | name: '{{ include "chart.fullname" . }}-webhook-service' 14 | namespace: {{ .Release.Namespace | quote }} 15 | path: /mount-lxcfs 16 | failurePolicy: Ignore 17 | name: club.cndoit18.lxcfs-on-kubernetes 18 | namespaceSelector: 19 | matchLabels: {{- toYaml .Values.lxcfs.matchLabels | nindent 6 }} 20 | rules: 21 | - apiGroups: 22 | - "" 23 | apiVersions: 24 | - v1 25 | operations: 26 | - CREATE 27 | resources: 28 | - pods 29 | sideEffects: NoneOnDryRun 30 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: '{{ include "chart.fullname" . }}-webhook-service' 5 | namespace: {{ .Release.Namespace | quote }} 6 | labels: {{- include "chart.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: 443 11 | targetPort: 9443 12 | protocol: TCP 13 | name: https 14 | selector: 15 | {{- include "chart.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /charts/lxcfs-on-kubernetes/values.yaml: -------------------------------------------------------------------------------- 1 | # replicas -- Number of replicas for the controller 2 | replicas: 1 3 | 4 | image: 5 | # image.manager -- lxcfs-on-kubernetes controller image 6 | manager: ghcr.io/cndoit18/lxcfs-manager:latest 7 | # image.agent -- lxcfs-on-kubernetes agent image 8 | agent: ghcr.io/cndoit18/lxcfs-agent:latest 9 | 10 | # 11 | service: 12 | # service.type -- Service type to use 13 | type: ClusterIP 14 | # service.port -- Expose port for WebHook controller 15 | port: 443 16 | 17 | # logLevel -- Set the verbosity of controller. Range of 0 - 6 with 6 being the most verbose. 18 | # Info level is 4. 19 | logLevel: 4 20 | 21 | leaderElection: 22 | # leaderElection.enable -- Whether to enabled leaderElection 23 | enable: false 24 | # leaderElection.namespace -- The namespace used to store the ConfigMap for leader election 25 | namespace: kube-system 26 | # leaderElection.id -- The id used to store the ConfigMap for leader election 27 | id: lxcfs-on-kubernetes-leader-election 28 | 29 | # imagePullSecrets -- Reference to one or more secrets to be used when pulling images 30 | # 31 | # For example: 32 | # `[ 33 | # {"name":"image-pull-secret"} 34 | # ]` 35 | imagePullSecrets: [] 36 | 37 | # pullPolicy -- The image pull policy. 38 | pullPolicy: IfNotPresent 39 | 40 | # resources -- Expects input structure as per specification 41 | resources: 42 | limits: 43 | cpu: 500m 44 | memory: 300Mi 45 | requests: 46 | cpu: 300m 47 | memory: 200Mi 48 | 49 | # affinity -- Affinity to add to the controller Pods 50 | affinity: {} 51 | #affinity: 52 | # nodeAffinity: 53 | # requiredDuringSchedulingIgnoredDuringExecution: 54 | # nodeSelectorTerms: 55 | # - matchExpressions: 56 | # - key: node-role.kubernetes.io/control-plane 57 | # operator: Exists 58 | # podAntiAffinity: 59 | # preferredDuringSchedulingIgnoredDuringExecution: 60 | # - podAffinityTerm: 61 | # labelSelector: 62 | # matchLabels: 63 | # app.kubernetes.io/instance: your-release-name 64 | # app.kubernetes.io/compose: manager 65 | # topologyKey: kubernetes.io/hostname 66 | # weight: 100 67 | 68 | # podAnnotations -- Additional annotations to add to the controller Pods 69 | podAnnotations: {} 70 | 71 | lxcfs: 72 | # lxcfs.useDaemonset -- Installing lxcfs with daemonset 73 | useDaemonset: true 74 | # lxcfs.mountPath -- Specify the mount path of lxcfs on the host 75 | mountPath: /var/lib/lxcfs 76 | # lxcfs.resources -- Expects input structure as per specification 77 | resources: 78 | limits: 79 | cpu: 500m 80 | memory: 300Mi 81 | requests: 82 | cpu: 300m 83 | memory: 200M 84 | # lxcfs.matchLabels -- For namespaces that match the labes, the Pods under it will mount lxcfs. 85 | matchLabels: 86 | mount-lxcfs: enabled 87 | # lxcfs.podAnnotations -- Additional annotations to add to the agent Pods 88 | podAnnotations: {} 89 | 90 | # lxcfs.args -- Adjusting the boot parameters of lxcfs 91 | args: 92 | - -l 93 | - --enable-cfs 94 | - --enable-pidfd -------------------------------------------------------------------------------- /cmd/manager/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Yinan Li 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "os" 22 | 23 | "github.com/spf13/pflag" 24 | 25 | "github.com/cndoit18/lxcfs-on-kubernetes/pkg/admission" 26 | "github.com/cndoit18/lxcfs-on-kubernetes/version" 27 | klog "k8s.io/klog/v2" 28 | klogr "k8s.io/klog/v2/klogr" 29 | "sigs.k8s.io/controller-runtime/pkg/client/config" 30 | "sigs.k8s.io/controller-runtime/pkg/healthz" 31 | logr "sigs.k8s.io/controller-runtime/pkg/log" 32 | "sigs.k8s.io/controller-runtime/pkg/manager" 33 | "sigs.k8s.io/controller-runtime/pkg/manager/signals" 34 | ) 35 | 36 | var log = logr.Log.WithName("main") 37 | 38 | func init() { 39 | logr.SetLogger(klogr.New()) 40 | } 41 | 42 | // Automatically generate RBAC rules to allow the Controller to read and write Deployments 43 | // +kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=* 44 | // +kubebuilder:rbac:groups="",resources=configmaps;events,verbs=* 45 | 46 | func main() { 47 | var ( 48 | leaderElection = flag.Bool("leader-election", false, "LeaderElection determines whether or not to use leader election when starting the manager.") 49 | leaderElectionNamespace = flag.String("leader-election-namespace", "default", "The leader election namespace.") 50 | leaderElectionID = flag.String("leader-election-id", "lxcfs-on-kubernetes-leader-election", "The leader election id.") 51 | lxcfsPath = flag.String("lxcfs-path", "/var/lib/lxcfs", "Path for lxcfs mounts.") 52 | ) 53 | 54 | // set logging 55 | fs := pflag.NewFlagSet(os.Args[0], pflag.ExitOnError) 56 | fs.AddGoFlagSet(flag.CommandLine) 57 | 58 | klogFlags := flag.NewFlagSet("klog", flag.ExitOnError) 59 | klog.InitFlags(klogFlags) 60 | fs.AddGoFlagSet(klogFlags) 61 | 62 | if err := fs.Parse(os.Args); err != nil { 63 | log.Error(err, "Failed to parse command line args") 64 | os.Exit(1) 65 | } 66 | 67 | log.Info("manager Starting", "Version", version.Version()) 68 | 69 | // Get a config to talk to the apiserver 70 | cfg, err := config.GetConfig() 71 | if err != nil { 72 | log.Error(err, "Failed to get configuration.") 73 | os.Exit(1) 74 | } 75 | 76 | // Create a new Cmd to provide shared dependencies and start components 77 | mgr, err := manager.New(cfg, manager.Options{ 78 | LeaderElection: *leaderElection, 79 | LeaderElectionNamespace: *leaderElectionNamespace, 80 | LeaderElectionID: *leaderElectionID, 81 | HealthProbeBindAddress: ":8081", 82 | }) 83 | if err != nil { 84 | log.Error(err, "Failed to create manager.") 85 | os.Exit(1) 86 | } 87 | 88 | if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { 89 | log.Error(err, "Failed to add healthzCheck to manager") 90 | os.Exit(1) 91 | } 92 | 93 | if err := admission.AddToManager(mgr, 94 | admission.WithMutatePath(*lxcfsPath), 95 | ); err != nil { 96 | log.Error(err, "Failed to add admission to manager") 97 | os.Exit(1) 98 | } 99 | 100 | // Start the Cmd 101 | if err := mgr.Start(signals.SetupSignalHandler()); err != nil { 102 | log.Error(err, "unable to start the manager") 103 | os.Exit(1) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /config/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | # More document can be found at https://docs.cert-manager.io 2 | apiVersion: cert-manager.io/v1 3 | kind: Issuer 4 | metadata: 5 | name: selfsigned-issuer 6 | spec: 7 | selfSigned: {} 8 | --- 9 | apiVersion: cert-manager.io/v1 10 | kind: Certificate 11 | metadata: 12 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 13 | spec: 14 | # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize 15 | dnsNames: 16 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc 17 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local 18 | issuerRef: 19 | kind: Issuer 20 | name: selfsigned-issuer 21 | secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize 22 | -------------------------------------------------------------------------------- /config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /config/default/daemonset_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: controller-manager-daemonset 5 | namespace: system 6 | spec: 7 | selector: 8 | matchLabels: 9 | app.kubernetes.io/component: lxcfs-agen 10 | template: 11 | spec: 12 | containers: 13 | - name: agent 14 | args: 15 | - "/var/lib/lxcfs" 16 | volumeMounts: 17 | - name: lxcfs 18 | mountPath: /var/lib/lxcfs 19 | mountPropagation: Bidirectional 20 | volumes: 21 | - name: lxcfs 22 | hostPath: 23 | path: /var/lib/lxcfs 24 | type: DirectoryOrCreate 25 | -------------------------------------------------------------------------------- /config/default/deployment_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | selector: 8 | matchLabels: 9 | app.kubernetes.io/component: lxcfs 10 | template: 11 | spec: 12 | containers: 13 | - name: manager 14 | args: 15 | - --lxcfs-path=/var/lib/lxcfs 16 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: lxcfs-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: lxcfs- 10 | 11 | bases: 12 | - ../rbac 13 | - ../manager 14 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 15 | # crd/kustomization.yaml 16 | - ../webhook 17 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 18 | - ../certmanager 19 | 20 | patchesStrategicMerge: 21 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 22 | # crd/kustomization.yaml 23 | - manager_webhook_patch.yaml 24 | 25 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 26 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 27 | # 'CERTMANAGER' needs to be enabled to use ca injection 28 | - webhookcainjection_patch.yaml 29 | 30 | # the following config is for teaching kustomize how to do var substitution 31 | vars: 32 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 33 | - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 34 | objref: 35 | kind: Certificate 36 | group: cert-manager.io 37 | version: v1 38 | name: serving-cert # this name should match the one in certificate.yaml 39 | fieldref: 40 | fieldpath: metadata.namespace 41 | - name: CERTIFICATE_NAME 42 | objref: 43 | kind: Certificate 44 | group: cert-manager.io 45 | version: v1 46 | name: serving-cert # this name should match the one in certificate.yaml 47 | - name: SERVICE_NAMESPACE # namespace of the service 48 | objref: 49 | kind: Service 50 | version: v1 51 | name: webhook-service 52 | fieldref: 53 | fieldpath: metadata.namespace 54 | - name: SERVICE_NAME 55 | objref: 56 | kind: Service 57 | version: v1 58 | name: webhook-service 59 | 60 | patches: 61 | - daemonset_patch.yaml 62 | - deployment_patch.yaml 63 | -------------------------------------------------------------------------------- /config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | selector: 8 | matchLabels: 9 | app.kubernetes.io/component: lxcfs 10 | template: 11 | spec: 12 | containers: 13 | - name: manager 14 | ports: 15 | - containerPort: 9443 16 | name: webhook-server 17 | protocol: TCP 18 | volumeMounts: 19 | - mountPath: /tmp/k8s-webhook-server/serving-certs 20 | name: cert 21 | readOnly: true 22 | volumes: 23 | - name: cert 24 | secret: 25 | defaultMode: 420 26 | secretName: webhook-server-cert 27 | -------------------------------------------------------------------------------- /config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | # apiVersion: admissionregistration.k8s.io/v1 11 | # kind: ValidatingWebhookConfiguration 12 | # metadata: 13 | # name: validating-webhook-configuration 14 | # annotations: 15 | # cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /config/helm/certificate/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: "{{ .Release.Namespace | quote }}" 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | patchesStrategicMerge: 9 | - patch_certificate_dns.yaml 10 | - patch_certificate_secret.yaml 11 | 12 | bases: 13 | - ../../certmanager 14 | -------------------------------------------------------------------------------- /config/helm/certificate/patch_certificate_dns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Certificate 3 | metadata: 4 | name: serving-cert 5 | spec: 6 | dnsNames: 7 | - '{{ include "chart.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc' 8 | - '{{ include "chart.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc.cluster.local' 9 | -------------------------------------------------------------------------------- /config/helm/certificate/patch_certificate_secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Certificate 3 | metadata: 4 | name: serving-cert 5 | spec: 6 | secretName: '{{ include "chart.fullname" . }}-certificate' 7 | -------------------------------------------------------------------------------- /config/helm/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: "{{ .Release.Namespace | quote }}" 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | images: 9 | - name: ghcr.io/cndoit18/lxcfs-manager 10 | newName: "{{.Values.image.manager}}" 11 | - name: ghcr.io/cndoit18/lxcfs-agent 12 | newName: "{{.Values.image.agent}}" 13 | 14 | patches: 15 | - patch_deployment_config.yaml 16 | - patch_deployment_webhook.yaml 17 | - patch_daemonset_config.yaml 18 | 19 | patchesJson6902: 20 | - target: 21 | version: v1 22 | group: apps 23 | kind: Deployment 24 | name: controller-manager 25 | path: patch_deployment_metadata.yaml 26 | - target: 27 | version: v1 28 | group: apps 29 | kind: Deployment 30 | name: controller-manager 31 | path: patch_deployment_resources.yaml 32 | - target: 33 | version: v1 34 | group: apps 35 | kind: Deployment 36 | name: controller-manager 37 | path: patch_deployment_security.yaml 38 | - target: 39 | version: v1 40 | group: apps 41 | kind: Deployment 42 | name: controller-manager 43 | path: patch_deployment_spec.yaml 44 | - target: 45 | version: v1 46 | group: apps 47 | kind: DaemonSet 48 | name: controller-manager-daemonset 49 | path: patch_daemonset_metadata.yaml 50 | - target: 51 | version: v1 52 | group: apps 53 | kind: DaemonSet 54 | name: controller-manager-daemonset 55 | path: patch_daemonset_resources.yaml 56 | - target: 57 | version: v1 58 | group: apps 59 | kind: DaemonSet 60 | name: controller-manager-daemonset 61 | path: patch_daemonset_security.yaml 62 | 63 | bases: 64 | - ../../manager 65 | -------------------------------------------------------------------------------- /config/helm/manager/patch_daemonset_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: controller-manager-daemonset 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: agent 11 | args: '{{- include "chart.lxcfs.args" . | nindent 8 }}' 12 | volumeMounts: 13 | - name: lxcfs 14 | mountPath: "{{.Values.lxcfs.mountPath}}" 15 | mountPropagation: Bidirectional 16 | volumes: 17 | - name: lxcfs 18 | hostPath: 19 | path: "{{.Values.lxcfs.mountPath}}" 20 | type: DirectoryOrCreate 21 | -------------------------------------------------------------------------------- /config/helm/manager/patch_daemonset_metadata.yaml: -------------------------------------------------------------------------------- 1 | - op: replace 2 | path: /metadata/labels 3 | value: '{{- include "chart.lxcfs.labels" . | nindent 4 }}' 4 | - op: replace 5 | path: /spec/selector/matchLabels 6 | value: '{{- include "chart.lxcfs.selectorLabels" . | nindent 6 }}' 7 | - op: replace 8 | path: /spec/template/metadata/labels 9 | value: '{{- include "chart.lxcfs.selectorLabels" . | nindent 8 }}' 10 | - op: replace 11 | path: /spec/template/metadata/annotations 12 | value: "{{- toYaml .Values.lxcfs.podAnnotations | nindent 8 }}" 13 | -------------------------------------------------------------------------------- /config/helm/manager/patch_daemonset_resources.yaml: -------------------------------------------------------------------------------- 1 | - op: replace 2 | path: /spec/template/spec/containers/0/resources 3 | value: "{{- toYaml .Values.lxcfs.resources | nindent 10 }}" 4 | -------------------------------------------------------------------------------- /config/helm/manager/patch_daemonset_security.yaml: -------------------------------------------------------------------------------- 1 | - op: replace 2 | path: /spec/template/spec/containers/0/imagePullPolicy 3 | value: "{{ .Values.pullPolicy | quote }}" 4 | -------------------------------------------------------------------------------- /config/helm/manager/patch_deployment_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | affinity: {} 10 | containers: 11 | - name: manager 12 | args: 13 | - "--lxcfs-path={{.Values.lxcfs.mountPath}}" 14 | - "--v={{.Values.logLevel}}" 15 | - "--leader-election={{.Values.leaderElection.enable}}" 16 | - "--leader-election-namespace={{.Values.leaderElection.namespace}}" 17 | - "--leader-election-id={{.Values.leaderElection.id}}" 18 | -------------------------------------------------------------------------------- /config/helm/manager/patch_deployment_metadata.yaml: -------------------------------------------------------------------------------- 1 | - op: replace 2 | path: /metadata/labels 3 | value: '{{- include "chart.labels" . | nindent 4 }}' 4 | - op: replace 5 | path: /spec/selector/matchLabels 6 | value: '{{- include "chart.selectorLabels" . | nindent 6 }}' 7 | - op: replace 8 | path: /spec/template/metadata/labels 9 | value: '{{- include "chart.selectorLabels" . | nindent 8 }}' 10 | - op: replace 11 | path: /spec/template/metadata/annotations 12 | value: "{{- toYaml .Values.podAnnotations | nindent 8 }}" 13 | -------------------------------------------------------------------------------- /config/helm/manager/patch_deployment_resources.yaml: -------------------------------------------------------------------------------- 1 | - op: test 2 | path: /spec/template/spec/containers/0/name 3 | value: manager 4 | - op: replace 5 | path: /spec/template/spec/containers/0/resources 6 | value: "{{- toYaml .Values.resources | nindent 10 }}" 7 | -------------------------------------------------------------------------------- /config/helm/manager/patch_deployment_security.yaml: -------------------------------------------------------------------------------- 1 | - op: replace 2 | path: /spec/template/spec/containers/0/imagePullPolicy 3 | value: "{{ .Values.pullPolicy | quote }}" 4 | -------------------------------------------------------------------------------- /config/helm/manager/patch_deployment_spec.yaml: -------------------------------------------------------------------------------- 1 | - op: replace 2 | path: /spec/replicas 3 | value: '{{ .Values.replicas }}' 4 | -------------------------------------------------------------------------------- /config/helm/manager/patch_deployment_webhook.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: '{{ include "chart.fullname" . }}-certificate' 24 | -------------------------------------------------------------------------------- /config/helm/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: "{{ .Release.Namespace | quote }}" 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | patches: 9 | - patch_clusterrolebinding.yaml 10 | 11 | bases: 12 | - ../../rbac 13 | -------------------------------------------------------------------------------- /config/helm/rbac/patch_clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | subjects: 6 | - kind: ServiceAccount 7 | name: default 8 | namespace: "{{ .Release.Namespace | quote }}" 9 | -------------------------------------------------------------------------------- /config/helm/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: "{{ .Release.Namespace | quote }}" 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | commonAnnotations: 9 | # Trick so kustomize does not split the annotation value 10 | cert-manager.io/inject-ca-from: '{{.Release.Namespace}}/{{. | include "chart.fullname"}}-serving-cert' 11 | 12 | # patchesStrategicMerge: 13 | # - validatingwebhook_endpoint_patch.yaml 14 | # - mutatingwebhook_endpoint_patch.yaml 15 | 16 | bases: 17 | - ../../webhook 18 | 19 | patchesJson6902: 20 | - target: 21 | version: v1 22 | group: admissionregistration.k8s.io 23 | kind: MutatingWebhookConfiguration 24 | name: mutating-webhook-configuration 25 | path: patch_mutatingwebhook_config.yaml 26 | -------------------------------------------------------------------------------- /config/helm/webhook/mutatingwebhook_endpoint_patch.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: mutating-webhook-configuration 6 | webhooks: 7 | - name: club.cndoit18.lxcfs-on-kubernetes 8 | clientConfig: 9 | service: 10 | name: '{{ include "chart.fullname" . | quote }}' 11 | namespace: "{{ .Release.Namespace | quote }}" 12 | -------------------------------------------------------------------------------- /config/helm/webhook/patch_mutatingwebhook_config.yaml: -------------------------------------------------------------------------------- 1 | - op: replace 2 | path: /webhooks/0/namespaceSelector/matchLabels 3 | value: "{{- toYaml .Values.lxcfs.matchLabels | nindent 6 }}" 4 | -------------------------------------------------------------------------------- /config/manager/daemonset_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: controller-manager-daemonset 5 | namespace: system 6 | spec: 7 | selector: 8 | matchLabels: 9 | app.kubernetes.io/component: lxcfs-agen 10 | template: 11 | spec: 12 | tolerations: 13 | - key: node-role.kubernetes.io/master 14 | effect: NoSchedule 15 | containers: 16 | - name: agent 17 | args: 18 | - "/var/lib/lxcfs" 19 | volumeMounts: 20 | - name: lxcfs 21 | mountPath: /var/lib/lxcfs 22 | mountPropagation: Bidirectional 23 | volumes: 24 | - name: lxcfs 25 | hostPath: 26 | path: /var/lib/lxcfs 27 | type: DirectoryOrCreate 28 | -------------------------------------------------------------------------------- /config/manager/deployment_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | selector: 8 | matchLabels: 9 | app.kubernetes.io/component: lxcfs 10 | template: 11 | spec: 12 | containers: 13 | - name: manager 14 | args: 15 | - --lxcfs-path=/var/lib/lxcfs 16 | -------------------------------------------------------------------------------- /config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | -------------------------------------------------------------------------------- /config/manager/manifests.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | labels: 7 | app.kubernetes.io/component: lxcfs 8 | spec: 9 | selector: 10 | matchLabels: 11 | app.kubernetes.io/component: lxcfs 12 | template: 13 | metadata: 14 | labels: 15 | app.kubernetes.io/component: lxcfs 16 | spec: 17 | containers: 18 | - image: ghcr.io/cndoit18/lxcfs-manager 19 | name: manager 20 | imagePullPolicy: IfNotPresent 21 | resources: 22 | limits: 23 | cpu: 500m 24 | memory: 300Mi 25 | requests: 26 | cpu: 300m 27 | memory: 200Mi 28 | terminationGracePeriodSeconds: 10 29 | --- 30 | apiVersion: apps/v1 31 | kind: DaemonSet 32 | metadata: 33 | namespace: system 34 | name: controller-manager-daemonset 35 | labels: 36 | app.kubernetes.io/component: lxcfs-agent 37 | spec: 38 | selector: 39 | matchLabels: 40 | app.kubernetes.io/component: lxcfs-agent 41 | template: 42 | metadata: 43 | labels: 44 | app.kubernetes.io/component: lxcfs-agent 45 | spec: 46 | hostPID: true 47 | containers: 48 | - name: agent 49 | image: ghcr.io/cndoit18/lxcfs-agent 50 | securityContext: 51 | privileged: true 52 | volumeMounts: 53 | - name: cgroup 54 | mountPath: /sys/fs/cgroup 55 | resources: 56 | limits: 57 | cpu: 500m 58 | memory: 300Mi 59 | requests: 60 | cpu: 300m 61 | memory: 200Mi 62 | imagePullPolicy: IfNotPresent 63 | volumes: 64 | - name: cgroup 65 | hostPath: 66 | path: /sys/fs/cgroup 67 | -------------------------------------------------------------------------------- /config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - role.yaml 3 | - role_binding.yaml 4 | -------------------------------------------------------------------------------- /config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: manager-role 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - configmaps 12 | - events 13 | verbs: 14 | - '*' 15 | - apiGroups: 16 | - coordination.k8s.io 17 | resources: 18 | - leases 19 | verbs: 20 | - '*' 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - pods 25 | verbs: 26 | - '*' 27 | -------------------------------------------------------------------------------- /config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | 8 | patchesStrategicMerge: 9 | - mutatingwebhook_patch.yaml 10 | -------------------------------------------------------------------------------- /config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting vars. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | 24 | varReference: 25 | - path: metadata/annotations 26 | -------------------------------------------------------------------------------- /config/webhook/manifests.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | creationTimestamp: null 6 | name: mutating-webhook-configuration 7 | webhooks: 8 | - admissionReviewVersions: 9 | - v1 10 | clientConfig: 11 | service: 12 | name: webhook-service 13 | namespace: system 14 | path: /mount-lxcfs 15 | failurePolicy: Ignore 16 | name: club.cndoit18.lxcfs-on-kubernetes 17 | rules: 18 | - apiGroups: 19 | - "" 20 | apiVersions: 21 | - v1 22 | operations: 23 | - CREATE 24 | resources: 25 | - pods 26 | sideEffects: NoneOnDryRun 27 | -------------------------------------------------------------------------------- /config/webhook/mutatingwebhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admissionregistration.k8s.io/v1 2 | kind: MutatingWebhookConfiguration 3 | metadata: 4 | name: mutating-webhook-configuration 5 | webhooks: 6 | - name: club.cndoit18.lxcfs-on-kubernetes 7 | namespaceSelector: 8 | matchLabels: 9 | mount-lxcfs: enabled 10 | -------------------------------------------------------------------------------- /config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: webhook-service 5 | namespace: system 6 | spec: 7 | ports: 8 | - port: 443 9 | targetPort: 9443 10 | selector: 11 | app.kubernetes.io/component: lxcfs 12 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cndoit18/lxcfs-on-kubernetes 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/spf13/pflag v1.0.5 7 | k8s.io/api v0.29.15 8 | k8s.io/klog/v2 v2.110.1 9 | sigs.k8s.io/controller-runtime v0.17.6 10 | ) 11 | 12 | require ( 13 | github.com/beorn7/perks v1.0.1 // indirect 14 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 15 | github.com/davecgh/go-spew v1.1.1 // indirect 16 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 17 | github.com/evanphx/json-patch/v5 v5.8.0 // indirect 18 | github.com/fsnotify/fsnotify v1.7.0 // indirect 19 | github.com/go-logr/logr v1.4.1 // indirect 20 | github.com/go-openapi/jsonpointer v0.19.6 // indirect 21 | github.com/go-openapi/jsonreference v0.20.2 // indirect 22 | github.com/go-openapi/swag v0.22.3 // indirect 23 | github.com/gogo/protobuf v1.3.2 // indirect 24 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 25 | github.com/golang/protobuf v1.5.4 // indirect 26 | github.com/google/gnostic-models v0.6.8 // indirect 27 | github.com/google/go-cmp v0.6.0 // indirect 28 | github.com/google/gofuzz v1.2.0 // indirect 29 | github.com/google/uuid v1.3.0 // indirect 30 | github.com/imdario/mergo v0.3.12 // indirect 31 | github.com/josharian/intern v1.0.0 // indirect 32 | github.com/json-iterator/go v1.1.12 // indirect 33 | github.com/mailru/easyjson v0.7.7 // indirect 34 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect 35 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 36 | github.com/modern-go/reflect2 v1.0.2 // indirect 37 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 38 | github.com/pkg/errors v0.9.1 // indirect 39 | github.com/prometheus/client_golang v1.18.0 // indirect 40 | github.com/prometheus/client_model v0.5.0 // indirect 41 | github.com/prometheus/common v0.45.0 // indirect 42 | github.com/prometheus/procfs v0.12.0 // indirect 43 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect 44 | golang.org/x/net v0.23.0 // indirect 45 | golang.org/x/oauth2 v0.12.0 // indirect 46 | golang.org/x/sys v0.18.0 // indirect 47 | golang.org/x/term v0.18.0 // indirect 48 | golang.org/x/text v0.14.0 // indirect 49 | golang.org/x/time v0.3.0 // indirect 50 | gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect 51 | google.golang.org/appengine v1.6.7 // indirect 52 | google.golang.org/protobuf v1.33.0 // indirect 53 | gopkg.in/inf.v0 v0.9.1 // indirect 54 | gopkg.in/yaml.v2 v2.4.0 // indirect 55 | gopkg.in/yaml.v3 v3.0.1 // indirect 56 | k8s.io/apimachinery v0.29.15 // indirect 57 | k8s.io/client-go v0.29.15 // indirect 58 | k8s.io/component-base v0.29.2 // indirect 59 | k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect 60 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect 61 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 62 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect 63 | sigs.k8s.io/yaml v1.4.0 // indirect 64 | ) 65 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 | github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= 4 | github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= 10 | github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 11 | github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= 12 | github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 13 | github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro= 14 | github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= 15 | github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= 16 | github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 17 | github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 18 | github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 19 | github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 20 | github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= 21 | github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= 22 | github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= 23 | github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= 24 | github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= 25 | github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= 26 | github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= 27 | github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 28 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= 29 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= 30 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 31 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 32 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 33 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 34 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 35 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 36 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 37 | github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= 38 | github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= 39 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 40 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 41 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 42 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 43 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 44 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 45 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= 46 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 47 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 48 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 49 | github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= 50 | github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 51 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 52 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 53 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 54 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 55 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 56 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 57 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 58 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 59 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 60 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 61 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 62 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 63 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 64 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 65 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 66 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= 67 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 68 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 69 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 70 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 71 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 72 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 73 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 74 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 75 | github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= 76 | github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= 77 | github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= 78 | github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= 79 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 80 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 81 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 82 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 83 | github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= 84 | github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= 85 | github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= 86 | github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= 87 | github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= 88 | github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 89 | github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= 90 | github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 91 | github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= 92 | github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= 93 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 94 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 95 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 96 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 97 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 98 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 99 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 100 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 101 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 102 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 103 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 104 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 105 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 106 | go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 107 | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 108 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 109 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 110 | go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= 111 | go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= 112 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 113 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 114 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 115 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= 116 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= 117 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 118 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 119 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 120 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 121 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 122 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 123 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 124 | golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= 125 | golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 126 | golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= 127 | golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 128 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 129 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 130 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 131 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 132 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 133 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 134 | golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= 135 | golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 136 | golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= 137 | golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= 138 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 139 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 140 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 141 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 142 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 143 | golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= 144 | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 145 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 146 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 147 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 148 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 149 | golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= 150 | golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= 151 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 152 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 153 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 154 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 155 | gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= 156 | gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= 157 | google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= 158 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 159 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 160 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 161 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 162 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 163 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 164 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 165 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 166 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 167 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 168 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 169 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 170 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 171 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 172 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 173 | k8s.io/api v0.29.15 h1:QxPcAheYujeBwkdiE0vMyKkAtqUq5YNyXVqimT+me44= 174 | k8s.io/api v0.29.15/go.mod h1:16duIp2ez6GiLPq1g8XtZNIkw6hJpIitpxZSvv0dZ6E= 175 | k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg= 176 | k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8= 177 | k8s.io/apimachinery v0.29.15 h1:aLc0wghElkdnTO7TMVTxTrifoXah1lqRL8s6szDHGbg= 178 | k8s.io/apimachinery v0.29.15/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y= 179 | k8s.io/client-go v0.29.15 h1:zCBOXKCtz9Hl8boKUGs8zbtZEP6pc7O8Ov3ma+gnS6o= 180 | k8s.io/client-go v0.29.15/go.mod h1:xPy0D3p4sonPhZhI3QoYo4m7oLKoPjFf4vYF9oxoxNM= 181 | k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8= 182 | k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM= 183 | k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= 184 | k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= 185 | k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= 186 | k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= 187 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= 188 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 189 | sigs.k8s.io/controller-runtime v0.17.6 h1:12IXsozEsIXWAMRpgRlYS1jjAHQXHtWEOMdULh3DbEw= 190 | sigs.k8s.io/controller-runtime v0.17.6/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY= 191 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= 192 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= 193 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= 194 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= 195 | sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= 196 | sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= 197 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Yinan Li 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ -------------------------------------------------------------------------------- /hack/boilerplate.txt: -------------------------------------------------------------------------------- 1 | # Copyright Yinan Li 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. -------------------------------------------------------------------------------- /pkg/admission/mutate.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Yinan Li 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package admission 18 | 19 | import ( 20 | "context" 21 | "encoding/json" 22 | "net/http" 23 | "sort" 24 | "strings" 25 | 26 | corev1 "k8s.io/api/core/v1" 27 | logr "sigs.k8s.io/controller-runtime/pkg/log" 28 | "sigs.k8s.io/controller-runtime/pkg/manager" 29 | "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 30 | ) 31 | 32 | var ( 33 | log = logr.Log.WithName("mutate") 34 | _ admission.Handler = &mutate{} 35 | ) 36 | 37 | type admissionOption func(m *mutate) 38 | 39 | func WithMutatePath(mutatePath string) admissionOption { 40 | return func(m *mutate) { 41 | if !strings.HasSuffix(mutatePath, "/") { 42 | mutatePath = mutatePath + "/" 43 | } 44 | m.mutatePath = mutatePath 45 | } 46 | } 47 | 48 | // nolint: lll 49 | // +kubebuilder:webhook:path=/mount-lxcfs,mutating=true,failurePolicy=ignore,groups="",resources=pods,verbs=create,versions=v1,name=club.cndoit18.lxcfs-on-kubernetes,sideEffects=NoneOnDryRun,admissionReviewVersions=v1 50 | // +kubebuilder:rbac:groups=core,resources=pods,verbs=* 51 | 52 | func AddToManager(mgr manager.Manager, opts ...admissionOption) error { 53 | m := &mutate{} 54 | for _, opt := range opts { 55 | opt(m) 56 | } 57 | 58 | mgr.GetWebhookServer().Register("/mount-lxcfs", &admission.Webhook{ 59 | Handler: m, 60 | }) 61 | 62 | return nil 63 | } 64 | 65 | type mutate struct { 66 | decoder *admission.Decoder 67 | mutatePath string 68 | } 69 | 70 | func (m *mutate) Handle(ctx context.Context, req admission.Request) admission.Response { 71 | pod := &corev1.Pod{} 72 | err := m.decoder.DecodeRaw(req.Object, pod) 73 | if err != nil { 74 | return admission.Errored(http.StatusInternalServerError, err) 75 | } 76 | 77 | // TODO: Add filter conditions. 78 | pod.Spec = m.ensurePodSpec(pod.Spec) 79 | 80 | marshalled, err := json.Marshal(pod) 81 | if err != nil { 82 | return admission.Errored(http.StatusInternalServerError, err) 83 | } 84 | 85 | // Create the patch 86 | return admission.PatchResponseFromRaw(req.Object.Raw, marshalled) 87 | } 88 | 89 | func (m *mutate) InjectDecoder(d *admission.Decoder) error { 90 | m.decoder = d 91 | 92 | return nil 93 | } 94 | 95 | func (m *mutate) ensurePodSpec(spec corev1.PodSpec) corev1.PodSpec { 96 | spec.Volumes = m.ensureVolume(spec.Volumes) 97 | spec.Containers = m.ensureContainer(spec.Containers) 98 | 99 | return spec 100 | } 101 | 102 | func (m *mutate) ensureContainer(cs []corev1.Container) []corev1.Container { 103 | containers := make([]corev1.Container, 0, len(cs)) 104 | containers = append(containers, cs...) 105 | for i := range containers { 106 | containers[i].VolumeMounts = m.ensureVolumeMount(containers[i].VolumeMounts) 107 | } 108 | 109 | return containers 110 | } 111 | 112 | func (m *mutate) ensureVolumeMount(volumeMounts []corev1.VolumeMount) []corev1.VolumeMount { 113 | mounts := map[string]string{ 114 | "lxcfs-proc-cpuinfo": "/proc/cpuinfo", 115 | "lxcfs-proc-diskstats": "/proc/diskstats", 116 | "lxcfs-proc-meminfo": "/proc/meminfo", 117 | "lxcfs-proc-stat": "/proc/stat", 118 | "lxcfs-proc-swaps": "/proc/swaps", 119 | "lxcfs-proc-uptime": "/proc/uptime", 120 | "lxcfs-proc-loadavg": "/proc/loadavg", 121 | "lxcfs-sys-devices-system-cpu": "/sys/devices/system/cpu", 122 | "lxcfs-sys-devices-system-cpu-online": "/sys/devices/system/cpu/online", 123 | } 124 | for _, v := range volumeMounts { 125 | if _, ok := mounts[v.Name]; !ok { 126 | continue 127 | } 128 | delete(mounts, v.Name) 129 | } 130 | 131 | result := make([]corev1.VolumeMount, 0, len(volumeMounts)+len(mounts)) 132 | result = append(result, volumeMounts...) 133 | for k, v := range mounts { 134 | result = append(result, 135 | corev1.VolumeMount{ 136 | Name: k, 137 | MountPath: v, 138 | ReadOnly: true, 139 | }) 140 | } 141 | 142 | sort.Slice(result, func(i, j int) bool { 143 | return result[i].Name < result[j].Name 144 | }) 145 | 146 | return result 147 | } 148 | 149 | func (m *mutate) ensureVolume(vs []corev1.Volume) []corev1.Volume { 150 | volumes := map[string]corev1.VolumeSource{ 151 | "lxcfs-proc-cpuinfo": { 152 | HostPath: &corev1.HostPathVolumeSource{ 153 | Path: m.mutatePath + "proc/cpuinfo", 154 | }, 155 | }, 156 | "lxcfs-proc-diskstats": { 157 | HostPath: &corev1.HostPathVolumeSource{ 158 | Path: m.mutatePath + "proc/diskstats", 159 | }, 160 | }, 161 | "lxcfs-proc-meminfo": { 162 | HostPath: &corev1.HostPathVolumeSource{ 163 | Path: m.mutatePath + "proc/meminfo", 164 | }, 165 | }, 166 | "lxcfs-proc-stat": { 167 | HostPath: &corev1.HostPathVolumeSource{ 168 | Path: m.mutatePath + "proc/stat", 169 | }, 170 | }, 171 | "lxcfs-proc-swaps": { 172 | HostPath: &corev1.HostPathVolumeSource{ 173 | Path: m.mutatePath + "proc/swaps", 174 | }, 175 | }, 176 | "lxcfs-proc-uptime": { 177 | HostPath: &corev1.HostPathVolumeSource{ 178 | Path: m.mutatePath + "proc/uptime", 179 | }, 180 | }, 181 | "lxcfs-proc-loadavg": { 182 | HostPath: &corev1.HostPathVolumeSource{ 183 | Path: m.mutatePath + "proc/loadavg", 184 | }, 185 | }, 186 | "lxcfs-sys-devices-system-cpu": { 187 | HostPath: &corev1.HostPathVolumeSource{ 188 | Path: m.mutatePath + "sys/devices/system/cpu", 189 | }, 190 | }, 191 | "lxcfs-sys-devices-system-cpu-online": { 192 | HostPath: &corev1.HostPathVolumeSource{ 193 | Path: m.mutatePath + "sys/devices/system/cpu/online", 194 | }, 195 | }, 196 | } 197 | 198 | for _, v := range vs { 199 | if _, ok := volumes[v.Name]; !ok { 200 | continue 201 | } 202 | delete(volumes, v.Name) 203 | } 204 | 205 | result := make([]corev1.Volume, 0, len(vs)+len(volumes)) 206 | result = append(result, vs...) 207 | for k, v := range volumes { 208 | result = append(result, corev1.Volume{ 209 | Name: k, 210 | VolumeSource: v, 211 | }) 212 | } 213 | 214 | sort.Slice(result, func(i, j int) bool { 215 | return result[i].Name < result[j].Name 216 | }) 217 | 218 | return result 219 | } 220 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Yinan Li 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package version 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | var ( 24 | GitCommit = "unknown" 25 | AppVersion = "unknown" 26 | ) 27 | 28 | func Version() string { 29 | return fmt.Sprintf("GitCommit: %s, AppVersion: %s", GitCommit, AppVersion) 30 | } 31 | --------------------------------------------------------------------------------