├── .github └── PULL_REQUEST_TEMPLATE.md ├── CONTRIBUTING.md ├── LICENSE ├── OWNERS ├── OWNERS_ALIASES ├── README.md ├── SECURITY_CONTACTS ├── code-of-conduct.md └── imagebuilder ├── .dockerignore ├── .gitignore ├── Dockerfile ├── Makefile ├── README.md ├── aws-1.10-jessie.yaml ├── aws-1.10-stretch.yaml ├── aws-1.11-jessie.yaml ├── aws-1.11-stretch.yaml ├── aws-1.12-stretch.yaml ├── aws-1.3.yaml ├── aws-1.4.yaml ├── aws-1.5.yaml ├── aws-1.6.yaml ├── aws-1.7.yaml ├── aws-1.8-jessie.yaml ├── aws-1.8-stretch.yaml ├── aws-1.9-jessie.yaml ├── aws-1.9-stretch.yaml ├── gce.yaml ├── glide.lock ├── glide.yaml ├── go.mod ├── go.sum ├── hack └── setup-aws.sh ├── main.go ├── pkg └── imagebuilder │ ├── aws.go │ ├── bootstrapvz.go │ ├── builder.go │ ├── cloud.go │ ├── config.go │ ├── executor │ ├── interface.go │ ├── local.go │ ├── ssh.go │ └── target.go │ ├── gce.go │ ├── template.go │ └── utils.go └── templates ├── 1.10-jessie.yml ├── 1.10-stretch.yml ├── 1.11-jessie.yml ├── 1.11-stretch.yml ├── 1.12-stretch.yml ├── 1.2.yml ├── 1.3.yml ├── 1.4.yml ├── 1.5.yml ├── 1.6.yml ├── 1.7.yml ├── 1.8-jessie.yml ├── 1.8-stretch.yml ├── 1.9-jessie.yml ├── 1.9-stretch.yml └── README.md /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | **What this PR does / why we need it**: 9 | 10 | **Which issue(s) this PR fixes** *(optional, in `fixes #(, fixes #, ...)` format, will close the issue(s) when PR gets merged)*: 11 | Fixes # 12 | 13 | **Special notes for your reviewer**: 14 | 15 | **Release note**: 16 | 20 | ```release-note 21 | 22 | ``` 23 | 24 | 25 | @kubernetes/kube-deploy-reviewers 26 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Read the following guide if you're interested in contributing to kube-deploy. 4 | 5 | ## Contributor License Agreements 6 | 7 | We'd love to accept your patches! Before we can take them, we have to jump a couple of legal hurdles. 8 | 9 | Please fill out either the individual or corporate Contributor License Agreement (CLA). More information about the CLA and instructions for signing it [can be found here](https://github.com/kubernetes/community/blob/master/CLA.md). 10 | 11 | ***NOTE***: Only original source code from you and other people that have signed the CLA can be accepted into the repository. 12 | 13 | ## Contributing a Patch 14 | 15 | 1. If you haven't already done so, sign a Contributor License Agreement (see details above). 16 | 1. Fork the desired repo, develop and test your code changes. 17 | 1. Submit a pull request. 18 | 19 | All changes must be code reviewed. Coding conventions and standards are explained in the official [developer docs](https://github.com/kubernetes/community/tree/master/contributors/devel). Expect reviewers to request that you avoid common [go style mistakes](https://github.com/golang/go/wiki/CodeReviewComments) in your PRs. 20 | 21 | ### Merge Approval 22 | 23 | Kube-deploy maintainers may add "LGTM" (Looks Good To Me) or an equivalent comment to indicate that a PR is acceptable. Any change requires at least one LGTM. No pull requests can be merged until at least one maintainer signs off with an LGTM. 24 | 25 | ## Support Channels 26 | 27 | Whether you are a user or contributor, official support channels include: 28 | 29 | - GitHub issues: https://github.com/kubernetes/kube-deploy/issues/new 30 | - Slack: Chat with us on [Slack](http://slack.k8s.io/): #sig-cluster-lifecycle 31 | - Email: [kubernetes-sig-cluster-lifecycle](https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle) mailing list 32 | 33 | Before opening a new issue or submitting a new pull request, it's helpful to search the project - it's likely that another user has already reported the issue you're facing, or it's a known issue that we're already aware of. 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - sig-cluster-lifecycle-leads 5 | - kube-deploy-admins 6 | - kube-deploy-maintainers 7 | 8 | reviewers: 9 | - kube-deploy-maintainers 10 | -------------------------------------------------------------------------------- /OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # See the OWNERS_ALIASES docs at https://go.k8s.io/owners#owners_aliases 2 | 3 | aliases: 4 | sig-cluster-lifecycle-leads: 5 | - justinsb 6 | - luxas 7 | - timothysc 8 | kube-deploy-admins: 9 | - justinsb 10 | - luxas 11 | kube-deploy-maintainers: 12 | - justinsb 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kube-deploy 2 | 3 | This is a repository of community maintained Kubernetes cluster deployment 4 | automations. 5 | 6 | Think of this as https://github.com/kubernetes/contrib for deployment 7 | automations! Each subdirectory is its own project. It should be a place where 8 | people can come see how the community is deploying kubernetes and should allow 9 | for faster development iteration compared to developing in the main repository. 10 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Committee to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | lukemarsden 14 | luxas 15 | roberthbailey 16 | timothysc 17 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /imagebuilder/.dockerignore: -------------------------------------------------------------------------------- 1 | imagebuilder 2 | -------------------------------------------------------------------------------- /imagebuilder/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | imagebuilder 3 | 4 | -------------------------------------------------------------------------------- /imagebuilder/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.11 AS build 2 | 3 | WORKDIR /go/src/k8s.io/kube-deploy/imagebuilder 4 | COPY . . 5 | RUN CGO_ENABLED=0 GOOS=linux go build 6 | 7 | FROM alpine:3.8 8 | WORKDIR /imagebuilder 9 | RUN apk add --no-cache ca-certificates 10 | COPY --from=build /go/src/k8s.io/kube-deploy/imagebuilder/imagebuilder imagebuilder 11 | ADD templates/ /imagebuilder/config/templates/ 12 | ADD aws*.yaml gce*.yaml /imagebuilder/config/ 13 | ENTRYPOINT ["/imagebuilder/imagebuilder"] 14 | -------------------------------------------------------------------------------- /imagebuilder/Makefile: -------------------------------------------------------------------------------- 1 | all: gocode 2 | 3 | gocode: 4 | go install k8s.io/kube-deploy/imagebuilder 5 | 6 | gofmt: 7 | gofmt -w -s main.go 8 | gofmt -w -s pkg 9 | -------------------------------------------------------------------------------- /imagebuilder/README.md: -------------------------------------------------------------------------------- 1 | ImageBuilder 2 | ============ 3 | 4 | ImageBuilder is a tool for building an optimized k8s images, currently only 5 | supporting AWS. 6 | 7 | Please also see the `README` in the `templates` folder for documentation as to 8 | the motivation for building a custom image. 9 | 10 | It is a wrapper around `bootstrap-vz`, which is the tool used to build official 11 | Debian cloud images. 12 | 13 | It adds functionality to spin up an instance for building the image, and 14 | publishing the image to all regions. 15 | 16 | Imagebuilder: 17 | 18 | * reads a config file (eg. `aws-1.11-stretch.yaml`) 19 | * creates an instance to build the image 20 | * builds the image as specified by `TemplatePath` in the config file 21 | * makes the image public if image publishing was enabled (it is, by default) 22 | * (AWS only) replicates the image to all accessible regions if replication was enabled (it is, by default) 23 | * and then shuts down the builder instance. 24 | 25 | These stages can be controlled through either flags or config file options, 26 | depending on the stage. 27 | 28 | For example, you might want to use `--publish=false` for an internal image. 29 | 30 | ## AWS 31 | 32 | * `export AWS_PROFILE=...` if you are not using the default profile. 33 | (or generate a new account & use `export AWS_ACCESS_KEY_ID` and `export AWS_SECRET_ACCESS_KEY`) 34 | * Create a VPC (with a subnet) and tag the subnet with `k8s.io/role/imagebuilder=1` 35 | * Create a security group in the VPC, allowing port 22, and tag with `k8s.io/role/imagebuilder=1` 36 | * The following commands are scripted in hack/setup-aws.sh 37 | 38 | ``` 39 | VPC_ID=`aws ec2 create-vpc --cidr-block 172.20.0.0/16 --query Vpc.VpcId --output text` 40 | aws ec2 create-tags --resources ${VPC_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 41 | 42 | SUBNET_ID=`aws ec2 create-subnet --cidr-block 172.20.1.0/24 --vpc-id ${VPC_ID} --query Subnet.SubnetId --output text` 43 | aws ec2 create-tags --resources ${SUBNET_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 44 | 45 | IGW_ID=`aws ec2 create-internet-gateway --query InternetGateway.InternetGatewayId --output text` 46 | aws ec2 create-tags --resources ${IGW_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 47 | 48 | aws ec2 attach-internet-gateway --internet-gateway-id ${IGW_ID} --vpc-id ${VPC_ID} 49 | 50 | RT_ID=`aws ec2 describe-route-tables --filters Name=vpc-id,Values=${VPC_ID} --query RouteTables[].RouteTableId --output text` 51 | 52 | SG_ID=`aws ec2 create-security-group --vpc-id ${VPC_ID} --group-name imagebuilder --description "imagebuilder security group" --query GroupId --output text` 53 | aws ec2 create-tags --resources ${SG_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 54 | 55 | aws ec2 associate-route-table --route-table-id ${RT_ID} --subnet-id ${SUBNET_ID} 56 | 57 | aws ec2 create-route --route-table-id ${RT_ID} --destination-cidr-block 0.0.0.0/0 --gateway-id ${IGW_ID} 58 | 59 | aws ec2 authorize-security-group-ingress --group-id ${SG_ID} --protocol tcp --port 22 --cidr 0.0.0.0/0 60 | ``` 61 | 62 | Then: 63 | 64 | ``` 65 | go get k8s.io/kube-deploy/imagebuilder 66 | ``` 67 | 68 | Build code: `make` 69 | 70 | Run the image builder: 71 | ``` 72 | cd ${GOPATH}/src/k8s.io/kube-deploy/imagebuilder` 73 | make 74 | ${GOPATH}/bin/imagebuilder --config aws.yaml --v=8 75 | ``` 76 | 77 | It will print the IDs of the image in each region, but it will also tag the 78 | image with a Name as specified in the template) and this is the easier way to 79 | retrieve the image. 80 | 81 | ## GCE 82 | 83 | * Edit gce.yaml, at least to specify the Project and GCSDestination to use 84 | * Create the GCS bucket in GCSDestination (if it does not exist) `gsutil mb 85 | gs:///` 86 | 87 | 88 | Then: 89 | 90 | ``` 91 | go get k8s.io/kube-deploy/imagebuilder 92 | ``` 93 | 94 | Run the image builder: 95 | ``` 96 | cd ${GOPATH}/src/k8s.io/kube-deploy/imagebuilder` 97 | make 98 | ${GOPATH}/bin/imagebuilder --config gce.yaml --v=8 --publish=false 99 | ``` 100 | 101 | Note that because GCE does not currently support publishing images, you must 102 | pass `--publish=false`. Also, images on GCE are global, so `replicate` does 103 | not actually need to do anything. 104 | 105 | Config file options 106 | =================== 107 | 108 | ImageBuilder uses a YAML config file that specifies a number of key 109 | configuration inputs. Some are specific to AWS or GCE. 110 | 111 | | **Option** | **Summary** | 112 | |--------------------|---------------------------------------------------------------------------------------------------| 113 | | `BootstrapVZBranch`| Git tag to pin `bootstrap-vz` to. Leave this at `image18` for now | 114 | | `BootstrapVZRepo` | Path to `bootstrap-vz` git repo. Leave this at `https://github.com/justinsb/bootstrap-vz.git` | 115 | | `Cloud` | Cloud provider. `aws` or `gce` | 116 | | `GCSDestination` | Google Cloud Storage bucket to store the final cloud image in | 117 | | `ImageID` | AWS machine image identifier (AMI) used for the _buildhost_ base OS where `bootstrap-vz` runs | 118 | | `InstanceProfile` | Optional AWS IAM role to be attached to the buildhost EC2 instance where `bootstrap-vz` runs | 119 | | `InstanceType` | Cloud compute instance type override, eg. `r4.large` | 120 | | `Project` | Google Cloud project to associate with the generated cloud image | 121 | | `SSHPrivateKey` | Path to SSH private key file in OpenSSH format. Default: `~/.ssh/id_rsa` | 122 | | `SSHPublicKey` | Path to SSH public key file in OpenSSH format. Default: `~/.ssh/id_rsa.pub` | 123 | | `Tags` | YAML map of cloud tags to be attached to the final cloud image | 124 | | `TemplatePath` | Path to `bootstrap-vz` template file, eg. `templates/1.11-stretch.yml` | 125 | 126 | Advanced options 127 | ================ 128 | 129 | Check out `--help`, but these options control which operations we perform, 130 | and may be useful for debugging or publishing a lot of images: 131 | 132 | * `--config=` path to a config file, as described above. Lets you 133 | configure most options 134 | 135 | * `--addtags=Foo=123,Bar=456,...` comma-separated list of additional cloud tags 136 | to apply. These will also be made available via Go templating in the 137 | `bootstrap-vz` configuration, specifically in the `Tags` map. See the next 138 | section for an example 139 | 140 | * `--up=true/false`, `--down=true/false` control whether we try to create and 141 | terminate an instance to do the building 142 | 143 | * `--publish=true/false` controls whether we make the image public 144 | 145 | * `--replicate=true/false` controls whether we copy the image to all regions 146 | 147 | Making use of tag data in templates 148 | =================================== 149 | 150 | The below example is a real-world demo of how tag data can be used; the 151 | assumption is that the `Branch` and `CIJob` are passed on the commandline with 152 | the `--addtags` option, probably filled with data from a continuous-build 153 | system. 154 | 155 | ``` 156 | {{- define "buildref" -}} 157 | {{- if eq .Tags.Branch "master" -}} 158 | {{- printf "master" -}} 159 | {{- else -}} 160 | {{- printf "%s" .Tags.CIJob -}} 161 | {{- end -}} 162 | {{- end -}} 163 | {{ if eq .Cloud "aws" }} 164 | name: k8s-1.9-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d}-{{ template "buildref" . }} 165 | {{ else }} 166 | name: k8s-1.9-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d}-{{- template "buildref" . }} 167 | {{ end }} 168 | ``` 169 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.10-jessie.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.10-jessie.yml 3 | Tags: 4 | k8s.io/kernel: "4.4" 5 | k8s.io/version: "1.10" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.10-stretch.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.10-stretch.yml 3 | Tags: 4 | k8s.io/kernel: "4.9" 5 | k8s.io/version: "1.10" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.11-jessie.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.11-jessie.yml 3 | Tags: 4 | k8s.io/kernel: "4.4" 5 | k8s.io/version: "1.11" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.11-stretch.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.11-stretch.yml 3 | Tags: 4 | k8s.io/kernel: "4.9" 5 | k8s.io/version: "1.11" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.12-stretch.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.12-stretch.yml 3 | Tags: 4 | k8s.io/kernel: "4.9" 5 | k8s.io/version: "1.12" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.3.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.3.yml -------------------------------------------------------------------------------- /imagebuilder/aws-1.4.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.4.yml 3 | Tags: 4 | k8s.io/kernel: "4.4" 5 | k8s.io/version: "1.4" 6 | k8s.io/family: "default" 7 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.5.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.5.yml 3 | Tags: 4 | k8s.io/kernel: "4.4" 5 | k8s.io/version: "1.5" 6 | k8s.io/family: "default" 7 | # Ensure the image is repeatable - really we should be locking to a tag 8 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 9 | BootstrapVZBranch: image15 10 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.6.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.6.yml 3 | Tags: 4 | k8s.io/kernel: "4.4" 5 | k8s.io/version: "1.6" 6 | k8s.io/family: "default" 7 | # Ensure the image is repeatable - really we should be locking to a tag 8 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 9 | BootstrapVZBranch: image16 10 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.7.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.7.yml 3 | Tags: 4 | k8s.io/kernel: "4.4" 5 | k8s.io/version: "1.7" 6 | k8s.io/family: "default" 7 | # Ensure the image is repeatable - really we should be locking to a tag 8 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 9 | BootstrapVZBranch: image17 10 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.8-jessie.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.8-jessie.yml 3 | Tags: 4 | k8s.io/kernel: "4.9" 5 | k8s.io/version: "1.8" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.8-stretch.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.8-stretch.yml 3 | Tags: 4 | k8s.io/kernel: "4.9" 5 | k8s.io/version: "1.8" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.9-jessie.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.9-jessie.yml 3 | Tags: 4 | k8s.io/kernel: "4.9" 5 | k8s.io/version: "1.9" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/aws-1.9-stretch.yaml: -------------------------------------------------------------------------------- 1 | Cloud: aws 2 | TemplatePath: templates/1.9-stretch.yml 3 | Tags: 4 | k8s.io/kernel: "4.9" 5 | k8s.io/version: "1.9" 6 | k8s.io/family: "default" 7 | k8s.io/distro: "debian" 8 | k8s.io/ssh-user: "admin" 9 | # Ensure the image is repeatable - really we should be locking to a tag 10 | BootstrapVZRepo: https://github.com/justinsb/bootstrap-vz.git 11 | BootstrapVZBranch: image18 12 | -------------------------------------------------------------------------------- /imagebuilder/gce.yaml: -------------------------------------------------------------------------------- 1 | Cloud: gce 2 | TemplatePath: templates/1.3.yml 3 | 4 | # GCE Project that you want to use 5 | Project: 6 | 7 | # GCS bucket where the image should be uploaded 8 | GCSDestination: gs:/// 9 | -------------------------------------------------------------------------------- /imagebuilder/glide.lock: -------------------------------------------------------------------------------- 1 | hash: d8ebb43fb9bda2861c6d3cf8cc7f270791e1e7f2161c51cefcb32a7630138e2d 2 | updated: 2016-07-04T16:01:53.294324612-04:00 3 | imports: 4 | - name: github.com/aws/aws-sdk-go 5 | version: caee6e866bf437a6bef0777a3bf141cdd3aa022d 6 | subpackages: 7 | - aws 8 | - aws/awserr 9 | - aws/session 10 | - service/ec2 11 | - aws/credentials 12 | - aws/client 13 | - aws/corehandlers 14 | - aws/defaults 15 | - aws/request 16 | - private/endpoints 17 | - aws/awsutil 18 | - aws/client/metadata 19 | - aws/signer/v4 20 | - private/protocol 21 | - private/protocol/ec2query 22 | - private/waiter 23 | - aws/credentials/ec2rolecreds 24 | - aws/ec2metadata 25 | - private/protocol/rest 26 | - private/protocol/query/queryutil 27 | - private/protocol/xml/xmlutil 28 | - name: github.com/cloudfoundry-incubator/candiedyaml 29 | version: 99c3df83b51532e3615f851d8c2dbb638f5313bf 30 | - name: github.com/ghodss/yaml 31 | version: aa0c862057666179de291b67d9f093d12b5a8473 32 | - name: github.com/go-ini/ini 33 | version: 927d8d7ced542ab92df77ac1637b6e56336ee0dd 34 | - name: github.com/golang/glog 35 | version: 23def4e6c14b4da8ac2ed8007337bc5eb5007998 36 | - name: github.com/golang/protobuf 37 | version: 3852dcfda249c2097355a6aabb199a28d97b30df 38 | subpackages: 39 | - proto 40 | - name: github.com/jmespath/go-jmespath 41 | version: 0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74 42 | - name: golang.org/x/crypto 43 | version: 0c565bf13221fb55497d7ae2bb95694db1fd1bff 44 | subpackages: 45 | - ssh 46 | - curve25519 47 | - ed25519 48 | - ed25519/internal/edwards25519 49 | - name: golang.org/x/net 50 | version: b400c2eff1badec7022a8c8f5bea058b6315eed7 51 | subpackages: 52 | - context 53 | - context/ctxhttp 54 | - name: golang.org/x/oauth2 55 | version: df5b72659a3b1789a345ea643bb7c28442681652 56 | subpackages: 57 | - google 58 | - internal 59 | - jws 60 | - jwt 61 | - name: google.golang.org/api 62 | version: 57212573ccf9e4f69f4caa0336831697e29adcd6 63 | subpackages: 64 | - compute/v1 65 | - googleapi 66 | - storage/v1 67 | - gensupport 68 | - googleapi/internal/uritemplates 69 | - name: google.golang.org/appengine 70 | version: 267c27e7492265b84fc6719503b14a1e17975d79 71 | subpackages: 72 | - urlfetch 73 | - internal 74 | - internal/app_identity 75 | - internal/modules 76 | - internal/urlfetch 77 | - internal/base 78 | - internal/datastore 79 | - internal/log 80 | - internal/remote_api 81 | - name: google.golang.org/cloud 82 | version: ebfe3819c9ab4acaf086ae57e4cbd7dee683baf0 83 | subpackages: 84 | - compute/metadata 85 | - internal 86 | - name: gopkg.in/yaml.v2 87 | version: a83829b6f1293c91addabc89d0571c246397bbf4 88 | devImports: [] 89 | -------------------------------------------------------------------------------- /imagebuilder/glide.yaml: -------------------------------------------------------------------------------- 1 | package: k8s.io/kube-deploy/imagebuilder 2 | import: 3 | - package: github.com/aws/aws-sdk-go 4 | subpackages: 5 | - aws 6 | - aws/awserr 7 | - aws/session 8 | - service/ec2 9 | - package: github.com/ghodss/yaml 10 | - package: github.com/golang/glog 11 | - package: golang.org/x/crypto 12 | subpackages: 13 | - ssh 14 | - package: golang.org/x/net 15 | subpackages: 16 | - context 17 | - package: golang.org/x/oauth2 18 | subpackages: 19 | - google 20 | - package: google.golang.org/api 21 | subpackages: 22 | - compute/v1 23 | - googleapi 24 | - storage/v1 25 | - package: gopkg.in/yaml.v2 26 | -------------------------------------------------------------------------------- /imagebuilder/go.mod: -------------------------------------------------------------------------------- 1 | module k8s.io/kube-deploy/imagebuilder 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go v1.2.2 7 | github.com/cloudfoundry-incubator/candiedyaml v0.0.0-20160429080125-99c3df83b515 8 | github.com/ghodss/yaml v0.0.0-20160604002925-aa0c86205766 9 | github.com/go-ini/ini v0.0.0-20160702095645-927d8d7ced54 10 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b 11 | github.com/golang/protobuf v0.0.0-20160629211053-3852dcfda249 12 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 13 | golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f 14 | golang.org/x/net v0.0.0-20160630220910-b400c2eff1ba 15 | golang.org/x/oauth2 v0.0.0-20160702010809-df5b72659a3b 16 | google.golang.org/api v0.0.0-20160630034138-57212573ccf9 17 | google.golang.org/appengine v0.0.0-20160621060416-267c27e74922 18 | google.golang.org/cloud v0.0.0-20160701095312-ebfe3819c9ab 19 | gopkg.in/yaml.v2 v2.0.0-20160301204022-a83829b6f129 20 | ) 21 | -------------------------------------------------------------------------------- /imagebuilder/go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-sdk-go v1.2.2 h1:GYEG5KMO0YrEK9QmIFlX0uiGIDTLjV5lW1C2Lk1Xtfc= 2 | github.com/aws/aws-sdk-go v1.2.2/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= 3 | github.com/cloudfoundry-incubator/candiedyaml v0.0.0-20160429080125-99c3df83b515 h1:w9aM4g/uDa2+bpH8M0pG+fUQID3yV1oXzgyXGdxp8yw= 4 | github.com/cloudfoundry-incubator/candiedyaml v0.0.0-20160429080125-99c3df83b515/go.mod h1:dOLSIXcRQJiDS1vlrYFNJicoHNZLsBKideE+70hGdV4= 5 | github.com/ghodss/yaml v0.0.0-20160604002925-aa0c86205766 h1:zuHHSLtqQzeNb4X5AjIhNehd5ATHqhI1EOGO+4MdJFE= 6 | github.com/ghodss/yaml v0.0.0-20160604002925-aa0c86205766/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 7 | github.com/go-ini/ini v0.0.0-20160702095645-927d8d7ced54 h1:BRIwmzjQlRuzYFjTdkZkL5aJq7h+IR5aPrG+7JBR5xE= 8 | github.com/go-ini/ini v0.0.0-20160702095645-927d8d7ced54/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 9 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 10 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 11 | github.com/golang/protobuf v0.0.0-20160629211053-3852dcfda249/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 12 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE= 13 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 14 | golang.org/x/crypto v0.0.0-20160704103416-0c565bf13221/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 15 | golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f h1:qWFY9ZxP3tfI37wYIs/MnIAqK0vlXp1xnYEa5HxFSSY= 16 | golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 17 | golang.org/x/net v0.0.0-20160630220910-b400c2eff1ba h1:uDRLy7XWpErbelDDzBrVF4l3MkgIwXtu5nl44tiWpE0= 18 | golang.org/x/net v0.0.0-20160630220910-b400c2eff1ba/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 19 | golang.org/x/oauth2 v0.0.0-20160702010809-df5b72659a3b h1:3iVfXCULp6VYN3NwTfM8gRcZSyIC6OtBFX22ynl+hQQ= 20 | golang.org/x/oauth2 v0.0.0-20160702010809-df5b72659a3b/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 21 | google.golang.org/api v0.0.0-20160630034138-57212573ccf9 h1:yJolfx5bJExkprmLeMih/TQadBvec1Ft75VvGsiNNAo= 22 | google.golang.org/api v0.0.0-20160630034138-57212573ccf9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 23 | google.golang.org/appengine v0.0.0-20160621060416-267c27e74922/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 24 | google.golang.org/cloud v0.0.0-20160701095312-ebfe3819c9ab h1:litgndtapfTyH0d3dM9y6VR2xkylgnSYYm5rg3Vb2e8= 25 | google.golang.org/cloud v0.0.0-20160701095312-ebfe3819c9ab/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= 26 | gopkg.in/yaml.v2 v2.0.0-20160301204022-a83829b6f129 h1:RBgb9aPUbZ9nu66ecQNIBNsA7j3mB5h8PNDIfhPjaJg= 27 | gopkg.in/yaml.v2 v2.0.0-20160301204022-a83829b6f129/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 28 | -------------------------------------------------------------------------------- /imagebuilder/hack/setup-aws.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo Starting aws setup 4 | 5 | # this does not working us-east-2 yet 6 | # export AWS_REGION=us-west-1 7 | 8 | export VPC_ID=`aws ec2 create-vpc --cidr-block 172.20.0.0/16 --query Vpc.VpcId --output text` 9 | aws ec2 create-tags --resources ${VPC_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 10 | 11 | export SUBNET_ID=`aws ec2 create-subnet --cidr-block 172.20.1.0/24 --vpc-id ${VPC_ID} --query Subnet.SubnetId --output text` 12 | aws ec2 create-tags --resources ${SUBNET_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 13 | 14 | 15 | export IGW_ID=`aws ec2 create-internet-gateway --query InternetGateway.InternetGatewayId --output text` 16 | aws ec2 create-tags --resources ${IGW_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 17 | 18 | aws ec2 attach-internet-gateway --internet-gateway-id ${IGW_ID} --vpc-id ${VPC_ID} 19 | 20 | export RT_ID=`aws ec2 describe-route-tables --filters Name=vpc-id,Values=${VPC_ID} --query RouteTables[].RouteTableId --output text` 21 | 22 | export SG_ID=`aws ec2 create-security-group --vpc-id ${VPC_ID} --group-name imagebuilder --description "imagebuilder security group" --query GroupId --output text` 23 | aws ec2 create-tags --resources ${SG_ID} --tags Key=k8s.io/role/imagebuilder,Value=1 24 | 25 | aws ec2 associate-route-table --route-table-id ${RT_ID} --subnet-id ${SUBNET_ID} 26 | 27 | aws ec2 create-route --route-table-id ${RT_ID} --destination-cidr-block 0.0.0.0/0 --gateway-id ${IGW_ID} 28 | 29 | aws ec2 authorize-security-group-ingress --group-id ${SG_ID} --protocol tcp --port 22 --cidr 0.0.0.0/0 30 | 31 | IMGBUILDER_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 32 | 33 | cd $IMGBUILDER_DIRECTORY/.. 34 | 35 | export AWS_REGION=$(aws configure get region) 36 | imagebuilder --config aws.yaml --v=8 37 | 38 | echo We are done, and there be dragons! 39 | -------------------------------------------------------------------------------- /imagebuilder/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors All rights reserved. 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 | "fmt" 22 | "io/ioutil" 23 | "math/rand" 24 | "net" 25 | "net/url" 26 | "os" 27 | "path" 28 | "strings" 29 | "time" 30 | 31 | "github.com/aws/aws-sdk-go/aws" 32 | "github.com/aws/aws-sdk-go/aws/session" 33 | "github.com/aws/aws-sdk-go/service/ec2" 34 | "github.com/ghodss/yaml" 35 | "github.com/golang/glog" 36 | "golang.org/x/crypto/ssh" 37 | "golang.org/x/net/context" 38 | "golang.org/x/oauth2/google" 39 | "google.golang.org/api/compute/v1" 40 | "google.golang.org/api/storage/v1" 41 | "k8s.io/kube-deploy/imagebuilder/pkg/imagebuilder" 42 | "k8s.io/kube-deploy/imagebuilder/pkg/imagebuilder/executor" 43 | ) 44 | 45 | var flagConfig = flag.String("config", "", "Config file to load") 46 | 47 | //var flagRegion = flag.String("region", "", "Cloud region to use") 48 | //var flagImage = flag.String("image", "", "Image to use as builder") 49 | //var flagSSHKey = flag.String("sshkey", "", "Name of SSH key to use") 50 | //var flagInstanceType = flag.String("instancetype", "m3.medium", "Instance type to launch") 51 | //var flagSubnet = flag.String("subnet", "", "Subnet in which to launch") 52 | //var flagSecurityGroup = flag.String("securitygroup", "", "Security group to use for launch") 53 | //var flagTemplatePath = flag.String("template", "", "Path to image template") 54 | 55 | var flagUp = flag.Bool("up", true, "Set to create instance (if not found)") 56 | var flagBuild = flag.Bool("build", true, "Set to build image") 57 | var flagTag = flag.Bool("tag", true, "Set to tag image") 58 | var flagPublish = flag.Bool("publish", true, "Set to publish image") 59 | var flagReplicate = flag.Bool("replicate", true, "Set to copy the image to all regions") 60 | var flagDown = flag.Bool("down", true, "Set to shut down instance (if found)") 61 | var flagAddTags = flag.String("addtags", "", "Comma-separated list of key=value pairs to be added as additional Tags") 62 | 63 | var flagLocalhost = flag.Bool("localhost", false, "Set to use local machine for execution") 64 | var flagLogdir = flag.String("logdir", "", "Set to preserve logs") 65 | 66 | func loadConfig(dest interface{}, src string) error { 67 | data, err := ioutil.ReadFile(src) 68 | if err != nil { 69 | return fmt.Errorf("error reading file %q: %v", src, err) 70 | } 71 | 72 | err = yaml.Unmarshal(data, dest) 73 | if err != nil { 74 | return fmt.Errorf("error parsing file %q: %v", src, err) 75 | } 76 | 77 | return nil 78 | } 79 | 80 | func main() { 81 | rand.Seed(time.Now().UTC().UnixNano()) 82 | 83 | flag.Set("alsologtostderr", "true") 84 | flag.Parse() 85 | 86 | if *flagConfig == "" { 87 | glog.Exitf("--config must be specified") 88 | } 89 | 90 | var templateContext interface{} 91 | 92 | config := &imagebuilder.Config{} 93 | config.InitDefaults() 94 | err := loadConfig(config, *flagConfig) 95 | if err != nil { 96 | glog.Exitf("Error loading config: %v", err) 97 | } 98 | 99 | for key, value := range splitAdditionalTags() { 100 | glog.Infof("Injecting additional tag: %q = %q", key, value) 101 | config.Tags[key] = value 102 | } 103 | 104 | var cloud imagebuilder.Cloud 105 | switch config.Cloud { 106 | case "aws": 107 | awsConfig, awsCloud, err := initAWS(*flagLocalhost) 108 | if err != nil { 109 | glog.Exitf("%v", err) 110 | } 111 | awsConfig.Tags = config.Tags 112 | templateContext = awsConfig 113 | cloud = awsCloud 114 | 115 | case "gce": 116 | if *flagPublish { 117 | glog.Exitf("Publishing images is not supported on gce (pass --publish=false)") 118 | } 119 | 120 | gceConfig, gceCloud, err := initGCE() 121 | if err != nil { 122 | glog.Exitf("%v", err) 123 | } 124 | gceConfig.Tags = config.Tags 125 | templateContext = gceConfig 126 | cloud = gceCloud 127 | 128 | case "": 129 | glog.Exitf("Cloud not set") 130 | default: 131 | glog.Exitf("Unknown cloud: %q", config.Cloud) 132 | } 133 | 134 | if *flagBuild && config.TemplatePath == "" { 135 | glog.Fatalf("TemplatePath must be provided") 136 | } 137 | 138 | var bvzTemplate *imagebuilder.BootstrapVzTemplate 139 | var imageName string 140 | if config.TemplatePath != "" { 141 | templateResolved := path.Join(path.Dir(*flagConfig), config.TemplatePath) 142 | 143 | templateRaw, err := imagebuilder.ReadFile(templateResolved) 144 | if err != nil { 145 | glog.Fatalf("error reading template: %v", err) 146 | } 147 | 148 | templateString, err := imagebuilder.ExpandTemplate(templateResolved, string(templateRaw), templateContext) 149 | if err != nil { 150 | glog.Fatalf("error executing template: %v", err) 151 | } 152 | 153 | bvzTemplate, err = imagebuilder.NewBootstrapVzTemplate(templateString) 154 | if err != nil { 155 | glog.Fatalf("error parsing template: %v", err) 156 | } 157 | 158 | imageName, err = bvzTemplate.BuildImageName() 159 | if err != nil { 160 | glog.Fatalf("error inferring image name: %v", err) 161 | } 162 | 163 | glog.Infof("Parsed template %q; will build image with name %s", config.TemplatePath, imageName) 164 | } 165 | 166 | instance, err := cloud.GetInstance() 167 | if err != nil { 168 | glog.Fatalf("error getting instance: %v", err) 169 | } 170 | 171 | if instance == nil && *flagUp { 172 | instance, err = cloud.CreateInstance() 173 | if err != nil { 174 | glog.Fatalf("error creating instance: %v", err) 175 | } 176 | } 177 | 178 | image, err := cloud.FindImage(imageName) 179 | if err != nil { 180 | glog.Fatalf("error finding image %q: %v", imageName, err) 181 | } 182 | 183 | if image != nil { 184 | glog.Infof("found existing image %q", image) 185 | } 186 | 187 | if *flagBuild && image == nil { 188 | if instance == nil { 189 | glog.Fatalf("Instance was not found (specify --up?)") 190 | } 191 | 192 | validateHostKey := func(hostname string, remote net.Addr, key ssh.PublicKey) error { 193 | glog.Infof("accepting host key %s for %s", key, hostname) 194 | return nil 195 | } 196 | 197 | sshConfig := &ssh.ClientConfig{ 198 | User: config.SSHUsername, 199 | HostKeyCallback: validateHostKey, 200 | } 201 | 202 | if !*flagLocalhost { 203 | if config.SSHPrivateKey == "" { 204 | glog.Fatalf("SSHPublicKey is required") 205 | // We used to allow the SSH agent, but probably more trouble than it is worth? 206 | //sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")) 207 | //if err != nil { 208 | // glog.Fatalf("error connecting to SSH agent: %v", err) 209 | //} 210 | // 211 | //sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)) 212 | } else { 213 | keyBytes, err := imagebuilder.ReadFile(config.SSHPrivateKey) 214 | if err != nil { 215 | glog.Exitf("error loading SSH private key: %v", err) 216 | } 217 | key, err := ssh.ParsePrivateKey(keyBytes) 218 | if err != nil { 219 | glog.Exitf("error parsing SSH private key: %v", err) 220 | } 221 | 222 | sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeys(key)) 223 | } 224 | } 225 | x, err := instance.DialSSH(sshConfig) 226 | if err != nil { 227 | glog.Fatalf("error SSHing to instance: %v", err) 228 | } 229 | defer x.Close() 230 | 231 | sshHelper := executor.NewTarget(x) 232 | 233 | builder := imagebuilder.NewBuilder(config, sshHelper) 234 | err = builder.RunSetupCommands() 235 | if err != nil { 236 | glog.Fatalf("error setting up instance: %v", err) 237 | } 238 | 239 | extraEnv, err := cloud.GetExtraEnv() 240 | if err != nil { 241 | glog.Fatalf("error building environment: %v", err) 242 | } 243 | 244 | logdir := *flagLogdir 245 | 246 | err = builder.BuildImage(bvzTemplate.Bytes(), extraEnv, logdir) 247 | if err != nil { 248 | glog.Fatalf("error building image: %v", err) 249 | } 250 | 251 | image, err = cloud.FindImage(imageName) 252 | if err != nil { 253 | glog.Fatalf("error finding image %q: %v", imageName, err) 254 | } 255 | 256 | if image == nil { 257 | glog.Fatalf("image not found after build: %q", imageName) 258 | } 259 | } 260 | 261 | if *flagTag { 262 | if image == nil { 263 | glog.Fatalf("image not found: %q", imageName) 264 | } 265 | 266 | glog.Infof("Tagging image %q", image) 267 | 268 | tags := make(map[string]string) 269 | for k, v := range config.Tags { 270 | tags[k] = v 271 | } 272 | 273 | { 274 | t := time.Now().UTC().Format("20060102150405") 275 | tags["k8s.io/build"] = t 276 | } 277 | 278 | err = image.AddTags(tags) 279 | if err != nil { 280 | glog.Fatalf("error tagging image %q: %v", imageName, err) 281 | } 282 | 283 | glog.Infof("Tagged image %q", image) 284 | } 285 | 286 | if *flagPublish { 287 | if image == nil { 288 | glog.Fatalf("image not found: %q", imageName) 289 | } 290 | 291 | glog.Infof("Making image public: %v", image) 292 | 293 | err = image.EnsurePublic() 294 | if err != nil { 295 | glog.Fatalf("error making image public %q: %v", imageName, err) 296 | } 297 | 298 | glog.Infof("Made image public: %v", image) 299 | } 300 | 301 | if *flagReplicate { 302 | if image == nil { 303 | glog.Fatalf("image not found: %q", imageName) 304 | } 305 | 306 | glog.Infof("Copying image to all regions: %v", image) 307 | 308 | images, err := image.ReplicateImage(*flagPublish) 309 | if err != nil { 310 | glog.Fatalf("error replicating image %q: %v", imageName, err) 311 | } 312 | 313 | for region, imageID := range images { 314 | glog.Infof("Image in region %q: %q", region, imageID) 315 | } 316 | } 317 | 318 | if *flagDown { 319 | if instance == nil { 320 | glog.Infof("Instance not found / already shutdown") 321 | } else { 322 | err := instance.Shutdown() 323 | if err != nil { 324 | glog.Fatalf("error terminating instance: %v", err) 325 | } 326 | } 327 | } 328 | } 329 | 330 | func splitAdditionalTags() map[string]string { 331 | tags := make(map[string]string) 332 | if *flagAddTags != "" { 333 | for _, tagpair := range strings.Split(*flagAddTags, ",") { 334 | trimmed := strings.TrimSpace(tagpair) 335 | kv := strings.Split(trimmed, "=") 336 | if len(kv) != 2 { 337 | glog.Fatalf("addtags value malformed, should be key=value: %q", tagpair) 338 | } 339 | tags[kv[0]] = kv[1] 340 | } 341 | } 342 | return tags 343 | } 344 | 345 | func initAWS(useLocalhost bool) (*imagebuilder.AWSConfig, *imagebuilder.AWSCloud, error) { 346 | region := os.Getenv("AWS_REGION") 347 | if region == "" { 348 | region = os.Getenv("AWS_DEFAULT_REGION") 349 | } 350 | awsConfig := &imagebuilder.AWSConfig{} 351 | awsConfig.InitDefaults(region) 352 | err := loadConfig(awsConfig, *flagConfig) 353 | if err != nil { 354 | glog.Exitf("Error loading AWS config: %v", err) 355 | } 356 | 357 | if awsConfig.Region == "" { 358 | glog.Exitf("Region must be set") 359 | } 360 | 361 | ec2Client := ec2.New(session.New(), &aws.Config{Region: &awsConfig.Region}) 362 | awsCloud := imagebuilder.NewAWSCloud(ec2Client, awsConfig, useLocalhost) 363 | 364 | return awsConfig, awsCloud, nil 365 | } 366 | 367 | func initGCE() (*imagebuilder.GCEConfig, *imagebuilder.GCECloud, error) { 368 | config := &imagebuilder.GCEConfig{} 369 | config.InitDefaults() 370 | err := loadConfig(config, *flagConfig) 371 | if err != nil { 372 | return nil, nil, fmt.Errorf("Error loading GCE config: %v", err) 373 | } 374 | 375 | if config.Project == "" { 376 | return nil, nil, fmt.Errorf("Project must be set") 377 | } 378 | 379 | if config.MachineName == "" { 380 | return nil, nil, fmt.Errorf("Name must be set") 381 | } 382 | if config.Zone == "" { 383 | return nil, nil, fmt.Errorf("Zone must be set") 384 | } 385 | if config.MachineType == "" { 386 | return nil, nil, fmt.Errorf("MachineType must be set") 387 | } 388 | 389 | if config.Image == "" { 390 | return nil, nil, fmt.Errorf("Image must be set") 391 | } 392 | 393 | if config.GCSDestination == "" { 394 | return nil, nil, fmt.Errorf("GCSDestination must be set") 395 | } 396 | 397 | // Avoid common mistake... 398 | if !strings.HasSuffix(config.GCSDestination, "/") { 399 | return nil, nil, fmt.Errorf("GCSDestination should end in /") 400 | } 401 | if !strings.HasPrefix(config.GCSDestination, "gs://") { 402 | return nil, nil, fmt.Errorf("GCSDestination should start with gs://") 403 | } 404 | 405 | ctx := context.Background() 406 | 407 | client, err := google.DefaultClient(ctx, compute.ComputeScope) 408 | if err != nil { 409 | return nil, nil, fmt.Errorf("error building google API client: %v", err) 410 | } 411 | computeService, err := compute.New(client) 412 | if err != nil { 413 | return nil, nil, fmt.Errorf("error building compute API client: %v", err) 414 | } 415 | 416 | storageService, err := storage.New(client) 417 | if err != nil { 418 | return nil, nil, fmt.Errorf("error building compute API client: %v", err) 419 | } 420 | u, err := url.Parse(config.GCSDestination) 421 | if err != nil { 422 | return nil, nil, fmt.Errorf("GCSDestination %q is not a well-formed URL: %v", config.GCSDestination, err) 423 | } 424 | glog.Infof("Checking for bucket %q", u.Host) 425 | _, err = storageService.Buckets.Get(u.Host).Do() 426 | if err != nil { 427 | if imagebuilder.IsGCENotFound(err) { 428 | return nil, nil, fmt.Errorf("GCS bucket does not exist: %v", config.GCSDestination) 429 | } 430 | return nil, nil, fmt.Errorf("Error checking that bucket exists: %v", err) 431 | } 432 | 433 | cloud := imagebuilder.NewGCECloud(computeService, config) 434 | 435 | return config, cloud, nil 436 | } 437 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/bootstrapvz.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors All rights reserved. 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 imagebuilder 18 | 19 | import ( 20 | "fmt" 21 | "regexp" 22 | "strconv" 23 | "strings" 24 | "time" 25 | 26 | "gopkg.in/yaml.v2" 27 | ) 28 | 29 | // NewBootstrapVzTemplate builds a BootstrapVzTemplate from a file 30 | func NewBootstrapVzTemplate(data string) (*BootstrapVzTemplate, error) { 31 | m := make(map[interface{}]interface{}) 32 | 33 | err := yaml.Unmarshal([]byte(data), &m) 34 | if err != nil { 35 | return nil, fmt.Errorf("error parsing template: %v", err) 36 | } 37 | return &BootstrapVzTemplate{data: m, raw: []byte(data)}, nil 38 | } 39 | 40 | // BootstrapVzTemplate represents a bootstrap-vz template file 41 | type BootstrapVzTemplate struct { 42 | data map[interface{}]interface{} 43 | raw []byte 44 | } 45 | 46 | // Bytes returns the template contents 47 | func (t *BootstrapVzTemplate) Bytes() []byte { 48 | return t.raw 49 | } 50 | 51 | // BuildImageName computes the name of the image that will be built 52 | func (t *BootstrapVzTemplate) BuildImageName() (string, error) { 53 | name, err := t.getString("name") 54 | if err != nil { 55 | return "", err 56 | } 57 | if name == "" { 58 | return "", fmt.Errorf("name not found in template") 59 | } 60 | regex := regexp.MustCompile("{([^}]*)}") 61 | 62 | now := time.Now().UTC() 63 | 64 | var replaceErr error 65 | 66 | replacer := func(path string) string { 67 | // Remove { and } 68 | path = path[1 : len(path)-1] 69 | 70 | if path == "" { 71 | return "" 72 | } 73 | 74 | if path[0] == '%' { 75 | switch path { 76 | case "%Y": 77 | return strconv.Itoa(now.Year()) 78 | case "%m": 79 | return fmt.Sprintf("%02d", now.Month()) 80 | case "%d": 81 | return fmt.Sprintf("%02d", now.Day()) 82 | default: 83 | replaceErr = fmt.Errorf("unknown template specifier: %q", path) 84 | return "" 85 | } 86 | } else { 87 | v, err := t.getString(path) 88 | if err != nil { 89 | replaceErr = fmt.Errorf("error replacing template spec %q: %v", path, err) 90 | return "" 91 | } 92 | return v 93 | } 94 | } 95 | 96 | name = regex.ReplaceAllStringFunc(name, replacer) 97 | if replaceErr != nil { 98 | return "", replaceErr 99 | } 100 | return name, nil 101 | } 102 | 103 | func (t *BootstrapVzTemplate) getString(path string) (string, error) { 104 | tokens := strings.Split(path, ".") 105 | pos := t.data 106 | for i, token := range tokens { 107 | next, found := pos[token] 108 | if !found { 109 | return "", nil 110 | } 111 | 112 | if (i + 1) == len(tokens) { 113 | s, ok := next.(string) 114 | if !ok { 115 | return "", fmt.Errorf("Expected string, found %T at %q", next, path) 116 | } 117 | return s, nil 118 | } 119 | 120 | m, ok := next.(map[interface{}]interface{}) 121 | if !ok { 122 | return "", fmt.Errorf("Expected map, found %T at %q", next, path) 123 | } 124 | pos = m 125 | } 126 | 127 | panic("unreachable") 128 | } 129 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/builder.go: -------------------------------------------------------------------------------- 1 | package imagebuilder 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/rand" 7 | "os" 8 | "path" 9 | 10 | "k8s.io/kube-deploy/imagebuilder/pkg/imagebuilder/executor" 11 | ) 12 | 13 | type Builder struct { 14 | config *Config 15 | target *executor.Target 16 | } 17 | 18 | func NewBuilder(config *Config, target *executor.Target) *Builder { 19 | return &Builder{ 20 | config: config, 21 | target: target, 22 | } 23 | } 24 | 25 | func (b *Builder) RunSetupCommands() error { 26 | for _, c := range b.config.SetupCommands { 27 | if err := b.target.Exec(c...); err != nil { 28 | return err 29 | } 30 | } 31 | 32 | return nil 33 | } 34 | 35 | func (b *Builder) BuildImage(template []byte, extraEnv map[string]string, logdir string) error { 36 | tmpdir := fmt.Sprintf("/tmp/imagebuilder-%d", rand.Int63()) 37 | err := b.target.Mkdir(tmpdir, 0755) 38 | if err != nil { 39 | return err 40 | } 41 | defer b.target.Exec("rm", "-rf", tmpdir) 42 | 43 | if logdir == "" { 44 | logdir = path.Join(tmpdir, "logs") 45 | } 46 | err = b.target.Mkdir(logdir, 0755) 47 | if err != nil && !os.IsExist(err) { 48 | return err 49 | } 50 | 51 | //err = ssh.Exec("git clone https://github.com/andsens/bootstrap-vz.git " + tmpdir + "/bootstrap-vz") 52 | err = b.target.Exec("git", "clone", b.config.BootstrapVZRepo, "-b", b.config.BootstrapVZBranch, tmpdir+"/bootstrap-vz") 53 | if err != nil { 54 | return err 55 | } 56 | 57 | err = b.target.Put(tmpdir+"/template.yml", len(template), bytes.NewReader(template), 0644) 58 | if err != nil { 59 | return err 60 | } 61 | 62 | cmd := b.target.Command("./bootstrap-vz/bootstrap-vz", "--debug", "--log", logdir, "./template.yml") 63 | cmd.Cwd = tmpdir 64 | for k, v := range extraEnv { 65 | cmd.Env[k] = v 66 | } 67 | cmd.Sudo = true 68 | err = cmd.Run() 69 | if err != nil { 70 | return err 71 | } 72 | 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/cloud.go: -------------------------------------------------------------------------------- 1 | package imagebuilder 2 | 3 | import ( 4 | "golang.org/x/crypto/ssh" 5 | "k8s.io/kube-deploy/imagebuilder/pkg/imagebuilder/executor" 6 | ) 7 | 8 | type Cloud interface { 9 | GetInstance() (Instance, error) 10 | CreateInstance() (Instance, error) 11 | 12 | FindImage(imageName string) (Image, error) 13 | 14 | GetExtraEnv() (map[string]string, error) 15 | } 16 | 17 | type Instance interface { 18 | DialSSH(config *ssh.ClientConfig) (executor.Executor, error) 19 | Shutdown() error 20 | } 21 | 22 | type Image interface { 23 | EnsurePublic() error 24 | 25 | // Adds the specified tags to the image 26 | AddTags(tags map[string]string) error 27 | 28 | ReplicateImage(makePublic bool) (map[string]Image, error) 29 | } 30 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/config.go: -------------------------------------------------------------------------------- 1 | package imagebuilder 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/golang/glog" 7 | ) 8 | 9 | type Config struct { 10 | Cloud string 11 | TemplatePath string 12 | SetupCommands [][]string 13 | 14 | BootstrapVZRepo string 15 | BootstrapVZBranch string 16 | 17 | SSHUsername string 18 | SSHPublicKey string 19 | SSHPrivateKey string 20 | 21 | InstanceProfile string 22 | 23 | // Tags to add to the image 24 | Tags map[string]string 25 | } 26 | 27 | func (c *Config) InitDefaults() { 28 | c.BootstrapVZRepo = "https://github.com/andsens/bootstrap-vz.git" 29 | c.BootstrapVZBranch = "master" 30 | 31 | c.SSHUsername = "admin" 32 | c.SSHPublicKey = "~/.ssh/id_rsa.pub" 33 | c.SSHPrivateKey = "~/.ssh/id_rsa" 34 | 35 | c.InstanceProfile = "" 36 | 37 | setupCommands := []string{ 38 | "sudo apt-get update", 39 | "sudo apt-get install --yes git python debootstrap python-pip kpartx parted", 40 | "sudo pip install --upgrade requests termcolor jsonschema fysom docopt pyyaml boto boto3", 41 | } 42 | for _, cmd := range setupCommands { 43 | c.SetupCommands = append(c.SetupCommands, strings.Split(cmd, " ")) 44 | } 45 | } 46 | 47 | type AWSConfig struct { 48 | Config 49 | 50 | Region string 51 | ImageID string 52 | InstanceType string 53 | SSHKeyName string 54 | SubnetID string 55 | SecurityGroupID string 56 | Tags map[string]string 57 | } 58 | 59 | func (c *AWSConfig) InitDefaults(region string) { 60 | c.Config.InitDefaults() 61 | c.InstanceType = "m3.medium" 62 | 63 | if region == "" { 64 | region = "us-east-1" 65 | } 66 | 67 | c.Region = region 68 | switch c.Region { 69 | case "cn-north-1": 70 | glog.Infof("Detected cn-north-1 region") 71 | // A slightly older image, but the newest one we have 72 | c.ImageID = "ami-da69a1b7" 73 | 74 | // Debian 9.5 images from https://wiki.debian.org/Cloud/AmazonEC2Image/Stretch 75 | case "ap-northeast-1": 76 | c.ImageID = "ami-048813c43a892bf4a" 77 | case "ap-northeast-2": 78 | c.ImageID = "ami-0b61dc7b9ac9452c7" 79 | case "ap-south-1": 80 | c.ImageID = "ami-02f59cc6982469cd2" 81 | case "ap-southeast-1": 82 | c.ImageID = "ami-0a9a79bb079115e9b" 83 | case "ap-southeast-2": 84 | c.ImageID = "ami-0abf02e9015527575" 85 | case "ca-central-1": 86 | c.ImageID = "ami-0e825d093523065f9" 87 | case "eu-central-1": 88 | c.ImageID = "ami-0681ed9bb7a58a33d" 89 | case "eu-west-1": 90 | c.ImageID = "ami-0483f1cc1c483803f" 91 | case "eu-west-2": 92 | c.ImageID = "ami-0d9ba70fd9e495233" 93 | case "eu-west-3": 94 | c.ImageID = "ami-0b59b5cf392c3c2b3" 95 | case "sa-east-1": 96 | c.ImageID = "ami-0bd8e4655e2beef08" 97 | case "us-east-1": 98 | c.ImageID = "ami-03006931f694ea7eb" 99 | case "us-east-2": 100 | c.ImageID = "ami-06dfb9abeb4a6afc6" 101 | case "us-west-1": 102 | c.ImageID = "ami-0f0674cb683fcc1f7" 103 | case "us-west-2": 104 | c.ImageID = "ami-0a1fbca0e5b419fd1" 105 | 106 | default: 107 | glog.Warningf("Building in unknown region %q - will require specifying an image, may not work correctly") 108 | } 109 | 110 | // Not all regions support m3.medium 111 | switch c.Region { 112 | case "us-east-2": 113 | c.InstanceType = "m4.large" 114 | } 115 | } 116 | 117 | type GCEConfig struct { 118 | Config 119 | 120 | // To create an image on GCE, we have to upload it to a bucket first 121 | GCSDestination string 122 | 123 | Project string 124 | Zone string 125 | MachineName string 126 | 127 | MachineType string 128 | Image string 129 | Tags map[string]string 130 | } 131 | 132 | func (c *GCEConfig) InitDefaults() { 133 | c.Config.InitDefaults() 134 | c.MachineName = "k8s-imagebuilder" 135 | c.Zone = "us-central1-f" 136 | c.MachineType = "n1-standard-2" 137 | c.Image = "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-8-jessie-v20160329" 138 | } 139 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/executor/interface.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "math/rand" 8 | "os" 9 | "strings" 10 | 11 | "github.com/golang/glog" 12 | ) 13 | 14 | type Executor interface { 15 | Close() error 16 | 17 | Run(c *CommandExecution) error 18 | 19 | Put(dest string, length int, content io.Reader, mode os.FileMode) error 20 | Mkdir(dest string, mode os.FileMode) error 21 | } 22 | 23 | type runFunction func(cmd []string) ([]byte, error) 24 | 25 | // runCommand is a helper function for executing a command 26 | func runCommand(cmd *CommandExecution, x Executor, runner runFunction) error { 27 | // Warn if the caller is doing something dumb 28 | if cmd.Sudo && cmd.Command[0] == "sudo" { 29 | glog.Warningf("sudo used with command that includes sudo (%q)", cmd.Command) 30 | } 31 | 32 | var script bytes.Buffer 33 | 34 | needScript := false 35 | 36 | script.WriteString("#!/bin/bash -e\n") 37 | if cmd.Cwd != "" { 38 | script.WriteString("cd " + cmd.Cwd + "\n") 39 | needScript = true 40 | } 41 | if cmd.Env != nil && len(cmd.Env) != 0 { 42 | // Most SSH servers are configured not to accept arbitrary env vars 43 | for k, v := range cmd.Env { 44 | /* err := session.Setenv(k, v) 45 | if err != nil { 46 | return fmt.Errorf("error setting env var in SSH session: %v", err) 47 | } 48 | */ 49 | script.WriteString("export " + k + "='" + v + "'\n") 50 | needScript = true 51 | } 52 | } 53 | script.WriteString(joinCommand(cmd.Command) + "\n") 54 | 55 | cmdToRun := cmd.Command 56 | if needScript { 57 | tmpScript := fmt.Sprintf("/tmp/ssh-exec-%d", rand.Int63()) 58 | scriptBytes := script.Bytes() 59 | err := x.Put(tmpScript, len(scriptBytes), bytes.NewReader(scriptBytes), 0755) 60 | if err != nil { 61 | return fmt.Errorf("error uploading temporary script: %v", err) 62 | } 63 | defer runner([]string{"rm", "-rf", tmpScript}) 64 | if cmd.Sudo { 65 | cmdToRun = []string{"sudo", tmpScript} 66 | } else { 67 | cmdToRun = []string{tmpScript} 68 | } 69 | } else { 70 | if cmd.Sudo { 71 | cmdToRun = append([]string{"sudo"}, cmdToRun...) 72 | } 73 | } 74 | 75 | // We "lie" about the command we're running when we're using a script 76 | glog.Infof("Executing command: %q", cmd.Command) 77 | output, err := runner(cmdToRun) 78 | if err != nil { 79 | glog.Infof("Error from SSH command %q: %v", cmd.Command, err) 80 | glog.Infof("Output was: %s", output) 81 | return fmt.Errorf("error executing SSH command %q: %v", cmd.Command, err) 82 | } 83 | 84 | glog.V(2).Infof("Output was: %s", output) 85 | return nil 86 | } 87 | 88 | func joinCommand(argv []string) string { 89 | // TODO: escaping 90 | return strings.Join(argv, " ") 91 | } 92 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/executor/local.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "os/exec" 8 | 9 | "github.com/golang/glog" 10 | ) 11 | 12 | type LocalhostExecutor struct { 13 | } 14 | 15 | var _ Executor = &LocalhostExecutor{} 16 | 17 | func (e *LocalhostExecutor) Close() error { 18 | return nil 19 | } 20 | 21 | func (s *LocalhostExecutor) Mkdir(dest string, mode os.FileMode) error { 22 | return os.Mkdir(dest, mode) 23 | } 24 | 25 | func (s *LocalhostExecutor) Put(dest string, length int, content io.Reader, mode os.FileMode) error { 26 | f, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) 27 | if err != nil { 28 | return fmt.Errorf("error opening file %q: %v", dest, err) 29 | } 30 | 31 | defer func() { 32 | if f != nil { 33 | err := f.Close() 34 | if err != nil { 35 | glog.Warningf("error closing file %q: %v", dest, err) 36 | } 37 | } 38 | }() 39 | 40 | _, err = io.Copy(f, content) 41 | if err != nil { 42 | return fmt.Errorf("error writing file %q: %v", dest, err) 43 | } 44 | 45 | err = f.Close() 46 | f = nil // Don't close in defer block 47 | if err != nil { 48 | return fmt.Errorf("error closing file %q: %v", dest, err) 49 | } 50 | 51 | return nil 52 | } 53 | 54 | func (s *LocalhostExecutor) Run(cmd *CommandExecution) error { 55 | return runCommand(cmd, s, func(command []string) ([]byte, error) { 56 | name := command[0] 57 | args := []string{} 58 | if len(command) > 1 { 59 | args = command[1:] 60 | } 61 | 62 | output, err := exec.Command(name, args...).CombinedOutput() 63 | return output, err 64 | }) 65 | } 66 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/executor/ssh.go: -------------------------------------------------------------------------------- 1 | package executor 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "path/filepath" 8 | "strconv" 9 | 10 | "github.com/golang/glog" 11 | "golang.org/x/crypto/ssh" 12 | ) 13 | 14 | type SSHExecutor struct { 15 | sshClient *ssh.Client 16 | } 17 | 18 | func NewSSH(client *ssh.Client) Executor { 19 | return &SSHExecutor{sshClient: client} 20 | } 21 | 22 | var _ Executor = &SSHExecutor{} 23 | 24 | func (e *SSHExecutor) Close() error { 25 | return e.sshClient.Close() 26 | } 27 | 28 | // SCPMkdir executes a mkdir against the SSH target, using SCP 29 | func (s *SSHExecutor) Mkdir(dest string, mode os.FileMode) error { 30 | glog.Infof("Doing SSH SCP mkdir: %q", dest) 31 | session, err := s.sshClient.NewSession() 32 | if err != nil { 33 | return fmt.Errorf("error establishing SSH session: %v", err) 34 | } 35 | defer session.Close() 36 | 37 | name := filepath.Base(dest) 38 | scpBase := filepath.Dir(dest) 39 | //scpBase = "." + scpBase 40 | 41 | var stdinErr error 42 | go func() { 43 | w, _ := session.StdinPipe() 44 | defer w.Close() 45 | _, stdinErr = fmt.Fprintln(w, "D0"+toOctal(mode), 0, name) 46 | if stdinErr != nil { 47 | return 48 | } 49 | }() 50 | output, err := session.CombinedOutput("/usr/bin/scp -tr " + scpBase) 51 | if err != nil { 52 | glog.Warningf("Error output from SCP: %s", output) 53 | return fmt.Errorf("error doing SCP mkdir: %v", err) 54 | } 55 | if stdinErr != nil { 56 | glog.Warningf("Error output from SCP: %s", output) 57 | return fmt.Errorf("error doing SCP mkdir (writing to stdin): %v", stdinErr) 58 | } 59 | 60 | return nil 61 | } 62 | 63 | func toOctal(mode os.FileMode) string { 64 | return strconv.FormatUint(uint64(mode), 8) 65 | } 66 | 67 | // SCPPut copies a file to the SSH target, using SCP 68 | func (s *SSHExecutor) Put(dest string, length int, content io.Reader, mode os.FileMode) error { 69 | glog.Infof("Doing SSH SCP upload: %q", dest) 70 | session, err := s.sshClient.NewSession() 71 | if err != nil { 72 | return fmt.Errorf("error establishing SSH session: %v", err) 73 | } 74 | defer session.Close() 75 | 76 | name := filepath.Base(dest) 77 | scpBase := filepath.Dir(dest) 78 | //scpBase = "." + scpBase 79 | 80 | var stdinErr error 81 | go func() { 82 | w, _ := session.StdinPipe() 83 | defer w.Close() 84 | _, stdinErr = fmt.Fprintln(w, "C0"+toOctal(mode), length, name) 85 | if stdinErr != nil { 86 | return 87 | } 88 | _, stdinErr = io.Copy(w, content) 89 | if stdinErr != nil { 90 | return 91 | } 92 | _, stdinErr = fmt.Fprint(w, "\x00") 93 | if stdinErr != nil { 94 | return 95 | } 96 | }() 97 | output, err := session.CombinedOutput("/usr/bin/scp -tr " + scpBase) 98 | if err != nil { 99 | glog.Warningf("Error output from SCP: %s", output) 100 | return fmt.Errorf("error doing SCP put: %v", err) 101 | } 102 | if stdinErr != nil { 103 | glog.Warningf("Error output from SCP: %s", output) 104 | return fmt.Errorf("error doing SCP put (writing to stdin): %v", stdinErr) 105 | } 106 | 107 | return nil 108 | } 109 | 110 | func (s *SSHExecutor) Run(cmd *CommandExecution) error { 111 | session, err := s.sshClient.NewSession() 112 | if err != nil { 113 | return fmt.Errorf("error establishing SSH session: %v", err) 114 | } 115 | defer session.Close() 116 | 117 | return runCommand(cmd, s, func(command []string) ([]byte, error) { 118 | output, err := session.CombinedOutput(joinCommand(command)) 119 | return output, err 120 | }) 121 | } 122 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/executor/target.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors All rights reserved. 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 | // TODO: This probably should be moved to / shared with nodeup, because then it would allow action on a remote target 18 | 19 | package executor 20 | 21 | import ( 22 | "io" 23 | "os" 24 | ) 25 | 26 | // NewTarget constructs a new target 27 | func NewTarget(executor Executor) *Target { 28 | return &Target{ 29 | executor: executor, 30 | } 31 | } 32 | 33 | // SSH holds an SSH client, and adds utilities like SCP functionality 34 | type Target struct { 35 | executor Executor 36 | } 37 | 38 | func (t *Target) Put(dest string, length int, content io.Reader, mode os.FileMode) error { 39 | return t.executor.Put(dest, length, content, mode) 40 | } 41 | 42 | func (t *Target) Mkdir(dest string, mode os.FileMode) error { 43 | return t.executor.Mkdir(dest, mode) 44 | } 45 | 46 | // CommandExecution helps us build a command for running 47 | type CommandExecution struct { 48 | Command []string 49 | Cwd string 50 | Env map[string]string 51 | Sudo bool 52 | executor Executor 53 | } 54 | 55 | // WithSudo indicates that the command should be executed with sudo 56 | func (c *CommandExecution) WithSudo() *CommandExecution { 57 | c.Sudo = true 58 | return c 59 | } 60 | 61 | // WithCwd sets the directory in which the command will execute 62 | func (c *CommandExecution) WithCwd(cwd string) *CommandExecution { 63 | c.Cwd = cwd 64 | return c 65 | } 66 | 67 | // Setenv sets an environment variable for the command execution 68 | func (c *CommandExecution) Setenv(k, v string) *CommandExecution { 69 | c.Env[k] = v 70 | return c 71 | } 72 | 73 | // Run executes the command 74 | func (c *CommandExecution) Run() error { 75 | return c.executor.Run(c) 76 | } 77 | 78 | // Command builds a CommandExecution bound to the current SSH target 79 | func (s *Target) Command(cmd ...string) *CommandExecution { 80 | c := &CommandExecution{ 81 | executor: s.executor, 82 | Command: cmd, 83 | Env: make(map[string]string), 84 | } 85 | return c 86 | } 87 | 88 | // Exec executes a command against the SSH target 89 | func (s *Target) Exec(cmd ...string) error { 90 | c := s.Command(cmd...) 91 | return c.Run() 92 | } 93 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/gce.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors All rights reserved. 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 imagebuilder 18 | 19 | import ( 20 | "fmt" 21 | "time" 22 | 23 | "github.com/golang/glog" 24 | "golang.org/x/crypto/ssh" 25 | "google.golang.org/api/compute/v1" 26 | "google.golang.org/api/googleapi" 27 | "k8s.io/kube-deploy/imagebuilder/pkg/imagebuilder/executor" 28 | ) 29 | 30 | // TODO: We should replace most of this code with a fast-install manifest 31 | // This would also allow more customization, and get rid of half of this code 32 | // BUT... there's a circular dependency in the PRs here... :-) 33 | 34 | // GCEInstance manages an GCE instance, used for building an image 35 | type GCEInstance struct { 36 | cloud *GCECloud 37 | name string 38 | instance *compute.Instance 39 | } 40 | 41 | // Shutdown terminates the running instance 42 | func (i *GCEInstance) Shutdown() error { 43 | glog.Infof("Terminating instance %q", i.name) 44 | return i.cloud.deleteInstance(i.name) 45 | } 46 | 47 | // DialSSH establishes an SSH client connection to the instance 48 | func (i *GCEInstance) DialSSH(config *ssh.ClientConfig) (executor.Executor, error) { 49 | publicIP, err := i.WaitPublicIP() 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | for { 55 | // TODO: Timeout, check error code 56 | sshClient, err := ssh.Dial("tcp", publicIP+":22", config) 57 | if err != nil { 58 | glog.Warningf("error connecting to SSH on server %q: %v", publicIP, err) 59 | time.Sleep(5 * time.Second) 60 | continue 61 | // return nil, fmt.Errorf("error connecting to SSH on server %q", publicIP) 62 | } 63 | 64 | return executor.NewSSH(sshClient), nil 65 | } 66 | } 67 | 68 | // WaitPublicIP waits for the instance to get a public IP, returning it 69 | func (i *GCEInstance) WaitPublicIP() (string, error) { 70 | // TODO: Timeout 71 | for { 72 | instance, err := i.cloud.describeInstance(i.name) 73 | if err != nil { 74 | return "", err 75 | } 76 | 77 | for _, ni := range instance.NetworkInterfaces { 78 | for _, ac := range ni.AccessConfigs { 79 | if ac.NatIP != "" { 80 | glog.Infof("Instance public IP is %q", ac.NatIP) 81 | return ac.NatIP, nil 82 | } 83 | } 84 | } 85 | glog.V(2).Infof("Sleeping before requerying instance for public IP: %q", i.name) 86 | time.Sleep(5 * time.Second) 87 | } 88 | } 89 | 90 | // GCECloud is a helper type for talking to an GCE acccount 91 | type GCECloud struct { 92 | config *GCEConfig 93 | 94 | computeClient *compute.Service 95 | } 96 | 97 | var _ Cloud = &GCECloud{} 98 | 99 | func NewGCECloud(computeClient *compute.Service, config *GCEConfig) *GCECloud { 100 | return &GCECloud{ 101 | computeClient: computeClient, 102 | config: config, 103 | } 104 | } 105 | 106 | func (a *GCECloud) GetExtraEnv() (map[string]string, error) { 107 | // No extra env needed on GCE 108 | env := make(map[string]string) 109 | return env, nil 110 | } 111 | 112 | func IsGCENotFound(err error) bool { 113 | apiErr, ok := err.(*googleapi.Error) 114 | if !ok { 115 | return false 116 | } 117 | return apiErr.Code == 404 118 | } 119 | 120 | func (c *GCECloud) describeInstance(name string) (*compute.Instance, error) { 121 | glog.V(2).Infof("GCE Instances List Name=%q", name) 122 | instances, err := c.computeClient.Instances.List(c.config.Project, c.config.Zone).Filter("name eq " + name).Do() 123 | if err != nil { 124 | return nil, fmt.Errorf("error making GCE Instances List call: %v", err) 125 | } 126 | 127 | if len(instances.Items) == 0 { 128 | return nil, nil 129 | } 130 | if len(instances.Items) != 1 { 131 | return nil, fmt.Errorf("found multiple instances with name %q", name) 132 | } 133 | return instances.Items[0], nil 134 | } 135 | 136 | // deleteInstance terminates the specified instance 137 | func (c *GCECloud) deleteInstance(name string) error { 138 | glog.V(2).Infof("GCE Delete Instances name=%q", name) 139 | _, err := c.computeClient.Instances.Delete(c.config.Project, c.config.Zone, name).Do() 140 | if err != nil { 141 | return fmt.Errorf("error terminating instance %q: %v", name, err) 142 | } 143 | return nil 144 | } 145 | 146 | // GetInstance returns the GCE instance matching our tags, or nil if not found 147 | func (c *GCECloud) GetInstance() (Instance, error) { 148 | name := c.config.MachineName 149 | 150 | instance, err := c.describeInstance(name) 151 | if err != nil { 152 | return nil, err 153 | } 154 | 155 | if instance != nil { 156 | glog.Infof("Found existing instance: %q", instance.Name) 157 | return &GCEInstance{ 158 | cloud: c, 159 | instance: instance, 160 | name: instance.Name, 161 | }, nil 162 | } 163 | 164 | return nil, nil 165 | } 166 | 167 | // CreateInstance creates an instance for building an image instance 168 | func (c *GCECloud) CreateInstance() (Instance, error) { 169 | name := c.config.MachineName 170 | zone := c.config.Zone 171 | 172 | machineType := "zones/" + zone + "/machineTypes/" + c.config.MachineType 173 | glog.Infof("creating instance with machinetype %s", machineType) 174 | 175 | var disks []*compute.AttachedDisk 176 | disks = append(disks, &compute.AttachedDisk{ 177 | InitializeParams: &compute.AttachedDiskInitializeParams{ 178 | SourceImage: c.config.Image, 179 | DiskType: "zones/" + zone + "/diskTypes/pd-ssd", 180 | }, 181 | Boot: true, 182 | DeviceName: "disk-0", 183 | Index: 0, 184 | AutoDelete: true, 185 | Mode: "READ_WRITE", 186 | Type: "PERSISTENT", 187 | }) 188 | 189 | metadata := &compute.Metadata{} 190 | 191 | if c.config.SSHPublicKey != "" { 192 | publicKey, err := ReadFile(c.config.SSHPublicKey) 193 | if err != nil { 194 | return nil, err 195 | } 196 | sshKey := "admin:" + string(publicKey) 197 | 198 | metadata.Items = append(metadata.Items, &compute.MetadataItems{ 199 | Key: "ssh-keys", 200 | Value: &sshKey, 201 | }) 202 | } 203 | 204 | scopes := []string{ 205 | "https://www.googleapis.com/auth/devstorage.read_write", 206 | "https://www.googleapis.com/auth/compute", 207 | } 208 | 209 | instance := &compute.Instance{ 210 | Name: name, 211 | NetworkInterfaces: []*compute.NetworkInterface{ 212 | { 213 | AccessConfigs: []*compute.AccessConfig{ 214 | { 215 | Name: "nat", 216 | Type: "ONE_TO_ONE_NAT", 217 | }, 218 | }, 219 | }, 220 | }, 221 | MachineType: machineType, 222 | Disks: disks, 223 | Metadata: metadata, 224 | ServiceAccounts: []*compute.ServiceAccount{ 225 | { 226 | Email: "default", 227 | Scopes: scopes, 228 | }, 229 | }, 230 | } 231 | _, err := c.computeClient.Instances.Insert(c.config.Project, c.config.Zone, instance).Do() 232 | if err != nil { 233 | return nil, fmt.Errorf("error running instance: %v", err) 234 | } 235 | return &GCEInstance{ 236 | cloud: c, 237 | name: name, 238 | }, nil 239 | } 240 | 241 | // FindImage finds a registered image, matching by the name tag 242 | func (c *GCECloud) FindImage(imageName string) (Image, error) { 243 | image, err := findGCEImage(c.computeClient, c.config.Project, imageName) 244 | if err != nil { 245 | return nil, err 246 | } 247 | 248 | if image == nil { 249 | return nil, nil 250 | } 251 | 252 | return &GCEImage{ 253 | computeClient: c.computeClient, 254 | name: imageName, 255 | //image: image, 256 | }, nil 257 | } 258 | 259 | func findGCEImage(computeClient *compute.Service, project string, imageName string) (*compute.Image, error) { 260 | images, err := computeClient.Images.List(project).Filter("name eq " + imageName).Do() 261 | if err != nil { 262 | return nil, fmt.Errorf("error listing images: %v", err) 263 | } 264 | 265 | glog.V(2).Infof("GCE Images List Filter:Name=%q", imageName) 266 | 267 | if len(images.Items) == 0 { 268 | return nil, nil 269 | } 270 | 271 | if len(images.Items) != 1 { 272 | return nil, fmt.Errorf("found multiple matching images for name: %q", imageName) 273 | } 274 | 275 | return images.Items[0], nil 276 | } 277 | 278 | // GCEImage represents an image on GCE 279 | type GCEImage struct { 280 | computeClient *compute.Service 281 | name string 282 | } 283 | 284 | var _ Image = &GCEImage{} 285 | 286 | // String returns a string representation of the image 287 | func (i *GCEImage) String() string { 288 | return "GCEImage[" + i.name + "]" 289 | } 290 | 291 | // EnsurePublic makes the image accessible outside the current account 292 | func (i *GCEImage) EnsurePublic() error { 293 | return fmt.Errorf("GCE does not currently support public images") 294 | } 295 | 296 | // AddTags adds the specified tags on the image 297 | func (i *GCEImage) AddTags(tags map[string]string) error { 298 | return fmt.Errorf("Tagging of GCE images not yet implemented") 299 | } 300 | 301 | // ReplicateImage copies the image to all accessible GCE regions 302 | func (i *GCEImage) ReplicateImage(makePublic bool) (map[string]Image, error) { 303 | if makePublic { 304 | return nil, fmt.Errorf("GCE does not currently support public images") 305 | } 306 | 307 | images := make(map[string]Image) 308 | // All images are already global 309 | return images, nil 310 | } 311 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/template.go: -------------------------------------------------------------------------------- 1 | package imagebuilder 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "text/template" 7 | ) 8 | 9 | // ExpandTemplate executes a golang template 10 | func ExpandTemplate(key string, templateString string, context interface{}) (string, error) { 11 | t := template.New(key) 12 | 13 | funcMap := make(template.FuncMap) 14 | 15 | t.Funcs(funcMap) 16 | 17 | _, err := t.Parse(templateString) 18 | if err != nil { 19 | return "", fmt.Errorf("error parsing template %q: %v", key, err) 20 | } 21 | 22 | t.Option("missingkey=zero") 23 | 24 | var buffer bytes.Buffer 25 | err = t.ExecuteTemplate(&buffer, key, context) 26 | if err != nil { 27 | return "", fmt.Errorf("error executing template %q: %v", key, err) 28 | } 29 | 30 | return buffer.String(), nil 31 | } 32 | -------------------------------------------------------------------------------- /imagebuilder/pkg/imagebuilder/utils.go: -------------------------------------------------------------------------------- 1 | package imagebuilder 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | // ReadFile reads the whole file using ioutil.ReadFile, but does path expansion first 11 | func ReadFile(p string) ([]byte, error) { 12 | if strings.HasPrefix(p, "~/") { 13 | p = os.Getenv("HOME") + p[1:] 14 | } 15 | data, err := ioutil.ReadFile(p) 16 | if err != nil { 17 | return nil, fmt.Errorf("error reading file %q: %v", p, err) 18 | } 19 | return data, nil 20 | } 21 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.10-jessie.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.10-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.10-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.10 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # todo: switch to variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generally useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # We don't enable unattended upgrades - nodeup can always add it 147 | # but if we add it now, there's a race to turn it off 148 | # cloud-init depends on unattended-upgrades, so we can't just remove it 149 | # Instead we turn them off; we turn them on later 150 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 151 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 152 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 153 | 154 | # Remove dkms & other unneeded packages 155 | # TODO: running kernel removal needs removing-running-kernel preseed 156 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 157 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 158 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 159 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 160 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 161 | 162 | # Install docker 163 | - [ 'wget', 'http://download.docker.com/linux/debian/dists/jessie/pool/stable/amd64/docker-ce_17.03.2~ce-0~debian-jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 164 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "a7ac54aaa7d33122ca5f7a2df817cbefb5cdbfc7 docker.deb" | shasum -c -' ] 165 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 166 | - [ 'rm', '{root}/tmp/docker.deb' ] 167 | 168 | {{ if eq .Cloud "aws" }} 169 | # Fix a cloud-init bug where it uses nobootwait 170 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 171 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 172 | {{ end }} 173 | 174 | # We perform a full replacement of some grub conf variables: 175 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 176 | # GRUB_TIMEOUT (remove boot delay) 177 | # (but leave the old versions commented out for people to see) 178 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 179 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 180 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 181 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 182 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 183 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 184 | - [ 'chroot', '{root}', 'update-grub2' ] 185 | 186 | # Update everything to latest versions 187 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 188 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 189 | 190 | # Cleanup packages 191 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 192 | 193 | # Remove machine-id, so that we regenerate next boot 194 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 195 | 196 | # Ensure we have cleaned up all our SSH keys 197 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 198 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 199 | # Workaround bootstrap-vz bug where it errors if all keys are removed 200 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 201 | 202 | # journald requires machine-id, so add a PreStart 203 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 204 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 205 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 206 | 207 | # Make sure journald is persistent 208 | # From /usr/share/doc/systemd/README.Debian 209 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 210 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 211 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.10-stretch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.10-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.10-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.10 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # todo: switch to variant: minbase 25 | system: 26 | release: stretch 27 | architecture: amd64 28 | bootloader: grub 29 | charmap: UTF-8 30 | locale: en_US 31 | timezone: UTC 32 | volume: 33 | {{ if eq .Cloud "aws" }} 34 | backing: ebs 35 | {{ else if eq .Cloud "gce" }} 36 | backing: raw 37 | {{ end }} 38 | partitions: 39 | type: gpt 40 | root: 41 | filesystem: ext4 42 | # We create the FS with more inodes... docker is pretty inode hungry 43 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 44 | size: 8GiB 45 | packages: 46 | {{ if eq .Cloud "aws" }} 47 | mirror: http://cloudfront.debian.net/debian 48 | {{ end }} 49 | install: 50 | # Important utils for administration 51 | # if minbase - openssh-server 52 | 53 | # Ensure systemd scripts run on shutdown 54 | - acpi-support 55 | 56 | # these packages are generally useful 57 | # (and are the ones from the GCE image) 58 | - rsync 59 | - screen 60 | - vim 61 | 62 | # needed for docker 63 | - iptables 64 | - libapparmor1 65 | - libltdl7 66 | 67 | # Handy utilities 68 | - htop 69 | - tcpdump 70 | - iotop 71 | - ethtool 72 | - sysstat 73 | 74 | # needed for setfacl below 75 | - acl 76 | 77 | {{ if eq .Cloud "aws" }} 78 | # these packages are included in the official AWS image 79 | - python-boto 80 | - python3-boto 81 | - apt-transport-https 82 | - lvm2 83 | - ncurses-term 84 | - parted 85 | - cloud-init 86 | - cloud-utils 87 | - gdisk 88 | - systemd 89 | - systemd-sysv 90 | 91 | # these packages are included in the official image, but we remove them 92 | # awscli : we install from pip instead 93 | {{ end }} 94 | 95 | # These packages would otherwise be installed during first boot 96 | - aufs-tools 97 | - curl 98 | - python-yaml 99 | - git 100 | - nfs-common 101 | - bridge-utils 102 | - logrotate 103 | - socat 104 | - python-apt 105 | - apt-transport-https 106 | - unattended-upgrades 107 | - lvm2 108 | - btrfs-tools 109 | 110 | {{ if eq .Cloud "aws" }} 111 | # So we can install the latest awscli 112 | - python-pip 113 | {{ end }} 114 | 115 | plugins: 116 | {{ if eq .Cloud "gce" }} 117 | ntp: 118 | servers: 119 | - metadata.google.internal 120 | {{ else }} 121 | ntp: {} 122 | {{ end }} 123 | 124 | {{ if eq .Cloud "aws" }} 125 | cloud_init: 126 | metadata_sources: Ec2 127 | username: admin 128 | enable_modules: 129 | cloud_init_modules: 130 | - {module: growpart, position: 4} 131 | {{ end }} 132 | 133 | commands: 134 | commands: 135 | {{ if eq .Cloud "aws" }} 136 | # Install awscli through python-pip 137 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 138 | {{ end }} 139 | 140 | # We don't enable unattended upgrades - nodeup can always add it 141 | # but if we add it now, there's a race to turn it off 142 | # cloud-init depends on unattended-upgrades, so we can't just remove it 143 | # Instead we turn them off; we turn them on later 144 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 145 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 146 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 147 | 148 | # Install docker 149 | - [ 'wget', 'http://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce_17.03.2~ce-0~debian-stretch_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 150 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "36773361cf44817371770cb4e6e6823590d10297 docker.deb" | shasum -c -' ] 151 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 152 | - [ 'rm', '{root}/tmp/docker.deb' ] 153 | 154 | # We perform a full replacement of some grub conf variables: 155 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 156 | # GRUB_TIMEOUT (remove boot delay) 157 | # (but leave the old versions commented out for people to see) 158 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 159 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 160 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 161 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 162 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0 nvme_core.io_timeout=255\"" >> /etc/default/grub' ] 163 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 164 | - [ 'chroot', '{root}', 'update-grub2' ] 165 | 166 | # Update everything to latest versions 167 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 168 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 169 | 170 | # Cleanup packages 171 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 172 | 173 | # Remove machine-id, so that we regenerate next boot 174 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "" > /etc/machine-id' ] 175 | 176 | # Ensure we have cleaned up all our SSH keys 177 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 178 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 179 | # Workaround bootstrap-vz bug where it errors if all keys are removed 180 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 181 | 182 | # journald requires machine-id, so add a PreStart 183 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 184 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 185 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 186 | 187 | # Make sure journald is persistent 188 | # From /usr/share/doc/systemd/README.Debian 189 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 190 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 191 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.11-jessie.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.11-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.11-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.11 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # todo: switch to variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generally useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # We don't enable unattended upgrades - nodeup can always add it 147 | # but if we add it now, there's a race to turn it off 148 | # cloud-init depends on unattended-upgrades, so we can't just remove it 149 | # Instead we turn them off; we turn them on later 150 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 151 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 152 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 153 | 154 | # Remove dkms & other unneeded packages 155 | # TODO: running kernel removal needs removing-running-kernel preseed 156 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 157 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 158 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 159 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 160 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 161 | 162 | # Install docker 163 | - [ 'wget', 'http://download.docker.com/linux/debian/dists/jessie/pool/stable/amd64/docker-ce_17.03.2~ce-0~debian-jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 164 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "a7ac54aaa7d33122ca5f7a2df817cbefb5cdbfc7 docker.deb" | shasum -c -' ] 165 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 166 | - [ 'rm', '{root}/tmp/docker.deb' ] 167 | 168 | {{ if eq .Cloud "aws" }} 169 | # Fix a cloud-init bug where it uses nobootwait 170 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 171 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 172 | {{ end }} 173 | 174 | # We perform a full replacement of some grub conf variables: 175 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 176 | # GRUB_TIMEOUT (remove boot delay) 177 | # (but leave the old versions commented out for people to see) 178 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 179 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 180 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 181 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 182 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 183 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 184 | - [ 'chroot', '{root}', 'update-grub2' ] 185 | 186 | # Update everything to latest versions 187 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 188 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 189 | 190 | # Cleanup packages 191 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 192 | 193 | # Remove machine-id, so that we regenerate next boot 194 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 195 | 196 | # Ensure we have cleaned up all our SSH keys 197 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 198 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 199 | # Workaround bootstrap-vz bug where it errors if all keys are removed 200 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 201 | 202 | # journald requires machine-id, so add a PreStart 203 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 204 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 205 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 206 | 207 | # Make sure journald is persistent 208 | # From /usr/share/doc/systemd/README.Debian 209 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 210 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 211 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.11-stretch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.11-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.11-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.11 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # todo: switch to variant: minbase 25 | system: 26 | release: stretch 27 | architecture: amd64 28 | bootloader: grub 29 | charmap: UTF-8 30 | locale: en_US 31 | timezone: UTC 32 | volume: 33 | {{ if eq .Cloud "aws" }} 34 | backing: ebs 35 | {{ else if eq .Cloud "gce" }} 36 | backing: raw 37 | {{ end }} 38 | partitions: 39 | type: gpt 40 | root: 41 | filesystem: ext4 42 | # We create the FS with more inodes... docker is pretty inode hungry 43 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 44 | size: 8GiB 45 | packages: 46 | {{ if eq .Cloud "aws" }} 47 | mirror: http://cloudfront.debian.net/debian 48 | {{ end }} 49 | install: 50 | # Important utils for administration 51 | # if minbase - openssh-server 52 | 53 | # Ensure systemd scripts run on shutdown 54 | - acpi-support 55 | 56 | # these packages are generally useful 57 | # (and are the ones from the GCE image) 58 | - rsync 59 | - screen 60 | - vim 61 | 62 | # needed for docker 63 | - iptables 64 | - libapparmor1 65 | - libltdl7 66 | 67 | # Handy utilities 68 | - htop 69 | - tcpdump 70 | - iotop 71 | - ethtool 72 | - sysstat 73 | 74 | # needed for setfacl below 75 | - acl 76 | 77 | {{ if eq .Cloud "aws" }} 78 | # these packages are included in the official AWS image 79 | - python-boto 80 | - python3-boto 81 | - apt-transport-https 82 | - lvm2 83 | - ncurses-term 84 | - parted 85 | - cloud-init 86 | - cloud-utils 87 | - gdisk 88 | - systemd 89 | - systemd-sysv 90 | 91 | # these packages are included in the official image, but we remove them 92 | # awscli : we install from pip instead 93 | {{ end }} 94 | 95 | # These packages would otherwise be installed during first boot 96 | - aufs-tools 97 | - curl 98 | - python-yaml 99 | - git 100 | - nfs-common 101 | - bridge-utils 102 | - logrotate 103 | - socat 104 | - python-apt 105 | - apt-transport-https 106 | - unattended-upgrades 107 | - lvm2 108 | - btrfs-tools 109 | 110 | {{ if eq .Cloud "aws" }} 111 | # So we can install the latest awscli 112 | - python-pip 113 | {{ end }} 114 | 115 | plugins: 116 | {{ if eq .Cloud "gce" }} 117 | ntp: 118 | servers: 119 | - metadata.google.internal 120 | {{ else }} 121 | ntp: {} 122 | {{ end }} 123 | 124 | {{ if eq .Cloud "aws" }} 125 | cloud_init: 126 | metadata_sources: Ec2 127 | username: admin 128 | enable_modules: 129 | cloud_init_modules: 130 | - {module: growpart, position: 4} 131 | {{ end }} 132 | 133 | commands: 134 | commands: 135 | {{ if eq .Cloud "aws" }} 136 | # Install awscli through python-pip 137 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 138 | {{ end }} 139 | 140 | # We don't enable unattended upgrades - nodeup can always add it 141 | # but if we add it now, there's a race to turn it off 142 | # cloud-init depends on unattended-upgrades, so we can't just remove it 143 | # Instead we turn them off; we turn them on later 144 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 145 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 146 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 147 | 148 | # Install docker 149 | - [ 'wget', 'http://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce_17.03.2~ce-0~debian-stretch_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 150 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "36773361cf44817371770cb4e6e6823590d10297 docker.deb" | shasum -c -' ] 151 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 152 | - [ 'rm', '{root}/tmp/docker.deb' ] 153 | 154 | # We perform a full replacement of some grub conf variables: 155 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 156 | # GRUB_TIMEOUT (remove boot delay) 157 | # (but leave the old versions commented out for people to see) 158 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 159 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 160 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 161 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 162 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0 nvme_core.io_timeout=255\"" >> /etc/default/grub' ] 163 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 164 | - [ 'chroot', '{root}', 'update-grub2' ] 165 | 166 | # Update everything to latest versions 167 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 168 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 169 | 170 | # Cleanup packages 171 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 172 | 173 | # Remove machine-id, so that we regenerate next boot 174 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "" > /etc/machine-id' ] 175 | 176 | # Ensure we have cleaned up all our SSH keys 177 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 178 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 179 | # Workaround bootstrap-vz bug where it errors if all keys are removed 180 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 181 | 182 | # journald requires machine-id, so add a PreStart 183 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 184 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 185 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 186 | 187 | # Make sure journald is persistent 188 | # From /usr/share/doc/systemd/README.Debian 189 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 190 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 191 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.12-stretch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.12-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.12-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.12 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # todo: switch to variant: minbase 25 | system: 26 | release: stretch 27 | architecture: amd64 28 | bootloader: grub 29 | charmap: UTF-8 30 | locale: en_US 31 | timezone: UTC 32 | volume: 33 | {{ if eq .Cloud "aws" }} 34 | backing: ebs 35 | {{ else if eq .Cloud "gce" }} 36 | backing: raw 37 | {{ end }} 38 | partitions: 39 | type: gpt 40 | root: 41 | filesystem: ext4 42 | # We create the FS with more inodes... docker is pretty inode hungry 43 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 44 | size: 8GiB 45 | packages: 46 | {{ if eq .Cloud "aws" }} 47 | mirror: http://cloudfront.debian.net/debian 48 | {{ end }} 49 | install: 50 | # Important utils for administration 51 | # if minbase - openssh-server 52 | 53 | # Ensure systemd scripts run on shutdown 54 | - acpi-support 55 | 56 | # these packages are generally useful 57 | # (and are the ones from the GCE image) 58 | - rsync 59 | - screen 60 | - vim 61 | 62 | # needed for docker 63 | - iptables 64 | - libapparmor1 65 | - libltdl7 66 | 67 | # Handy utilities 68 | - htop 69 | - tcpdump 70 | - iotop 71 | - ethtool 72 | - sysstat 73 | 74 | # needed for setfacl below 75 | - acl 76 | 77 | {{ if eq .Cloud "aws" }} 78 | # these packages are included in the official AWS image 79 | - python-boto 80 | - python3-boto 81 | - apt-transport-https 82 | - lvm2 83 | - ncurses-term 84 | - parted 85 | - cloud-init 86 | - cloud-utils 87 | - gdisk 88 | - systemd 89 | - systemd-sysv 90 | 91 | # these packages are included in the official image, but we remove them 92 | # awscli : we install from pip instead 93 | {{ end }} 94 | 95 | # These packages would otherwise be installed during first boot 96 | - aufs-tools 97 | - curl 98 | - python-yaml 99 | - git 100 | - nfs-common 101 | - bridge-utils 102 | - logrotate 103 | - socat 104 | - python-apt 105 | - apt-transport-https 106 | - unattended-upgrades 107 | - lvm2 108 | - btrfs-tools 109 | 110 | {{ if eq .Cloud "aws" }} 111 | # So we can install the latest awscli 112 | - python-pip 113 | {{ end }} 114 | 115 | plugins: 116 | {{ if eq .Cloud "gce" }} 117 | ntp: 118 | servers: 119 | - metadata.google.internal 120 | {{ else }} 121 | ntp: {} 122 | {{ end }} 123 | 124 | {{ if eq .Cloud "aws" }} 125 | cloud_init: 126 | metadata_sources: Ec2 127 | username: admin 128 | enable_modules: 129 | cloud_init_modules: 130 | - {module: growpart, position: 4} 131 | {{ end }} 132 | 133 | commands: 134 | commands: 135 | {{ if eq .Cloud "aws" }} 136 | # Install awscli through python-pip 137 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 138 | {{ end }} 139 | 140 | # We don't enable unattended upgrades - nodeup can always add it 141 | # but if we add it now, there's a race to turn it off 142 | # cloud-init depends on unattended-upgrades, so we can't just remove it 143 | # Instead we turn them off; we turn them on later 144 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 145 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 146 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 147 | 148 | # Install docker 149 | - [ 'wget', 'https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce_18.06.3~ce~3-0~debian_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 150 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "93b5a055a39462867d79109b00db1367e3d9e32f docker.deb" | shasum -c -' ] 151 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 152 | - [ 'rm', '{root}/tmp/docker.deb' ] 153 | 154 | # We perform a full replacement of some grub conf variables: 155 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 156 | # GRUB_TIMEOUT (remove boot delay) 157 | # (but leave the old versions commented out for people to see) 158 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 159 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 160 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 161 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 162 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0 nvme_core.io_timeout=255\"" >> /etc/default/grub' ] 163 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 164 | - [ 'chroot', '{root}', 'update-grub2' ] 165 | 166 | # Update everything to latest versions 167 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 168 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 169 | 170 | # Cleanup packages 171 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 172 | 173 | # Remove machine-id, so that we regenerate next boot 174 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "" > /etc/machine-id' ] 175 | 176 | # Ensure we have cleaned up all our SSH keys 177 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 178 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 179 | # Workaround bootstrap-vz bug where it errors if all keys are removed 180 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 181 | 182 | # journald requires machine-id, so add a PreStart 183 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 184 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 185 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 186 | 187 | # Make sure journald is persistent 188 | # From /usr/share/doc/systemd/README.Debian 189 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 190 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 191 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.2-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.2-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.2 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | system: 25 | release: jessie 26 | architecture: amd64 27 | # We use grub, not extlinux. 28 | # See https://github.com/andsens/bootstrap-vz/issues/182 29 | # extlinux makes it harder to modify boot args, and may have reboot problems 30 | # bootloader: extlinux 31 | bootloader: grub 32 | charmap: UTF-8 33 | locale: en_US 34 | timezone: UTC 35 | volume: 36 | {{ if eq .Cloud "aws" }} 37 | backing: ebs 38 | {{ else if eq .Cloud "gce" }} 39 | backing: raw 40 | {{ end }} 41 | partitions: 42 | type: msdos 43 | root: 44 | filesystem: ext4 45 | size: 8GiB 46 | packages: 47 | {{ if eq .Cloud "aws" }} 48 | mirror: http://cloudfront.debian.net/debian 49 | {{ end }} 50 | install: 51 | # these packages are generaly useful 52 | # (and are the ones from the GCE image) 53 | - rsync 54 | - screen 55 | - vim 56 | {{ if eq .Cloud "aws" }} 57 | # these packages are included in the official AWS image 58 | - python-boto 59 | - python3-boto 60 | - apt-transport-https 61 | - lvm2 62 | - ncurses-term 63 | - parted 64 | - bootlogd 65 | - cloud-init 66 | - cloud-utils 67 | - gdisk 68 | - sysvinit 69 | - systemd 70 | - systemd-sysv 71 | 72 | # these packages are included in the official image, but we remove them 73 | # awscli : we install from pip instead 74 | {{ end }} 75 | 76 | # These packages would otherwise be installed during first boot 77 | - aufs-tools 78 | - curl 79 | - python-yaml 80 | - git 81 | - nfs-common 82 | - bridge-utils 83 | - logrotate 84 | - socat 85 | - python-apt 86 | - apt-transport-https 87 | - unattended-upgrades 88 | - lvm2 89 | - btrfs-tools 90 | 91 | {{ if eq .Cloud "aws" }} 92 | # cloud-initramfs-growroot will resize the master partition on boot 93 | - cloud-initramfs-growroot 94 | 95 | # So we can install the latest awscli 96 | - python-pip 97 | {{ end }} 98 | 99 | plugins: 100 | {{ if eq .Cloud "gce" }} 101 | ntp: 102 | servers: 103 | - metadata.google.internal 104 | {{ else }} 105 | ntp: {} 106 | {{ end }} 107 | 108 | {{ if eq .Cloud "aws" }} 109 | cloud_init: 110 | metadata_sources: Ec2 111 | username: admin 112 | {{ end }} 113 | 114 | commands: 115 | commands: 116 | {{ if eq .Cloud "aws" }} 117 | # Install awscli through python-pip 118 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 119 | {{ end }} 120 | 121 | # Install docker 122 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.9.1-0~jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 123 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "c58c39008fd6399177f6b2491222e4438f518d78 docker.deb" | shasum -c -' ] 124 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --assume-yes libapparmor1' ] 125 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 126 | - [ 'rm', '{root}/tmp/docker.deb' ] 127 | 128 | {{ if eq .Cloud "aws" }} 129 | # Fix a cloud-init bug where it uses nobootwait 130 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 131 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 132 | {{ end }} 133 | 134 | # We perform a full replacement of some grub conf variables: 135 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 136 | # GRUB_TIMEOUT (remove boot delay) 137 | # (but leave the old versions commented out for people to see) 138 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 139 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 140 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 141 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 143 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 144 | - [ 'chroot', '{root}', 'update-grub2' ] 145 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.3-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.3-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.3 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | system: 25 | release: jessie 26 | architecture: amd64 27 | # We use grub, not extlinux. 28 | # See https://github.com/andsens/bootstrap-vz/issues/182 29 | # extlinux makes it harder to modify boot args, and may have reboot problems 30 | # bootloader: extlinux 31 | bootloader: grub 32 | charmap: UTF-8 33 | locale: en_US 34 | timezone: UTC 35 | volume: 36 | {{ if eq .Cloud "aws" }} 37 | backing: ebs 38 | {{ else if eq .Cloud "gce" }} 39 | backing: raw 40 | {{ end }} 41 | partitions: 42 | type: msdos 43 | root: 44 | filesystem: ext4 45 | size: 8GiB 46 | packages: 47 | {{ if eq .Cloud "aws" }} 48 | mirror: http://cloudfront.debian.net/debian 49 | {{ end }} 50 | install: 51 | # these packages are generaly useful 52 | # (and are the ones from the GCE image) 53 | - rsync 54 | - screen 55 | - vim 56 | {{ if eq .Cloud "aws" }} 57 | # these packages are included in the official AWS image 58 | - python-boto 59 | - python3-boto 60 | - apt-transport-https 61 | - lvm2 62 | - ncurses-term 63 | - parted 64 | - bootlogd 65 | - cloud-init 66 | - cloud-utils 67 | - gdisk 68 | - sysvinit 69 | - systemd 70 | - systemd-sysv 71 | 72 | # these packages are included in the official image, but we remove them 73 | # awscli : we install from pip instead 74 | {{ end }} 75 | 76 | # These packages would otherwise be installed during first boot 77 | - aufs-tools 78 | - curl 79 | - python-yaml 80 | - git 81 | - nfs-common 82 | - bridge-utils 83 | - logrotate 84 | - socat 85 | - python-apt 86 | - apt-transport-https 87 | - unattended-upgrades 88 | - lvm2 89 | - btrfs-tools 90 | 91 | {{ if eq .Cloud "aws" }} 92 | # cloud-initramfs-growroot will resize the master partition on boot 93 | - cloud-initramfs-growroot 94 | 95 | # So we can install the latest awscli 96 | - python-pip 97 | {{ end }} 98 | 99 | plugins: 100 | {{ if eq .Cloud "gce" }} 101 | ntp: 102 | servers: 103 | - metadata.google.internal 104 | {{ else }} 105 | ntp: {} 106 | {{ end }} 107 | 108 | {{ if eq .Cloud "aws" }} 109 | cloud_init: 110 | metadata_sources: Ec2 111 | username: admin 112 | {{ end }} 113 | 114 | commands: 115 | commands: 116 | {{ if eq .Cloud "aws" }} 117 | # Install awscli through python-pip 118 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 119 | {{ end }} 120 | 121 | # Install docker 122 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.11.2-0~jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 123 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "c312f1f6fa0b34df4589bb812e4f7af8e28fd51d docker.deb" | shasum -c -' ] 124 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --assume-yes libapparmor1 libltdl7' ] 125 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 126 | - [ 'rm', '{root}/tmp/docker.deb' ] 127 | 128 | {{ if eq .Cloud "aws" }} 129 | # Fix a cloud-init bug where it uses nobootwait 130 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 131 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 132 | {{ end }} 133 | 134 | # We perform a full replacement of some grub conf variables: 135 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 136 | # GRUB_TIMEOUT (remove boot delay) 137 | # (but leave the old versions commented out for people to see) 138 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 139 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 140 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 141 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 143 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 144 | - [ 'chroot', '{root}', 'update-grub2' ] 145 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.4.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.4-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.4-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.4 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.5? variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generaly useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # Remove dkms ixgbevf driver 147 | - [ 'chroot', '{root}', 'dkms', 'remove', 'ixgbevf/2.16.1', '--all' ] 148 | 149 | # We don't enable unattended upgrades - nodeup can always add it 150 | # but if we add it now, there's a race to turn it off 151 | # cloud-init depends on unattended-upgrades, so we can't just remove it 152 | # Instead we turn them off; we turn them on later 153 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 154 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 155 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 156 | 157 | # Remove dkms & other unneeded packages 158 | # TODO: running kernel removal needs removing-running-kernel preseed 159 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 160 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 161 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 162 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 163 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 164 | 165 | # Install docker 166 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.11.2-0~jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 167 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "c312f1f6fa0b34df4589bb812e4f7af8e28fd51d docker.deb" | shasum -c -' ] 168 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 169 | - [ 'rm', '{root}/tmp/docker.deb' ] 170 | 171 | {{ if eq .Cloud "aws" }} 172 | # Fix a cloud-init bug where it uses nobootwait 173 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 174 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 175 | {{ end }} 176 | 177 | # We perform a full replacement of some grub conf variables: 178 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 179 | # GRUB_TIMEOUT (remove boot delay) 180 | # (but leave the old versions commented out for people to see) 181 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 182 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 183 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 184 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 185 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 186 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 187 | - [ 'chroot', '{root}', 'update-grub2' ] 188 | 189 | # Update everything to latest versions 190 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 191 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 192 | 193 | # Cleanup packages 194 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 195 | 196 | # Remove machine-id, so that we regenerate next boot 197 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 198 | 199 | # journald requires machine-id, so add a PreStart 200 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 201 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 202 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 203 | 204 | # Make sure journald is persistent 205 | # From /usr/share/doc/systemd/README.Debian 206 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 207 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 208 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.5.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.5-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.5-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.5 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.5? variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generaly useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # Remove dkms ixgbevf driver 147 | - [ 'chroot', '{root}', 'dkms', 'remove', 'ixgbevf/2.16.1', '--all' ] 148 | 149 | # We don't enable unattended upgrades - nodeup can always add it 150 | # but if we add it now, there's a race to turn it off 151 | # cloud-init depends on unattended-upgrades, so we can't just remove it 152 | # Instead we turn them off; we turn them on later 153 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 154 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 155 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 156 | 157 | # Remove dkms & other unneeded packages 158 | # TODO: running kernel removal needs removing-running-kernel preseed 159 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 160 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 161 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 162 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 163 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 164 | 165 | # Install docker 166 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.12.3-0~jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 167 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "7c7eb45542b67a9cfb33c292ba245710efb5d773 docker.deb" | shasum -c -' ] 168 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 169 | - [ 'rm', '{root}/tmp/docker.deb' ] 170 | 171 | {{ if eq .Cloud "aws" }} 172 | # Fix a cloud-init bug where it uses nobootwait 173 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 174 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 175 | {{ end }} 176 | 177 | # We perform a full replacement of some grub conf variables: 178 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 179 | # GRUB_TIMEOUT (remove boot delay) 180 | # (but leave the old versions commented out for people to see) 181 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 182 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 183 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 184 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 185 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 186 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 187 | - [ 'chroot', '{root}', 'update-grub2' ] 188 | 189 | # Update everything to latest versions 190 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 191 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 192 | 193 | # Cleanup packages 194 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 195 | 196 | # Remove machine-id, so that we regenerate next boot 197 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 198 | 199 | # journald requires machine-id, so add a PreStart 200 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 201 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 202 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 203 | 204 | # Make sure journald is persistent 205 | # From /usr/share/doc/systemd/README.Debian 206 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 207 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 208 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.6.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.6-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.6-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.6 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.7? variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generaly useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # Remove dkms ixgbevf driver 147 | - [ 'chroot', '{root}', 'dkms', 'status' ] 148 | - [ 'chroot', '{root}', 'dkms', 'remove', 'ixgbevf/2.16.1', '--all' ] 149 | 150 | # We don't enable unattended upgrades - nodeup can always add it 151 | # but if we add it now, there's a race to turn it off 152 | # cloud-init depends on unattended-upgrades, so we can't just remove it 153 | # Instead we turn them off; we turn them on later 154 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 155 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 156 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 157 | 158 | # Remove dkms & other unneeded packages 159 | # TODO: running kernel removal needs removing-running-kernel preseed 160 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 161 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 162 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 163 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 164 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 165 | 166 | # Install docker 167 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.12.6-0~debian-jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 168 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "1a8b0c4e3386e12964676a126d284cebf599cc8e docker.deb" | shasum -c -' ] 169 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 170 | - [ 'rm', '{root}/tmp/docker.deb' ] 171 | 172 | {{ if eq .Cloud "aws" }} 173 | # Fix a cloud-init bug where it uses nobootwait 174 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 175 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 176 | {{ end }} 177 | 178 | # We perform a full replacement of some grub conf variables: 179 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 180 | # GRUB_TIMEOUT (remove boot delay) 181 | # (but leave the old versions commented out for people to see) 182 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 183 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 184 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 185 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 186 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 187 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 188 | - [ 'chroot', '{root}', 'update-grub2' ] 189 | 190 | # Update everything to latest versions 191 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 192 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 193 | 194 | # Cleanup packages 195 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 196 | 197 | # Remove machine-id, so that we regenerate next boot 198 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 199 | 200 | # journald requires machine-id, so add a PreStart 201 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 202 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 203 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 204 | 205 | # Make sure journald is persistent 206 | # From /usr/share/doc/systemd/README.Debian 207 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 208 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 209 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.7.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.7-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.7-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.7 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.8? variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generally useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # Remove supplied dkms ixgbevf driver so we fall back to more recent in kernel driver (despite lower version number) 147 | - [ 'chroot', '{root}', 'dkms', 'status' ] 148 | - [ 'chroot', '{root}', 'dkms', 'remove', 'ixgbevf/2.16.1', '--all' ] 149 | 150 | # We don't enable unattended upgrades - nodeup can always add it 151 | # but if we add it now, there's a race to turn it off 152 | # cloud-init depends on unattended-upgrades, so we can't just remove it 153 | # Instead we turn them off; we turn them on later 154 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 155 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 156 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 157 | 158 | # Remove dkms & other unneeded packages 159 | # TODO: running kernel removal needs removing-running-kernel preseed 160 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 161 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 162 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 163 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 164 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 165 | 166 | # Install docker 167 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.12.6-0~debian-jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 168 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "1a8b0c4e3386e12964676a126d284cebf599cc8e docker.deb" | shasum -c -' ] 169 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 170 | - [ 'rm', '{root}/tmp/docker.deb' ] 171 | 172 | {{ if eq .Cloud "aws" }} 173 | # Fix a cloud-init bug where it uses nobootwait 174 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 175 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 176 | {{ end }} 177 | 178 | # We perform a full replacement of some grub conf variables: 179 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 180 | # GRUB_TIMEOUT (remove boot delay) 181 | # (but leave the old versions commented out for people to see) 182 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 183 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 184 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 185 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 186 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 187 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 188 | - [ 'chroot', '{root}', 'update-grub2' ] 189 | 190 | # Update everything to latest versions 191 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 192 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 193 | 194 | # Cleanup packages 195 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 196 | 197 | # Remove machine-id, so that we regenerate next boot 198 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 199 | 200 | # journald requires machine-id, so add a PreStart 201 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 202 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 203 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 204 | 205 | # Make sure journald is persistent 206 | # From /usr/share/doc/systemd/README.Debian 207 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 208 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 209 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.8-jessie.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.8-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.8-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.8 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.8? variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generally useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # We don't enable unattended upgrades - nodeup can always add it 147 | # but if we add it now, there's a race to turn it off 148 | # cloud-init depends on unattended-upgrades, so we can't just remove it 149 | # Instead we turn them off; we turn them on later 150 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 151 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 152 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 153 | 154 | # Remove dkms & other unneeded packages 155 | # TODO: running kernel removal needs removing-running-kernel preseed 156 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 157 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 158 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 159 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 160 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 161 | 162 | # Install docker 163 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.13.1-0~debian-jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 164 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "1d3370549e32ea13b2755b2db8dbc82b2b787ece docker.deb" | shasum -c -' ] 165 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 166 | - [ 'rm', '{root}/tmp/docker.deb' ] 167 | 168 | {{ if eq .Cloud "aws" }} 169 | # Fix a cloud-init bug where it uses nobootwait 170 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 171 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 172 | {{ end }} 173 | 174 | # We perform a full replacement of some grub conf variables: 175 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 176 | # GRUB_TIMEOUT (remove boot delay) 177 | # (but leave the old versions commented out for people to see) 178 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 179 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 180 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 181 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 182 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 183 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 184 | - [ 'chroot', '{root}', 'update-grub2' ] 185 | 186 | # Update everything to latest versions 187 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 188 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 189 | 190 | # Cleanup packages 191 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 192 | 193 | # Remove machine-id, so that we regenerate next boot 194 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 195 | 196 | # Ensure we have cleaned up all our SSH keys 197 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 198 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 199 | # Workaround bootstrap-vz bug where it errors if all keys are removed 200 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 201 | 202 | # journald requires machine-id, so add a PreStart 203 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 204 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 205 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 206 | 207 | # Make sure journald is persistent 208 | # From /usr/share/doc/systemd/README.Debian 209 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 210 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 211 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.8-stretch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.8-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.8-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.8 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.8? variant: minbase 25 | system: 26 | release: stretch 27 | architecture: amd64 28 | bootloader: grub 29 | charmap: UTF-8 30 | locale: en_US 31 | timezone: UTC 32 | volume: 33 | {{ if eq .Cloud "aws" }} 34 | backing: ebs 35 | {{ else if eq .Cloud "gce" }} 36 | backing: raw 37 | {{ end }} 38 | partitions: 39 | type: gpt 40 | root: 41 | filesystem: ext4 42 | # We create the FS with more inodes... docker is pretty inode hungry 43 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 44 | size: 8GiB 45 | packages: 46 | {{ if eq .Cloud "aws" }} 47 | mirror: http://cloudfront.debian.net/debian 48 | {{ end }} 49 | install: 50 | # Important utils for administration 51 | # if minbase - openssh-server 52 | 53 | # these packages are generally useful 54 | # (and are the ones from the GCE image) 55 | - rsync 56 | - screen 57 | - vim 58 | 59 | # needed for docker 60 | - iptables 61 | - libapparmor1 62 | - libltdl7 63 | 64 | # Handy utilities 65 | - htop 66 | - tcpdump 67 | - iotop 68 | - ethtool 69 | - sysstat 70 | 71 | # needed for setfacl below 72 | - acl 73 | 74 | {{ if eq .Cloud "aws" }} 75 | # these packages are included in the official AWS image 76 | - python-boto 77 | - python3-boto 78 | - apt-transport-https 79 | - lvm2 80 | - ncurses-term 81 | - parted 82 | - cloud-init 83 | - cloud-utils 84 | - gdisk 85 | - systemd 86 | - systemd-sysv 87 | 88 | # these packages are included in the official image, but we remove them 89 | # awscli : we install from pip instead 90 | {{ end }} 91 | 92 | # These packages would otherwise be installed during first boot 93 | - aufs-tools 94 | - curl 95 | - python-yaml 96 | - git 97 | - nfs-common 98 | - bridge-utils 99 | - logrotate 100 | - socat 101 | - python-apt 102 | - apt-transport-https 103 | - unattended-upgrades 104 | - lvm2 105 | - btrfs-tools 106 | 107 | {{ if eq .Cloud "aws" }} 108 | # So we can install the latest awscli 109 | - python-pip 110 | {{ end }} 111 | 112 | plugins: 113 | {{ if eq .Cloud "gce" }} 114 | ntp: 115 | servers: 116 | - metadata.google.internal 117 | {{ else }} 118 | ntp: {} 119 | {{ end }} 120 | 121 | {{ if eq .Cloud "aws" }} 122 | cloud_init: 123 | metadata_sources: Ec2 124 | username: admin 125 | enable_modules: 126 | cloud_init_modules: 127 | - {module: growpart, position: 4} 128 | {{ end }} 129 | 130 | commands: 131 | commands: 132 | {{ if eq .Cloud "aws" }} 133 | # Install awscli through python-pip 134 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 135 | {{ end }} 136 | 137 | # We don't enable unattended upgrades - nodeup can always add it 138 | # but if we add it now, there's a race to turn it off 139 | # cloud-init depends on unattended-upgrades, so we can't just remove it 140 | # Instead we turn them off; we turn them on later 141 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 143 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 144 | 145 | # Install docker 146 | - [ 'wget', 'http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.13.1-0~debian-jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 147 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "1d3370549e32ea13b2755b2db8dbc82b2b787ece docker.deb" | shasum -c -' ] 148 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 149 | - [ 'rm', '{root}/tmp/docker.deb' ] 150 | 151 | # We perform a full replacement of some grub conf variables: 152 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 153 | # GRUB_TIMEOUT (remove boot delay) 154 | # (but leave the old versions commented out for people to see) 155 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 156 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 157 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 158 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 159 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0 nvme_core.io_timeout=255\"" >> /etc/default/grub' ] 160 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 161 | - [ 'chroot', '{root}', 'update-grub2' ] 162 | 163 | # Update everything to latest versions 164 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 165 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 166 | 167 | # Cleanup packages 168 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 169 | 170 | # Remove machine-id, so that we regenerate next boot 171 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "" > /etc/machine-id' ] 172 | 173 | # Ensure we have cleaned up all our SSH keys 174 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 175 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 176 | # Workaround bootstrap-vz bug where it errors if all keys are removed 177 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 178 | 179 | # journald requires machine-id, so add a PreStart 180 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 181 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 182 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 183 | 184 | # Make sure journald is persistent 185 | # From /usr/share/doc/systemd/README.Debian 186 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 187 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 188 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.9-jessie.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.9-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.9-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.9 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.9? variant: minbase 25 | system: 26 | release: jessie 27 | architecture: amd64 28 | # We use grub, not extlinux. 29 | # See https://github.com/andsens/bootstrap-vz/issues/182 30 | # extlinux makes it harder to modify boot args, and may have reboot problems 31 | # bootloader: extlinux 32 | bootloader: grub 33 | charmap: UTF-8 34 | locale: en_US 35 | timezone: UTC 36 | volume: 37 | {{ if eq .Cloud "aws" }} 38 | backing: ebs 39 | {{ else if eq .Cloud "gce" }} 40 | backing: raw 41 | {{ end }} 42 | partitions: 43 | type: msdos 44 | root: 45 | filesystem: ext4 46 | # We create the FS with more inodes... docker is pretty inode hungry 47 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 48 | size: 8GiB 49 | packages: 50 | {{ if eq .Cloud "aws" }} 51 | mirror: http://cloudfront.debian.net/debian 52 | {{ end }} 53 | install: 54 | # Important utils for administration 55 | # if minbase - openssh-server 56 | 57 | # these packages are generally useful 58 | # (and are the ones from the GCE image) 59 | - rsync 60 | - screen 61 | - vim 62 | 63 | # needed for docker 64 | - iptables 65 | - libapparmor1 66 | - libltdl7 67 | 68 | {{ if eq .Cloud "aws" }} 69 | # these packages are included in the official AWS image 70 | - python-boto 71 | - python3-boto 72 | - apt-transport-https 73 | - lvm2 74 | - ncurses-term 75 | - parted 76 | - bootlogd 77 | - cloud-init 78 | - cloud-utils 79 | - gdisk 80 | - sysvinit 81 | - systemd 82 | - systemd-sysv 83 | - htop 84 | - tcpdump 85 | - iotop 86 | - ethtool 87 | - sysstat 88 | 89 | # these packages are included in the official image, but we remove them 90 | # awscli : we install from pip instead 91 | {{ end }} 92 | 93 | # These packages would otherwise be installed during first boot 94 | - aufs-tools 95 | - curl 96 | - python-yaml 97 | - git 98 | - nfs-common 99 | - bridge-utils 100 | - logrotate 101 | - socat 102 | - python-apt 103 | - apt-transport-https 104 | - unattended-upgrades 105 | - lvm2 106 | - btrfs-tools 107 | 108 | {{ if eq .Cloud "aws" }} 109 | # cloud-initramfs-growroot will resize the master partition on boot 110 | - cloud-initramfs-growroot 111 | 112 | # So we can install the latest awscli 113 | - python-pip 114 | {{ end }} 115 | 116 | plugins: 117 | {{ if eq .Cloud "gce" }} 118 | ntp: 119 | servers: 120 | - metadata.google.internal 121 | {{ else }} 122 | ntp: {} 123 | {{ end }} 124 | 125 | {{ if eq .Cloud "aws" }} 126 | cloud_init: 127 | metadata_sources: Ec2 128 | username: admin 129 | {{ end }} 130 | 131 | commands: 132 | commands: 133 | {{ if eq .Cloud "aws" }} 134 | # Install awscli through python-pip 135 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 136 | {{ end }} 137 | 138 | # Install our kernel... seems to be problems with bootstrap-vz & custom keys 139 | - [ 'wget', 'https://dist-kope-io.s3.amazonaws.com/apt/kopeio.gpg.key', '-O', '{root}/tmp/kopeio.gpg.key' ] 140 | - [ 'chroot', '{root}', 'apt-key', 'add', '/tmp/kopeio.gpg.key' ] 141 | - [ 'rm', '{root}/tmp/kopeio.gpg.key' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "deb http://dist.kope.io/apt jessie main" > /etc/apt/sources.list.d/kopeio.list' ] 143 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 144 | - [ 'chroot', '{root}', 'apt-get', 'install', '--yes', 'linux-image-k8s', 'linux-headers-k8s' ] 145 | 146 | # We don't enable unattended upgrades - nodeup can always add it 147 | # but if we add it now, there's a race to turn it off 148 | # cloud-init depends on unattended-upgrades, so we can't just remove it 149 | # Instead we turn them off; we turn them on later 150 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 151 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 152 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 153 | 154 | # Remove dkms & other unneeded packages 155 | # TODO: running kernel removal needs removing-running-kernel preseed 156 | # https://apt-browse.org/browse/debian/jessie/main/i386/linux-image-3.16.0-4-586/3.16.7-ckt25-2/debian/prerm 157 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-image-3.16.0-4-amd64', 'linux-headers-3.16.0-4-common' ] 158 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', '--purge', 'dkms' ] 159 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'linux-headers-3.16.0-4-common' ] 160 | - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'libgcc-4.8-dev', 'gcc-4.8', 'cpp', 'cpp-4.9' ] 161 | 162 | # Install docker 163 | - [ 'wget', 'http://download.docker.com/linux/debian/dists/jessie/pool/stable/amd64/docker-ce_17.03.2~ce-0~debian-jessie_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 164 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "a7ac54aaa7d33122ca5f7a2df817cbefb5cdbfc7 docker.deb" | shasum -c -' ] 165 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 166 | - [ 'rm', '{root}/tmp/docker.deb' ] 167 | 168 | {{ if eq .Cloud "aws" }} 169 | # Fix a cloud-init bug where it uses nobootwait 170 | # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=789884 171 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "mount_default_fields: [~, ~, ''auto'', ''defaults,nofail'', ''0'', ''2'']" > /etc/cloud/cloud.cfg.d/99_kubernetes.cfg' ] 172 | {{ end }} 173 | 174 | # We perform a full replacement of some grub conf variables: 175 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 176 | # GRUB_TIMEOUT (remove boot delay) 177 | # (but leave the old versions commented out for people to see) 178 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 179 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 180 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 181 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 182 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0\"" >> /etc/default/grub' ] 183 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 184 | - [ 'chroot', '{root}', 'update-grub2' ] 185 | 186 | # Update everything to latest versions 187 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 188 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 189 | 190 | # Cleanup packages 191 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 192 | 193 | # Remove machine-id, so that we regenerate next boot 194 | - [ 'rm', '-f', '{root}/etc/machine-id' ] 195 | 196 | # Ensure we have cleaned up all our SSH keys 197 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 198 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 199 | # Workaround bootstrap-vz bug where it errors if all keys are removed 200 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 201 | 202 | # journald requires machine-id, so add a PreStart 203 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 204 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 205 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 206 | 207 | # Make sure journald is persistent 208 | # From /usr/share/doc/systemd/README.Debian 209 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 210 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 211 | -------------------------------------------------------------------------------- /imagebuilder/templates/1.9-stretch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {{ if eq .Cloud "aws" }} 3 | name: k8s-1.9-debian-{system.release}-{system.architecture}-{provider.virtualization}-ebs-{%Y}-{%m}-{%d} 4 | {{ else }} 5 | name: k8s-1.9-debian-{system.release}-{system.architecture}-{%Y}-{%m}-{%d} 6 | {{ end }} 7 | provider: 8 | {{ if eq .Cloud "aws" }} 9 | name: ec2 10 | virtualization: hvm 11 | enhanced_networking: simple 12 | {{ else if eq .Cloud "gce" }} 13 | name: gce 14 | gcs_destination: {{ .GCSDestination }} 15 | gce_project: {{ .Project }} 16 | {{ else }} 17 | name: {{ .Cloud }} 18 | {{ end }} 19 | description: Kubernetes 1.9 Base Image - Debian {system.release} {system.architecture} 20 | bootstrapper: 21 | workspace: /target 22 | # tarball speeds up development, but for prod builds we want to be 100% sure... 23 | # tarball: true 24 | # 1.9? variant: minbase 25 | system: 26 | release: stretch 27 | architecture: amd64 28 | bootloader: grub 29 | charmap: UTF-8 30 | locale: en_US 31 | timezone: UTC 32 | volume: 33 | {{ if eq .Cloud "aws" }} 34 | backing: ebs 35 | {{ else if eq .Cloud "gce" }} 36 | backing: raw 37 | {{ end }} 38 | partitions: 39 | type: gpt 40 | root: 41 | filesystem: ext4 42 | # We create the FS with more inodes... docker is pretty inode hungry 43 | format_command: [ 'mkfs.{fs}', '-i', '4096', '{device_path}' ] 44 | size: 8GiB 45 | packages: 46 | {{ if eq .Cloud "aws" }} 47 | mirror: http://cloudfront.debian.net/debian 48 | {{ end }} 49 | install: 50 | # Important utils for administration 51 | # if minbase - openssh-server 52 | 53 | # these packages are generally useful 54 | # (and are the ones from the GCE image) 55 | - rsync 56 | - screen 57 | - vim 58 | 59 | # needed for docker 60 | - iptables 61 | - libapparmor1 62 | - libltdl7 63 | 64 | # Handy utilities 65 | - htop 66 | - tcpdump 67 | - iotop 68 | - ethtool 69 | - sysstat 70 | 71 | # needed for setfacl below 72 | - acl 73 | 74 | {{ if eq .Cloud "aws" }} 75 | # these packages are included in the official AWS image 76 | - python-boto 77 | - python3-boto 78 | - apt-transport-https 79 | - lvm2 80 | - ncurses-term 81 | - parted 82 | - cloud-init 83 | - cloud-utils 84 | - gdisk 85 | - systemd 86 | - systemd-sysv 87 | 88 | # these packages are included in the official image, but we remove them 89 | # awscli : we install from pip instead 90 | {{ end }} 91 | 92 | # These packages would otherwise be installed during first boot 93 | - aufs-tools 94 | - curl 95 | - python-yaml 96 | - git 97 | - nfs-common 98 | - bridge-utils 99 | - logrotate 100 | - socat 101 | - python-apt 102 | - apt-transport-https 103 | - unattended-upgrades 104 | - lvm2 105 | - btrfs-tools 106 | 107 | {{ if eq .Cloud "aws" }} 108 | # So we can install the latest awscli 109 | - python-pip 110 | {{ end }} 111 | 112 | plugins: 113 | {{ if eq .Cloud "gce" }} 114 | ntp: 115 | servers: 116 | - metadata.google.internal 117 | {{ else }} 118 | ntp: {} 119 | {{ end }} 120 | 121 | {{ if eq .Cloud "aws" }} 122 | cloud_init: 123 | metadata_sources: Ec2 124 | username: admin 125 | enable_modules: 126 | cloud_init_modules: 127 | - {module: growpart, position: 4} 128 | {{ end }} 129 | 130 | commands: 131 | commands: 132 | {{ if eq .Cloud "aws" }} 133 | # Install awscli through python-pip 134 | - [ 'chroot', '{root}', 'pip', 'install', 'awscli' ] 135 | {{ end }} 136 | 137 | # We don't enable unattended upgrades - nodeup can always add it 138 | # but if we add it now, there's a race to turn it off 139 | # cloud-init depends on unattended-upgrades, so we can't just remove it 140 | # Instead we turn them off; we turn them on later 141 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades' ] 142 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "APT::Periodic::Unattended-Upgrade \"0\"; " >> /etc/apt/apt.conf.d/20auto-upgrades' ] 143 | # - [ 'chroot', '{root}', 'apt-get', 'remove', '--yes', 'unattended-upgrades' ] 144 | 145 | # Install docker 146 | - [ 'wget', 'http://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce_17.03.2~ce-0~debian-stretch_amd64.deb', '-O', '{root}/tmp/docker.deb' ] 147 | - [ '/bin/sh', '-c', 'cd {root}/tmp; echo "36773361cf44817371770cb4e6e6823590d10297 docker.deb" | shasum -c -' ] 148 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'DEBIAN_FRONTEND=noninteractive dpkg --install /tmp/docker.deb' ] 149 | - [ 'rm', '{root}/tmp/docker.deb' ] 150 | 151 | # We perform a full replacement of some grub conf variables: 152 | # GRUB_CMDLINE_LINUX_DEFAULT (add memory cgroup) 153 | # GRUB_TIMEOUT (remove boot delay) 154 | # (but leave the old versions commented out for people to see) 155 | - [ 'chroot', '{root}', 'touch', '/etc/default/grub' ] 156 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_CMDLINE_LINUX_DEFAULT=/#GRUB_CMDLINE_LINUX_DEFAULT=/g', '/etc/default/grub' ] 157 | - [ 'chroot', '{root}', 'sed', '-i', 's/^GRUB_TIMEOUT=/#GRUB_TIMEOUT=/g', '/etc/default/grub' ] 158 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "# kubernetes image changes" >> /etc/default/grub' ] 159 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_CMDLINE_LINUX_DEFAULT=\"cgroup_enable=memory oops=panic panic=10 console=ttyS0 nvme_core.io_timeout=255\"" >> /etc/default/grub' ] 160 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "GRUB_TIMEOUT=0" >> /etc/default/grub' ] 161 | - [ 'chroot', '{root}', 'update-grub2' ] 162 | 163 | # Update everything to latest versions 164 | - [ 'chroot', '{root}', 'apt-get', 'update' ] 165 | - [ 'chroot', '{root}', 'apt-get', 'dist-upgrade', '--yes' ] 166 | 167 | # Cleanup packages 168 | - [ 'chroot', '{root}', 'apt-get', 'autoremove', '--yes' ] 169 | 170 | # Remove machine-id, so that we regenerate next boot 171 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "" > /etc/machine-id' ] 172 | 173 | # Ensure we have cleaned up all our SSH keys 174 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key' ] 175 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'shred --remove /etc/ssh/ssh_host_*_key.pub' ] 176 | # Workaround bootstrap-vz bug where it errors if all keys are removed 177 | - [ 'chroot', '{root}', 'bin/sh', '-c', 'touch /etc/ssh/ssh_host_rsa_key.pub' ] 178 | 179 | # journald requires machine-id, so add a PreStart 180 | - [ 'chroot', '{root}', 'mkdir', '-p', '/etc/systemd/system/debian-fixup.service.d/' ] 181 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "[Service]" > /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 182 | - [ 'chroot', '{root}', '/bin/sh', '-c', 'echo "ExecStartPre=/bin/systemd-machine-id-setup" >> /etc/systemd/system/debian-fixup.service.d/10-machineid.conf' ] 183 | 184 | # Make sure journald is persistent 185 | # From /usr/share/doc/systemd/README.Debian 186 | - [ 'chroot', '{root}', 'install', '-d', '-g', 'systemd-journal', '/var/log/journal' ] 187 | - [ 'chroot', '{root}', 'setfacl', '-R', '-nm', 'g:adm:rx,d:g:adm:rx', '/var/log/journal' ] 188 | -------------------------------------------------------------------------------- /imagebuilder/templates/README.md: -------------------------------------------------------------------------------- 1 | ## Kubernetes-optimized images 2 | 3 | This directory contains manifests for building Kubernetes-optimized images for 4 | various clouds (currently just AWS). It is currently highly experimental, and 5 | these images are not used by default (though you can pass `AWS_IMAGE` to the 6 | AWS kube-up script if you're feeling brave). 7 | 8 | Advantages of an optimized image: 9 | 10 | * We can preinstall packages that would otherwise require a download. Great 11 | for speed, and also for reliability (in case the source repository is down) 12 | * We can make kernel configuration changes that might otherwise require a 13 | reboot, or even apply kernel patches if we really want to. For example, 14 | Debian requires a kernel boot parameter to enable the cgroup memory 15 | controller, which we require. 16 | * The more configuration we can do in advance, the easier it is for people that 17 | don't want to use kube-up to get a cluster up and running. 18 | 19 | Advantages of a harmonized image: 20 | 21 | * All the platforms can test with the same versions of software, rather than 22 | relying on whatever image happens to be optimal on that cloud. 23 | 24 | ## bootstrap-vz 25 | 26 | Currently images are built using 27 | [bootstrap-vz](https://github.com/andsens/bootstrap-vz), because this is 28 | default builder for the official Debian images, and because it supports 29 | multiple clouds including AWS, Azure & GCE. It also supports KVM, which should 30 | support OpenStack. 31 | --------------------------------------------------------------------------------