├── .gitbook.yaml ├── .github └── workflows │ └── ci.yml ├── .markdownlint.json ├── .travis.yml ├── .verify-links.sh ├── LICENSE ├── README.md ├── charts └── guestbook │ ├── Chart.yaml │ ├── LICENSE │ ├── README.md │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── guestbook-deployment.yaml │ ├── guestbook-service.yaml │ ├── redis-master-deployment.yaml │ ├── redis-master-service.yaml │ ├── redis-slave-deployment.yaml │ └── redis-slave-service.yaml │ └── values.yaml ├── docs ├── Lab0 │ └── README.md ├── Lab1 │ └── README.md ├── Lab2 │ └── README.md ├── Lab3 │ └── README.md ├── Lab4 │ └── README.md ├── README.md ├── SUMMARY.md ├── images │ ├── guestbook-page.png │ └── helm-architecture.png └── index.yaml ├── index.yaml ├── mkdocs.yml ├── presentation ├── Helm.pptx ├── README.md └── demosteps.md └── repo └── stable ├── guestbook-0.1.0.tgz ├── guestbook-0.2.0.tgz ├── guestbook-0.2.1.tgz └── index.yaml /.gitbook.yaml: -------------------------------------------------------------------------------- 1 | # Do not edit this file, to adjust the table of contents, modify SUMMARY.md 2 | 3 | root: ./docs/ 4 | 5 | structure: 6 | readme: README.md 7 | summary: SUMMARY.md 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - master 7 | jobs: 8 | deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-python@v2 13 | with: 14 | python-version: 3.x 15 | - run: pip install mkdocs-material 16 | - run: mkdocs gh-deploy --force 17 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "MD013: Line length too large", 3 | "line-length": false 4 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | - language: node_js 2 | node_js: 10 3 | script: 4 | - npm install markdownlint-cli 5 | - markdownlint --config .markdownlint.json --ignore docs/SUMMARY.md docs 6 | -------------------------------------------------------------------------------- /.verify-links.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2017 The Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This script will scan all md (markdown) files for bad references. 18 | # It will look for strings of the form [...](...) and make sure that 19 | # the (...) points to either a valid file in the source tree or, in the 20 | # case of it being an http url, it'll make sure we don't get a 404. 21 | # 22 | # Usage: verify-links.sh [ dir | file ... ] 23 | # default arg is root of our source tree 24 | 25 | set -o errexit 26 | set -o nounset 27 | set -o pipefail 28 | 29 | verbose="" 30 | debugFlag="" 31 | maxRetries="1" 32 | stop="" 33 | tmp=/tmp/out${RANDOM} 34 | 35 | trap clean EXIT 36 | seenFiles=( ":" ) # just to prevent "undefined" errors 37 | 38 | # findPrevious will search for a file to see if we've seen it before. 39 | # If we have then return the matching "anchorFile". If we haven't 40 | # seen it then add it to "seenFiles" and create a new "anchorFile". 41 | # $1 == search file 42 | # Note we can't use a map because bash on a mac doesn't support it. 43 | foundAnchor="" 44 | function findPreviousFile() { 45 | for f in "${seenFiles[@]}" ; do 46 | orig=${f%%:*} 47 | if [[ "${orig}" == "$1" ]]; then 48 | foundAnchor=${f#*:} 49 | return 0 50 | fi 51 | done 52 | 53 | # Didn't it so create a new anchorFile and save it for next time 54 | foundAnchor="${tmp}-anchors-${RANDOM}-${RANDOM}" 55 | seenFiles+=("$1:${foundAnchor}") 56 | return 1 57 | } 58 | 59 | function debug { 60 | if [[ "$debugFlag" != "" ]]; then 61 | (>&2 echo $*) 62 | fi 63 | } 64 | 65 | function clean { 66 | rm -f ${tmp}* 67 | } 68 | 69 | while [[ "$#" != "0" && "$1" == "-"* ]]; do 70 | opts="${1:1}" 71 | while [[ "$opts" != "" ]]; do 72 | case "${opts:0:1}" in 73 | v) verbose="1" ;; 74 | d) debugFlag="1" ; verbose="1" ;; 75 | t) maxRetries="5" ;; 76 | -) stop="1" ;; 77 | ?) echo "Usage: $0 [OPTION]... [DIR|FILE]..." 78 | echo "Verify all links in markdown files." 79 | echo 80 | echo " -v show each file as it is checked" 81 | echo " -d show each href as it is found" 82 | echo " -t retry GETs to http(s) URLs 5 times" 83 | echo " -? show this help text" 84 | echo " -- treat remainder of args as dir/files" 85 | exit 0 ;; 86 | *) echo "Unknown option '${opts:0:1}'" 87 | exit 1 ;; 88 | esac 89 | opts="${opts:1}" 90 | done 91 | shift 92 | if [[ "$stop" == "1" ]]; then 93 | break 94 | fi 95 | done 96 | 97 | # echo verbose:$verbose 98 | # echo debugFlag:$debugFlag 99 | # echo args:$* 100 | 101 | arg="" 102 | 103 | if [ "$*" == "" ]; then 104 | arg="." 105 | fi 106 | 107 | mdFiles=$(find $* $arg -name "*.md" | sort | grep -v vendor | grep -v glide) 108 | 109 | clean 110 | for file in ${mdFiles}; do 111 | # echo scanning $file 112 | dir=$(dirname $file) 113 | 114 | [[ -n "$verbose" ]] && echo "> $file" 115 | 116 | # Replace ) with )\n so that each possible href is on its own line. 117 | # Then only grab lines that have [..](..) in them - put results in tmp file. 118 | # If the file doesn't have any lines with [..](..) then skip this file 119 | # Steps: 120 | # tr - convert all \n to a space since newlines shouldn't change anything 121 | # sed - add a \n after each ) since ) ends what we're looking for. 122 | # This makes it so that each href is on a line by itself 123 | # sed - prefix each line with a space so the grep can do [^\\] 124 | # grep - find all lines that match [...](...) 125 | cat $file | \ 126 | tr '\n' ' ' | \ 127 | sed "s/)/)\n/g" | \ 128 | sed "s/^/ /g" | \ 129 | grep "[^\\]\[.*\](.*)" > ${tmp}1 || continue 130 | 131 | # This sed will extract the href portion of the [..](..) - meaning 132 | # the stuff in the parens. 133 | sed "s/.*\[*\]\([^()]*\)/\1/" < ${tmp}1 > ${tmp}2 || continue 134 | 135 | cat ${tmp}2 | while read line ; do 136 | # Strip off the leading and trailing parens, and then spaces 137 | ref=${line#*(} 138 | ref=${ref%)*} 139 | ref=$(echo $ref | sed "s/ *//" | sed "s/ *$//") 140 | 141 | # Show all hrefs - mainly for verifying in our tests 142 | debug "Checking: '$ref'" 143 | 144 | # An external href (ie. starts with http) 145 | if [ "${ref:0:4}" == "http" ]; then 146 | try=0 147 | while true ; do 148 | if curl -f -s -k --connect-timeout 10 ${ref} > /dev/null 2>&1 ; then 149 | break 150 | fi 151 | let try=try+1 152 | if [ ${try} -eq ${maxRetries} ]; then 153 | extra="" 154 | if [ ${try} -gt 1 ]; then 155 | extra="(tried ${try} times) " 156 | fi 157 | echo $file: Can\'t load url: ${ref} ${extra} | tee -a ${tmp}3 158 | break 159 | fi 160 | sleep 1 161 | done 162 | continue 163 | fi 164 | 165 | # Skip "mailto:" refs 166 | if [ "${ref:0:7}" == "mailto:" ]; then 167 | continue 168 | fi 169 | 170 | # Local file link (i.e. ref contains a #) 171 | if [[ "${ref/\#}" != "${ref}" ]]; then 172 | 173 | # If ref doesn't start with "#" then update filepath 174 | if [ "${ref:0:1}" != "#" ]; then 175 | # Split ref into filepath and the section link 176 | reffile=$(echo ${ref} | awk -F"#" '{print $1}') 177 | fullpath=${dir}/${reffile} 178 | ref=$(echo ${ref} | awk -F"#" '{$1=""; print $0}') 179 | else 180 | fullpath=${file} 181 | ref=${ref:1} 182 | fi 183 | 184 | if [[ ! -e "${fullpath}" ]]; then 185 | echo "$file: Can't find referenced file '${fullpath}'" | \ 186 | tee -a ${tmp}3 187 | continue 188 | fi 189 | 190 | # Remove leading and trailing spaces 191 | ref=$(echo ${ref} | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//') 192 | 193 | # If we've seen this file before then grab its processed tmp file 194 | if findPreviousFile "${fullpath}" ; then 195 | anchorFile="${foundAnchor}" 196 | else 197 | anchorFile="${foundAnchor}" 198 | 199 | # Search file for sections 200 | used="" # anchors used, seen+twiddled ones 201 | 202 | # Find all section headers in the file. 203 | # Remove leading & trailing spaces. 204 | # Lower case it. 205 | # Convert spaces to "-". 206 | # Drop all non alphanumeric chars. 207 | # Twiddle section anchor if we've seen it before. 208 | grep "^[[:space:]]*#" < ${fullpath} | \ 209 | sed 's/[[:space:]]*##*[[:space:]]*//' | \ 210 | sed 's/[[:space:]]*$//' | \ 211 | tr '[:upper:]' '[:lower:]' | \ 212 | sed "s/ */-/g" | \ 213 | sed "s/[^-a-zA-Z0-9]//g" | while read section ; do 214 | # If we haven't used this exact anchor before just use it now 215 | if [[ "${used}" != *" ${section} "* ]]; then 216 | anchor=${section} 217 | else 218 | # We've used this anchor before so add "-#" to the end. 219 | # Keep adding 1 to "#" until we find a free spot. 220 | let num=1 221 | while true; do 222 | anchor="${section}-${num}" 223 | if [[ "${used}" != *" ${anchor} "* ]]; then 224 | break 225 | fi 226 | let num+=1 227 | done 228 | fi 229 | 230 | echo "${anchor}" 231 | used="${used} ${anchor} " 232 | 233 | debug "Mapped section '${section}' to '${anchor}'" 234 | 235 | done > ${anchorFile} || true 236 | 237 | # Add sections of the form 238 | grep ".*$/\1/' | \ 241 | sort | uniq >> ${anchorFile} || true 242 | 243 | # echo sections ; cat ${tmp}sections1 244 | fi 245 | 246 | # Skip refs of the form #L and assume its pointing to a line 247 | # number of a file and those don't have anchors 248 | if [[ "${ref}" =~ ^L([0-9])+$ ]]; then 249 | continue 250 | fi 251 | 252 | # Finally, look for the ref in the list of sections/anchors 253 | debug "Anchor file(${fullpath}): ${anchorFile}" 254 | if ! grep "^${ref}$" ${anchorFile} > /dev/null 2>&1 ; then 255 | echo $file: Can\'t find section \'\#${ref}\' in ${fullpath} | \ 256 | tee -a ${tmp}3 257 | fi 258 | 259 | continue 260 | 261 | fi 262 | 263 | newPath=${dir}/${ref} 264 | 265 | # And finally make sure the file is there 266 | # debug line: echo ref: $ref "->" $newPath 267 | if [[ ! -e "${newPath}" ]]; then 268 | echo $file: Can\'t find: ${newPath} | tee -a ${tmp}3 269 | fi 270 | 271 | done 272 | done 273 | 274 | if [ -s ${tmp}3 ]; then exit 1 ; fi 275 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction to Helm 2 | 3 | Helm is a tool that streamlines installation and management of Kubernetes applications. Think of Helm as an apt/yum/homebrew 4 | for Kubernetes. This repository provides learning materials for Helm. 5 | 6 | The default branch of this repo is `master` and it uses the current major release of [Helm](https://helm.sh/) which is v3. If you 7 | are using Helm v2 then go to the [helm-v2](https://github.com/IBM/helm101/tree/helm-v2) branch. Please refer to [Helm Status](#helm-status) 8 | for more details on the different Helm releases. 9 | 10 | ## Helm Status 11 | 12 | [Helm v3 was released](https://helm.sh/blog/helm-3-released/) in November 2019. The interface is quite similar but there 13 | are major changes to the architecture and internal plumbing of Helm, essentially making it a new product when compared forensically 14 | against Helm 2. Check out [what’s in Helm 3](https://developer.ibm.com/technologies/containers/blogs/kubernetes-helm-3/) for more 15 | details. 16 | 17 | The [Helm 2 Support Plan](https://helm.sh/blog/2019-10-22-helm-2150-released/#helm-2-support-plan) documents a 1 year "maintenance 18 | mode" for Helm v2. It states the following: 19 | 20 | - 6 month bug fixes until May 13 2020 21 | - 6 month security fixes until November 13 2020 22 | - At 1 year on November 13 2020, support for Helm v2 will end 23 | -------------------------------------------------------------------------------- /charts/guestbook/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: A Helm chart to deploy Guestbook three tier web application. 3 | name: guestbook 4 | version: 0.2.0 5 | -------------------------------------------------------------------------------- /charts/guestbook/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /charts/guestbook/README.md: -------------------------------------------------------------------------------- 1 | # guestbook: an example chart for educational purpose. 2 | 3 | This chart provides example of some of the important features of Helm. 4 | 5 | The chart installs a [guestbook](https://github.com/IBM/guestbook/tree/master/v1) application. 6 | 7 | ## Installing the Chart 8 | 9 | Add the repository to your local environment: 10 | ```bash 11 | $ helm repo add my-repo https://ibm.github.io/helm101/ 12 | ``` 13 | 14 | To install the chart with the default release name: 15 | 16 | ```bash 17 | $ helm install my-repo/guestbook 18 | ``` 19 | 20 | To install the chart with your preference of release name, for example, `my-release`: 21 | 22 | ```bash 23 | $ helm install my-repo/guestbook --name my-release 24 | ``` 25 | 26 | ### Uninstalling the Chart 27 | 28 | To completely uninstall/delete the `my-release` deployment: 29 | 30 | ```bash 31 | $ helm delete --purge my-release 32 | ``` 33 | 34 | The command removes all the Kubernetes components associated with the chart and deletes the release. 35 | 36 | ## Configuration 37 | 38 | The following tables lists the configurable parameters of the chart and their default values. 39 | 40 | | Parameter | Description | Default | 41 | | ----------------------- | --------------------------------------------- | ---------------------------------------------------------- | 42 | | `image.repository` | Image repository | `ibmcom/guestbook` | 43 | | `image.tag` | Image tag | `v1` | 44 | | `image.pullPolicy` | Image pull policy | `Always` | 45 | | `service.type` | Service type | `LoadBalancer` | 46 | | `service.port` | Service port | `3000` | 47 | | `redis.slaveEnabled` | Redis slave enabled | `true` | 48 | | `redis.port` | Redis port | `6379` | 49 | 50 | Specify each parameter using the `--set [key=value]` argument to `helm install`. For example, 51 | 52 | ```bash 53 | $ helm install my-repo/guestbook --set service.type=NodePort 54 | ``` 55 | -------------------------------------------------------------------------------- /charts/guestbook/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if contains "NodePort" .Values.service.type }} 3 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "guestbook.fullname" . }}) 4 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 5 | echo http://$NODE_IP:$NODE_PORT 6 | {{- else if contains "LoadBalancer" .Values.service.type }} 7 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 8 | You can watch the status of by running 'kubectl get svc -w {{ include "guestbook.fullname" . }} --namespace {{ .Release.Namespace }}' 9 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "guestbook.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 10 | echo http://$SERVICE_IP:{{ .Values.service.port }} 11 | {{- else if contains "ClusterIP" .Values.service.type }} 12 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "guestbook.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 13 | echo "Visit http://127.0.0.1:8080 to use your application" 14 | kubectl port-forward $POD_NAME 8080:80 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /charts/guestbook/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "guestbook.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "guestbook.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "guestbook.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | -------------------------------------------------------------------------------- /charts/guestbook/templates/guestbook-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: {{ include "guestbook.name" . }} 7 | helm.sh/chart: {{ include "guestbook.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | spec: 11 | replicas: {{ .Values.replicaCount }} 12 | selector: 13 | matchLabels: 14 | app.kubernetes.io/name: {{ include "guestbook.name" . }} 15 | app.kubernetes.io/instance: {{ .Release.Name }} 16 | template: 17 | metadata: 18 | labels: 19 | app.kubernetes.io/name: {{ include "guestbook.name" . }} 20 | app.kubernetes.io/instance: {{ .Release.Name }} 21 | spec: 22 | containers: 23 | - name: {{ .Chart.Name }} 24 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 25 | imagePullPolicy: {{ .Values.image.pullPolicy }} 26 | ports: 27 | - name: http-server 28 | containerPort: {{ .Values.service.port }} 29 | -------------------------------------------------------------------------------- /charts/guestbook/templates/guestbook-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "guestbook.fullname" . }} 5 | labels: 6 | app.kubernetes.io/name: {{ include "guestbook.name" . }} 7 | helm.sh/chart: {{ include "guestbook.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | spec: 11 | type: {{ .Values.service.type }} 12 | ports: 13 | - port: {{ .Values.service.port }} 14 | targetPort: http-server 15 | selector: 16 | app.kubernetes.io/name: {{ include "guestbook.name" . }} 17 | app.kubernetes.io/instance: {{ .Release.Name }} 18 | -------------------------------------------------------------------------------- /charts/guestbook/templates/redis-master-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: redis-master 5 | labels: 6 | app: redis 7 | role: master 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: redis 13 | role: master 14 | template: 15 | metadata: 16 | labels: 17 | app: redis 18 | role: master 19 | spec: 20 | containers: 21 | - name: redis-master 22 | image: redis:3.2.9 23 | ports: 24 | - name: redis-server 25 | containerPort: {{ .Values.redis.port }} 26 | -------------------------------------------------------------------------------- /charts/guestbook/templates/redis-master-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: redis-master 5 | labels: 6 | app: redis 7 | role: master 8 | spec: 9 | ports: 10 | - port: {{ .Values.redis.port }} 11 | targetPort: redis-server 12 | selector: 13 | app: redis 14 | role: master 15 | -------------------------------------------------------------------------------- /charts/guestbook/templates/redis-slave-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.slaveEnabled -}} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: redis-slave 6 | labels: 7 | app: redis 8 | role: slave 9 | spec: 10 | replicas: 2 11 | selector: 12 | matchLabels: 13 | app: redis 14 | role: slave 15 | template: 16 | metadata: 17 | labels: 18 | app: redis 19 | role: slave 20 | spec: 21 | containers: 22 | - name: redis-slave 23 | image: k8s.gcr.io/redis-slave:v2 24 | ports: 25 | - name: redis-server 26 | containerPort: {{ .Values.redis.port }} 27 | {{- end }} 28 | -------------------------------------------------------------------------------- /charts/guestbook/templates/redis-slave-service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.redis.slaveEnabled -}} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: redis-slave 6 | labels: 7 | app: redis 8 | role: slave 9 | spec: 10 | ports: 11 | - port: {{ .Values.redis.port }} 12 | targetPort: redis-server 13 | selector: 14 | app: redis 15 | role: slave 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /charts/guestbook/values.yaml: -------------------------------------------------------------------------------- 1 | # IBM Guestbook image version ibmcom/guestbook:v1 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 2 6 | 7 | image: 8 | repository: ibmcom/guestbook 9 | tag: v1 10 | pullPolicy: Always 11 | 12 | # For some dev env (like minikube), you may need to set the type to NodePort 13 | service: 14 | type: LoadBalancer 15 | port: 3000 16 | 17 | redis: 18 | port: 6379 19 | slaveEnabled: true 20 | 21 | -------------------------------------------------------------------------------- /docs/Lab0/README.md: -------------------------------------------------------------------------------- 1 | # Lab 0. Installing Helm on IBM Cloud Kubernetes Service 2 | 3 | The Helm client (`helm`) can be installed from source or pre-built binary releases. In this lab, we are going to use the pre-built binary release (Linux amd64) from the Helm community. Refer to the [Helm install docs](https://helm.sh/docs/intro/install/) for more details. 4 | 5 | ## Prerequisites 6 | 7 | Create a Kubernetes cluster with [IBM Cloud Kubernetes Service](https://cloud.ibm.com/docs/containers/cs_tutorials.html#cs_cluster_tutorial), following the steps to also configure the IBM Cloud CLI with the Kubernetes Service plug-in. 8 | 9 | ## Installing the Helm Client (helm) 10 | 11 | 1. Download the [latest release of Helm v3](https://github.com/helm/helm/releases) for your environment, the steps below are for `Linux amd64`, adjust the examples as needed for your environment. 12 | 13 | 2. Unpack it: `$ tar -zxvf helm-v3..-linux-amd64.tgz`. 14 | 15 | 3. Find the helm binary in the unpacked directory, and move it to its desired location: `mv linux-amd64/helm /usr/local/bin/helm`. It is best if the location you copy to is pathed, as it avoids having to path the helm commands. 16 | 17 | 4. The Helm client is now installed and can be tested with the command, `helm help`. 18 | 19 | ## Conclusion 20 | 21 | You are now ready to start using Helm. 22 | -------------------------------------------------------------------------------- /docs/Lab1/README.md: -------------------------------------------------------------------------------- 1 | # Lab 1. Deploy with Helm 2 | 3 | Let's investigate how Helm can help us focus on other things by letting a chart do the work for us. We'll first deploy an application to a Kubernetes cluster by using `kubectl` and then show how we can offload the work to a chart by deploying the same app with Helm. 4 | 5 | The application is the [Guestbook App](https://github.com/IBM/guestbook), which is a sample multi-tier web application. 6 | 7 | ## Scenario 1: Deploy the application using `kubectl` 8 | 9 | In this part of the lab, we will deploy the application using the Kubernetes client `kubectl`. We will use [Version 1](https://github.com/IBM/guestbook/tree/master/v1) of the app for deploying here. 10 | 11 | If you already have a copy of the guestbook application installed from the [kube101 lab](https://github.com/IBM/kube101), skip this section and go the `helm` example in [Scenario 2](#scenario-2-deploy-the-application-using-helm). 12 | 13 | Clone the [Guestbook App](https://github.com/IBM/guestbook) repo to get the files: 14 | 15 | ```console 16 | git clone https://github.com/IBM/guestbook.git 17 | ``` 18 | 19 | 1. Use the configuration files in the cloned Git repository to deploy the containers and create services for them by using the following commands: 20 | 21 | ```console 22 | $ cd guestbook/v1 23 | 24 | $ kubectl create -f redis-master-deployment.yaml 25 | deployment.apps/redis-master created 26 | 27 | $ kubectl create -f redis-master-service.yaml 28 | service/redis-master created 29 | 30 | $ kubectl create -f redis-slave-deployment.yaml 31 | deployment.apps/redis-slave created 32 | 33 | $ kubectl create -f redis-slave-service.yaml 34 | service/redis-slave created 35 | 36 | $ kubectl create -f guestbook-deployment.yaml 37 | deployment.apps/guestbook-v1 created 38 | 39 | $ kubectl create -f guestbook-service.yaml 40 | service/guestbook created 41 | ``` 42 | 43 | Refer to the [guestbook README](https://github.com/IBM/guestbook) for more details. 44 | 45 | 1. View the guestbook: 46 | 47 | You can now play with the guestbook that you just created by opening it in a browser (it might take a few moments for the guestbook to come up). 48 | 49 | * **Local Host:** 50 | If you are running Kubernetes locally, view the guestbook by navigating to `http://localhost:3000` in your browser. 51 | 52 | * **Remote Host:** 53 | 54 | 1. To view the guestbook on a remote host, locate the external IP and port of the load balancer in the **EXTERNAL-IP** and **PORTS** columns of the `$ kubectl get services` output. 55 | 56 | ```console 57 | $ kubectl get services 58 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 59 | guestbook LoadBalancer 172.21.252.107 50.23.5.136 3000:31838/TCP 14m 60 | redis-master ClusterIP 172.21.97.222 6379/TCP 14m 61 | redis-slave ClusterIP 172.21.43.70 6379/TCP 14m 62 | ......... 63 | ``` 64 | 65 | In this scenario the URL is `http://50.23.5.136:31838`. 66 | 67 | Note: If no external IP is assigned, then you can get the external IP with the following command: 68 | 69 | ```console 70 | $ kubectl get nodes -o wide 71 | NAME STATUS ROLES AGE VERSION EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME 72 | 10.47.122.98 Ready 1h v1.10.11+IKS 173.193.92.112 Ubuntu 16.04.5 LTS 4.4.0-141-generic docker://18.6.1 73 | ``` 74 | 75 | In this scenario the URL is `http://173.193.92.112:31838`. 76 | 77 | 2. Navigate to the output given (for example `http://50.23.5.136:31838`) in your browser. You should see the guestbook now displaying in your browser: 78 | 79 | ![Guestbook](../images/guestbook-page.png) 80 | 81 | ## Scenario 2: Deploy the application using Helm 82 | 83 | In this part of the lab, we will deploy the application by using Helm. We will set a release name of `guestbook-demo` to distinguish it from the previous deployment. The Helm chart is available [here](../../charts/guestbook). Clone the [Helm 101](https://github.com/IBM/helm101) repo to get the files: 84 | 85 | ```console 86 | git clone https://github.com/IBM/helm101 87 | ``` 88 | 89 | A chart is defined as a collection of files that describe a related set of Kubernetes resources. We probably then should take a look at the the files before we go and install the chart. The files for the `guestbook` chart are as follows: 90 | 91 | ```text 92 | . 93 | ├── Chart.yaml \\ A YAML file containing information about the chart 94 | ├── LICENSE \\ A plain text file containing the license for the chart 95 | ├── README.md \\ A README providing information about the chart usage, configuration, installation etc. 96 | ├── templates \\ A directory of templates that will generate valid Kubernetes manifest files when combined with values.yaml 97 | │ ├── _helpers.tpl \\ Template helpers/definitions that are re-used throughout the chart 98 | │ ├── guestbook-deployment.yaml \\ Guestbook app container resource 99 | │ ├── guestbook-service.yaml \\ Guestbook app service resource 100 | │ ├── NOTES.txt \\ A plain text file containing short usage notes about how to access the app post install 101 | │ ├── redis-master-deployment.yaml \\ Redis master container resource 102 | │ ├── redis-master-service.yaml \\ Redis master service resource 103 | │ ├── redis-slave-deployment.yaml \\ Redis slave container resource 104 | │ └── redis-slave-service.yaml \\ Redis slave service resource 105 | └── values.yaml \\ The default configuration values for the chart 106 | ``` 107 | 108 | Note: The template files shown above will be rendered into Kubernetes manifest files before being passed to the Kubernetes API server. Therefore, they map to the manifest files that we deployed when we used `kubectl` (minus the helper and notes files). 109 | 110 | Let's go ahead and install the chart now. If the `helm-demo` namespace does not exist, you will need to create it using: 111 | 112 | ```console 113 | kubectl create namespace helm-demo 114 | ``` 115 | 116 | 1. Install the app as a Helm chart: 117 | 118 | ```console 119 | $ cd helm101/charts 120 | 121 | $ helm install guestbook-demo ./guestbook/ --namespace helm-demo 122 | NAME: guestbook-demo 123 | ... 124 | ``` 125 | 126 | You should see output similar to the following: 127 | 128 | ```console 129 | NAME: guestbook-demo 130 | LAST DEPLOYED: Mon Feb 24 18:08:02 2020 131 | NAMESPACE: helm-demo 132 | STATUS: deployed 133 | REVISION: 1 134 | TEST SUITE: None 135 | NOTES: 136 | 1. Get the application URL by running these commands: 137 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 138 | You can watch the status of by running 'kubectl get svc -w guestbook-demo --namespace helm-demo' 139 | export SERVICE_IP=$(kubectl get svc --namespace helm-demo guestbook-demo -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 140 | echo http://$SERVICE_IP:3000 141 | ``` 142 | 143 | The chart install performs the Kubernetes deployments and service creations of the redis master and slaves, and the guestbook app, as one. This is because the chart is a collection of files that describe a related set of Kubernetes resources and Helm manages the creation of these resources via the Kubernetes API. 144 | 145 | Check the deployment: 146 | 147 | ```console 148 | kubectl get deployment guestbook-demo --namespace helm-demo 149 | ``` 150 | 151 | You should see output similar to the following: 152 | 153 | ```console 154 | $ kubectl get deployment guestbook-demo --namespace helm-dem 155 | NAME READY UP-TO-DATE AVAILABLE AGE 156 | guestbook-demo 2/2 2 2 51m 157 | ``` 158 | 159 | To check the status of the running application pods, use: 160 | 161 | ```console 162 | kubectl get pods --namespace helm-demo 163 | ``` 164 | 165 | You should see output similar to the following: 166 | 167 | ```console 168 | $ kubectl get pods --namespace helm-demo 169 | NAME READY STATUS RESTARTS AGE 170 | guestbook-demo-6c9cf8b9-jwbs9 1/1 Running 0 52m 171 | guestbook-demo-6c9cf8b9-qk4fb 1/1 Running 0 52m 172 | redis-master-5d8b66464f-j72jf 1/1 Running 0 52m 173 | redis-slave-586b4c847c-2xt99 1/1 Running 0 52m 174 | redis-slave-586b4c847c-q7rq5 1/1 Running 0 52m 175 | ``` 176 | 177 | To check the services, use: 178 | 179 | ```console 180 | kubectl get services --namespace helm-demo 181 | ``` 182 | 183 | ```console 184 | $ kubectl get services --namespace helm-demo 185 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 186 | guestbook-demo LoadBalancer 172.21.43.244 3000:31367/TCP 52m 187 | redis-master ClusterIP 172.21.12.43 6379/TCP 52m 188 | redis-slave ClusterIP 172.21.176.148 6379/TCP 52m 189 | ``` 190 | 191 | 1. View the guestbook: 192 | 193 | You can now play with the guestbook that you just created by opening it in a browser (it might take a few moments for the guestbook to come up). 194 | 195 | * **Local Host:** 196 | If you are running Kubernetes locally, view the guestbook by navigating to `http://localhost:3000` in your browser. 197 | 198 | * **Remote Host:** 199 | 200 | 1. To view the guestbook on a remote host, locate the external IP and the port of the load balancer by following the "NOTES" section in the install output. The commands will be similar to the following: 201 | 202 | ```console 203 | $ export SERVICE_IP=$(kubectl get svc --namespace helm-demo guestbook-demo -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 204 | $ echo http://$SERVICE_IP 205 | http://50.23.5.136 206 | ``` 207 | 208 | Combine the service IP with the port of the service printed earlier. In this scenario the URL is `http://50.23.5.136:31367`. 209 | 210 | Note: If no external IP is assigned, then you can get the external IP with the following command: 211 | 212 | ```console 213 | $ kubectl get nodes -o wide 214 | NAME STATUS ROLES AGE VERSION EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME 215 | 10.47.122.98 Ready 1h v1.10.11+IKS 173.193.92.112 Ubuntu 16.04.5 LTS 4.4.0-141-generic docker://18.6.1 216 | ``` 217 | 218 | In this scenario the URL is `http://173.193.92.112:31367`. 219 | 220 | 2. Navigate to the output given (for example `http://50.23.5.136:31367`) in your browser. You should see the guestbook now displaying in your browser: 221 | 222 | ![Guestbook](../images/guestbook-page.png) 223 | 224 | ## Conclusion 225 | 226 | Congratulations, you have now deployed an application by using two different methods to Kubernetes! From this lab, you can see that using Helm required less commands and less to think about (by giving it the chart path and not the individual files) versus using `kubectl`. Helm's application management provides the user with this simplicity. 227 | 228 | Move on to the next lab, [Lab2](../Lab2/README.md), to learn how to update our running app when the chart has been changed. 229 | -------------------------------------------------------------------------------- /docs/Lab2/README.md: -------------------------------------------------------------------------------- 1 | # Lab 2. Make changes with Helm 2 | 3 | In [Lab 1](../Lab1/README.md), we installed the guestbook sample app by using Helm and saw the benefits over using `kubectl`. You probably think that you're done and know enough to use Helm. But what about updates or improvements to the chart? How do you update your running app to pick up these changes? 4 | 5 | In this lab, we're going to look at how to update our running app when the chart has been changed. To demonstrate this, we're going to make changes to the original `guestbook` chart by: 6 | 7 | * Removing the Redis slaves and using just the in-memory DB 8 | * Changing the type from `LoadBalancer` to `NodePort`. 9 | 10 | It seems contrived but the goal of this lab is to show you how to update your apps with Kubernetes and Helm. So, how easy is it to do this? Let's take a look below. 11 | 12 | ## Scenario 1: Update the application using `kubectl` 13 | 14 | In this part of the lab we will update the previously deployed application [Guestbook](https://github.com/IBM/guestbook), using Kubernetes directly. 15 | 16 | 1. This is an **optional** step that is not technically required to update your running app. The reason for doing this step is "house keeping" - you want to have the correct files for the current configuration that you have deployed. This avoids making mistakes if you have future updates or even rollbacks. In this updated configuration, we remove the Redis slaves. To have the directory match the configuration, move/archive or simply remove the Redis slave files from the guestbook repo tree: 17 | 18 | ``` console 19 | cd guestbook/v1 20 | rm redis-slave-service.yaml 21 | rm redis-slave-deployment.yaml 22 | ``` 23 | 24 | > Note: you can reclaim these files later with a `git checkout -- ` command, if desired 25 | 26 | 1. Delete the Redis slave service and pods: 27 | 28 | ```console 29 | $ kubectl delete svc redis-slave --namespace default 30 | service "redis-slave" deleted 31 | $ kubectl delete deployment redis-slave --namespace default 32 | deployment.extensions "redis-slave" deleted 33 | ``` 34 | 35 | 1. Update the guestbook service from `LoadBalancer` to `NodePort` type: 36 | 37 | ```console 38 | sed -i.bak 's/LoadBalancer/NodePort/g' guestbook-service.yaml 39 | ``` 40 | 41 | > Note: you can reset the files later with a `git checkout -- ` command, if desired 42 | 43 | 1. Delete the guestbook service: 44 | 45 | ```console 46 | kubectl delete svc guestbook --namespace default 47 | ``` 48 | 49 | 1. Re-create the service with `NodePort` type: 50 | 51 | ```console 52 | kubectl create -f guestbook-service.yaml 53 | ``` 54 | 55 | 1. Check the updates, using 56 | 57 | ```console 58 | kubectl get all --namespace default 59 | ``` 60 | 61 | ```console 62 | $ kubectl get all --namespace default 63 | NAME READY STATUS RESTARTS AGE 64 | pod/guestbook-v1-7fc76dc46-9r4s7 1/1 Running 0 1h 65 | pod/guestbook-v1-7fc76dc46-hspnk 1/1 Running 0 1h 66 | pod/guestbook-v1-7fc76dc46-sxzkt 1/1 Running 0 1h 67 | pod/redis-master-5d8b66464f-pvbl9 1/1 Running 0 1h 68 | 69 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 70 | service/guestbook NodePort 172.21.45.29 3000:31989/TCP 31s 71 | service/kubernetes ClusterIP 172.21.0.1 443/TCP 9d 72 | service/redis-master ClusterIP 172.21.232.61 6379/TCP 1h 73 | 74 | NAME READY UP-TO-DATE AVAILABLE AGE 75 | deployment.apps/guestbook-demo 3/3 3 3 1h 76 | deployment.apps/redis-master 1/1 1 1 1h 77 | 78 | NAME DESIRED CURRENT READY AGE 79 | replicaset.apps/guestbook-v1-7fc76dc46 3 3 3 1h 80 | replicaset.apps/redis-master-5d8b66464f 1 1 1 1h 81 | ``` 82 | 83 | > Note: The service type has changed (to `NodePort`) and a new port has been allocated (`31989` in this output case) to the guestbook service. All `redis-slave` resources have been removed. 84 | 85 | 1. View the guestbook 86 | 87 | Get the public IP of one of your nodes: 88 | 89 | ```console 90 | kubectl get nodes -o wide 91 | ``` 92 | 93 | Navigate to the IP address plus the node port that printed earlier. 94 | 95 | ## Scenario 2: Update the application using Helm 96 | 97 | In this section, we'll update the previously deployed `guestbook-demo` application by using Helm. 98 | 99 | Before we start, let's take a few minutes to see how Helm simplifies the process compared to using Kubernetes directly. Helm's use of a [template language](https://helm.sh/docs/chart_template_guide/getting_started/) provides great flexibility and power to chart authors, which removes the complexity to the chart user. In the guestbook example, we'll use the following capabilities of templating: 100 | 101 | * Values: An object that provides access to the values passed into the chart. An example of this is in `guestbook-service`, which contains the line `type: {{ .Values.service.type }}`. This line provides the capability to set the service type during an upgrade or install. 102 | * Control structures: Also called “actions” in template parlance, control structures provide the template author with the ability to control the flow of a template’s generation. An example of this is in `redis-slave-service`, which contains the line `{{- if .Values.redis.slaveEnabled -}}`. This line allows us to enable/disable the REDIS master/slave during an upgrade or install. 103 | 104 | The complete `redis-slave-service.yaml` file shown below, demonstrates how the file becomes redundant when the `slaveEnabled` flag is disabled and also how the port value is set. There are more examples of templating functionality in the other chart files. 105 | 106 | ```yaml 107 | {{- if .Values.redis.slaveEnabled -}} 108 | apiVersion: v1 109 | kind: Service 110 | metadata: 111 | name: redis-slave 112 | labels: 113 | app: redis 114 | role: slave 115 | spec: 116 | ports: 117 | - port: {{ .Values.redis.port }} 118 | targetPort: redis-server 119 | selector: 120 | app: redis 121 | role: slave 122 | {{- end }} 123 | ``` 124 | 125 | Enough talking about the theory. Now let's give it a go! 126 | 127 | 1. First, lets check the app we deployed in Lab 1 with Helm. This can be done by checking the Helm releases: 128 | 129 | ```console 130 | helm list -n helm-demo 131 | ``` 132 | 133 | Note that we specify the namespace. If not specified, it uses the current namespace context. You should see output similar to the following: 134 | 135 | ```console 136 | $ helm list -n helm-demo 137 | NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION 138 | guestbook-demo helm-demo 1 2020-02-24 18:08:02.017401264 +0000 UTC deployed guestbook-0.2.0 139 | ``` 140 | 141 | The `list` command provides the list of deployed charts (releases) giving information of chart version, namespace, number of updates (revisions) etc. 142 | 143 | 1. We now know the release is there from step 1., so we can update the application: 144 | 145 | ```console 146 | $ cd helm101/charts 147 | 148 | $ helm upgrade guestbook-demo ./guestbook --set redis.slaveEnabled=false,service.type=NodePort --namespace helm-demo 149 | Release "guestbook-demo" has been upgraded. Happy Helming! 150 | ... 151 | ``` 152 | 153 | A Helm upgrade takes an existing release and upgrades it according to the information you provide. You should see output similar to the following: 154 | 155 | ```console 156 | $ helm upgrade guestbook-demo ./guestbook --set redis.slaveEnabled=false,service.type=NodePort --namespace helm-demo 157 | Release "guestbook-demo" has been upgraded. Happy Helming! 158 | NAME: guestbook-demo 159 | LAST DEPLOYED: Tue Feb 25 14:23:27 2020 160 | NAMESPACE: helm-demo 161 | STATUS: deployed 162 | REVISION: 2 163 | TEST SUITE: None 164 | NOTES: 165 | 1. Get the application URL by running these commands: 166 | export NODE_PORT=$(kubectl get --namespace helm-demo -o jsonpath="{.spec.ports[0].nodePort}" services guestbook-demo) 167 | export NODE_IP=$(kubectl get nodes --namespace helm-demo -o jsonpath="{.items[0].status.addresses[0].address}") 168 | echo http://$NODE_IP:$NODE_PORT 169 | ``` 170 | 171 | The `upgrade` command upgrades the app to a specified version of a chart, removes the `redis-slave` resources, and updates the app `service.type` to `NodePort`. 172 | 173 | Check the updates, using `kubectl get all --namespace helm-demo`: 174 | 175 | ```console 176 | $ kubectl get all --namespace helm-demo 177 | NAME READY STATUS RESTARTS AGE 178 | pod/guestbook-demo-6c9cf8b9-dhqk9 1/1 Running 0 20h 179 | pod/guestbook-demo-6c9cf8b9-zddn2 1/1 Running 0 20h 180 | pod/redis-master-5d8b66464f-g7sh6 1/1 Running 0 20h 181 | 182 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 183 | service/guestbook-demo NodePort 172.21.43.244 3000:31202/TCP 20h 184 | service/redis-master ClusterIP 172.21.12.43 6379/TCP 20h 185 | 186 | NAME READY UP-TO-DATE AVAILABLE AGE 187 | deployment.apps/guestbook-demo 2/2 2 2 20h 188 | deployment.apps/redis-master 1/1 1 1 20h 189 | 190 | NAME DESIRED CURRENT READY AGE 191 | replicaset.apps/guestbook-demo-6c9cf8b9 2 2 2 20h 192 | replicaset.apps/redis-master-5d8b66464f 1 1 1 20h 193 | 194 | ``` 195 | 196 | > Note: The service type has changed (to `NodePort`) and a new port has been allocated (`31202` in this output case) to the guestbook service. All `redis-slave` resources have been removed. 197 | 198 | When you check the Helm release with `helm list -n helm-demo`, you will see the revision and date has been updated: 199 | 200 | ```console 201 | $ helm list -n helm-demo 202 | NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION 203 | guestbook-demo helm-demo 2 2020-02-25 14:23:27.06732381 +0000 UTC deployed guestbook-0.2.0 204 | ``` 205 | 206 | 1. View the guestbook 207 | 208 | Get the public IP of one of your nodes: 209 | 210 | ```console 211 | kubectl get nodes -o wide 212 | ``` 213 | 214 | Navigate to the IP address plus the node port that printed earlier. 215 | 216 | ## Conclusion 217 | 218 | Congratulations, you have now updated the applications! Helm does not require any manual changing of resources and is therefore so much easier to upgrade! All configurations can be set on the fly on the command line or by using override files. This is made possible from when the logic was added to the template files, which enables or disables the capability, depending on the flag set. 219 | 220 | Check out [Lab 3](../Lab3/README.md) to get an insight into revision management. 221 | -------------------------------------------------------------------------------- /docs/Lab3/README.md: -------------------------------------------------------------------------------- 1 | # Lab 3. Keeping track of the deployed application 2 | 3 | Let's say you deployed different release versions of your application (i.e., you upgraded the running application). How do you keep track of the versions and how can you do a rollback? 4 | 5 | ## Scenario 1: Revision management using Kubernetes 6 | 7 | In this part of the lab, we should illustrate revision management of `guestbook` by using Kubernetes directly, but we can't. This is because Kubernetes does not provide any support for revision management. The onus is on you to manage your systems and any updates or changes you make. However, we can use Helm to conduct revision management. 8 | 9 | ## Scenario 2: Revision management using Helm 10 | 11 | In this part of the lab, we illustrate revision management on the deployed application `guestbook-demo` by using Helm. 12 | 13 | With Helm, every time an install, upgrade, or rollback happens, the revision number is incremented by 1. The first revision number is always 1. Helm persists release metadata in Secrets (default) or ConfigMaps, stored in the Kubernetes cluster. Every time your release changes, it appends that to the existing data. This provides Helm with the capability to rollback to a previous release. 14 | 15 | Let's see how this works in practice. 16 | 17 | 1. Check the number of deployments: 18 | 19 | ```console 20 | helm history guestbook-demo -n helm-demo 21 | ``` 22 | 23 | You should see output similar to the following because we did an upgrade in [Lab 2](../Lab2/README.md) after the initial install in [Lab 1](../Lab1/README.md): 24 | 25 | ```console 26 | $ helm history guestbook-demo -n helm-demo 27 | REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 28 | 1 Mon Feb 24 18:08:02 2020 superseded guestbook-0.2.0 Install complete 29 | 2 Tue Feb 25 14:23:27 2020 deployed guestbook-0.2.0 Upgrade complete 30 | ``` 31 | 32 | 1. Roll back to the previous revision: 33 | 34 | In this rollback, Helm checks the changes that occured when upgrading from the revision 1 to revision 2. This information enables it to makes the calls to the Kubernetes API server, to update the deployed application as per the initial deployment - in other words with Redis slaves and using a load balancer. 35 | 36 | Rollback with this command: 37 | 38 | ```console 39 | helm rollback guestbook-demo 1 -n helm-demo 40 | ``` 41 | 42 | ```console 43 | $ helm rollback guestbook-demo 1 -n helm-demo 44 | Rollback was a success! Happy Helming! 45 | ``` 46 | 47 | Check the history again: 48 | 49 | ```console 50 | helm history guestbook-demo -n helm-demo 51 | ``` 52 | 53 | You should see output similar to the following: 54 | 55 | ```console 56 | $ helm history guestbook-demo -n helm-demo 57 | REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 58 | 1 Mon Feb 24 18:08:02 2020 superseded guestbook-0.2.0 Install complete 59 | 2 Tue Feb 25 14:23:27 2020 superseded guestbook-0.2.0 Upgrade complete 60 | 3 Tue Feb 25 14:53:45 2020 deployed guestbook-0.2.0 Rollback to 1 61 | ``` 62 | 63 | Check the rollback, using: 64 | 65 | ```console 66 | kubectl get all --namespace helm-demo 67 | ``` 68 | 69 | ```console 70 | $ kubectl get all --namespace helm-demo 71 | NAME READY STATUS RESTARTS AGE 72 | pod/guestbook-demo-6c9cf8b9-dhqk9 1/1 Running 0 20h 73 | pod/guestbook-demo-6c9cf8b9-zddn 1/1 Running 0 20h 74 | pod/redis-master-5d8b66464f-g7sh6 1/1 Running 0 20h 75 | pod/redis-slave-586b4c847c-tkfj5 1/1 Running 0 5m15s 76 | pod/redis-slave-586b4c847c-xxrdn 1/1 Running 0 5m15s 77 | 78 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 79 | service/guestbook-demo LoadBalancer 172.21.43.244 3000:31202/TCP 20h 80 | service/redis-master ClusterIP 172.21.12.43 6379/TCP 20h 81 | service/redis-slave ClusterIP 172.21.232.16 6379/TCP 5m15s 82 | 83 | NAME READY UP-TO-DATE AVAILABLE AGE 84 | deployment.apps/guestbook-demo 2/2 2 2 20h 85 | deployment.apps/redis-master 1/1 1 1 20h 86 | deployment.apps/redis-slave 2/2 2 2 5m15s 87 | 88 | NAME DESIRED CURRENT READY AGE 89 | replicaset.apps/guestbook-demo-26c9cf8b9 2 2 2 20h 90 | replicaset.apps/redis-master-5d8b66464f 1 1 1 20h 91 | replicaset.apps/redis-slave-586b4c847c 2 2 2 5m15s 92 | ``` 93 | 94 | You can see from the output that the app service is the service type of `LoadBalancer` again and the Redis master/slave deployment has returned. 95 | This shows a complete rollback from the upgrade in [Lab 2](../Lab2/README.md) 96 | 97 | ## Conclusion 98 | 99 | From this lab, we can say that Helm does revision management well and Kubernetes does not have the capability built in! You might be wondering why we need `helm rollback` when you could just re-run the `helm upgrade` from a previous version. And that's a good question. Technically, you should end up with the same resources (with same parameters) deployed. However, the advantage of using `helm rollback` is that helm manages (ie. remembers) all of the variations/parameters of the previous `helm install\upgrade` for you. Doing the rollback via a `helm upgrade` requires you (and your entire team) to manually track how the command was previously executed. That's not only tedious but very error prone. It is much easier, safer and reliable to let Helm manage all of that for you and all you need to do it tell it which previous version to go back to, and it does the rest. 100 | 101 | [Lab 4](../Lab4/README.md) awaits. 102 | -------------------------------------------------------------------------------- /docs/Lab4/README.md: -------------------------------------------------------------------------------- 1 | # Lab 4. Share Helm Charts 2 | 3 | A key aspect of providing an application means sharing with others. Sharing can be direct counsumption (by users or in CI/CD pipelines) or as a dependency for other charts. If people can't find your app then they can't use it. 4 | 5 | A means of sharing is a chart repository, which is a location where packaged charts can be stored and shared. As the chart repository only applies to Helm, we will just look at the usage and storage of Helm charts. 6 | 7 | ## Using charts from a public repository 8 | 9 | Helm charts can be available on a remote repository or in a local environment/repository. The remote repositories can be public like [Bitnami Charts](https://github.com/bitnami/charts) or [IBM Helm Charts](https://github.com/IBM/charts), or hosted repositories like on Google Cloud Storage or GitHub. Refer to [Helm Chart Repository Guide](https://helm.sh/docs/topics/chart_repository/) for more details. You can learn more about the structure of a chart repository by examining the [chart index file](https://raw.githubusercontent.com/IBM/helm101/master/repo/stable/index.yaml) in this lab. 10 | 11 | In this part of the lab, we show you how to install the `guestbook` chart from the [Helm101 repo](https://ibm.github.io/helm101/). 12 | 13 | 1. Check the repositories configured on your system: 14 | 15 | ```console 16 | helm repo list 17 | ``` 18 | 19 | The output should be similar to the following: 20 | 21 | ```console 22 | $ helm repo list 23 | Error: no repositories to show 24 | ``` 25 | 26 | > Note: Chart repositories are not installed by default with Helm v3. It is expected that you add the repositories for the charts you want to use. The [Helm Hub](https://hub.helm.sh) provides a centralized search for publicly available distributed charts. Using the hub you can identify the chart with its hosted repository and then add it to your local respoistory list. The [Helm chart repository](https://github.com/helm/charts) like Helm v2 is in "maintenance mode" and will be deprecated by November 13, 2020. See the [project status](https://github.com/helm/charts#status-of-the-project) for more details. 27 | 28 | 1. Add `helm101` repo: 29 | 30 | ```console 31 | helm repo add helm101 https://ibm.github.io/helm101/ 32 | ``` 33 | 34 | Should generate an output as follows: 35 | 36 | ```console 37 | $ helm repo add helm101 https://ibm.github.io/helm101/ 38 | "helm101" has been added to your repositories 39 | ``` 40 | 41 | You can also search your repositories for charts by running the following command: 42 | 43 | ```console 44 | helm search repo helm101 45 | ``` 46 | 47 | ```console 48 | $ helm search repo helm101 49 | NAME CHART VERSION APP VERSION DESCRIPTION 50 | helm101/guestbook 0.2.1 A Helm chart to deploy Guestbook three tier web... 51 | ``` 52 | 53 | 1. Install the chart 54 | 55 | As mentioned we are going to install the `guestbook` chart from the [Helm101 repo](https://ibm.github.io/helm101/). As the repo is added to our local respoitory list we can reference the chart using the `repo name/chart name`, in other words `helm101/guestbook`. To see this in action, you will install the application to a new namespace called `repo-demo`. 56 | 57 | If the `repo-demo` namespace does not exist, create it using: 58 | 59 | ```console 60 | kubectl create namespace repo-demo 61 | ``` 62 | 63 | Now install the chart using this command: 64 | 65 | ```console 66 | helm install guestbook-demo helm101/guestbook --namespace repo-demo 67 | ``` 68 | 69 | The output should be similar to the following: 70 | 71 | ```console 72 | $helm install guestbook-demo helm101/guestbook --namespace repo-demo 73 | NAME: guestbook-demo 74 | LAST DEPLOYED: Tue Feb 25 15:40:17 2020 75 | NAMESPACE: repo-demo 76 | STATUS: deployed 77 | REVISION: 1 78 | TEST SUITE: None 79 | NOTES: 80 | 1. Get the application URL by running these commands: 81 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 82 | You can watch the status of by running 'kubectl get svc -w guestbook-demo --namespace repo-demo' 83 | export SERVICE_IP=$(kubectl get svc --namespace repo-demo guestbook-demo -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 84 | echo http://$SERVICE_IP:3000 85 | ``` 86 | 87 | Check that release deployed as expected as follows: 88 | 89 | ```console 90 | $ helm list -n repo-demo 91 | NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION 92 | guestbook-demo repo-demo 1 2020-02-25 15:40:17.627745329 +0000 UTC deployed guestbook-0.2.1 93 | ``` 94 | 95 | ## Conclusion 96 | 97 | This lab provided you with a brief introduction to the Helm repositories to show how charts can be installed. The ability to share your chart means ease of use to both you and your consumers. 98 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Helm 101 2 | 3 | [Helm](https://helm.sh/) is often described as the Kubernetes application package manager. So, what does Helm give you over using `kubectl` directly? 4 | 5 | ## Objectives 6 | 7 | These labs provide an insight on the advantages of using Helm over using Kubernetes directly through `kubectl`. In several of the labs there are two scenarios. The first scenario gives an example of how to perform the task using `kubectl`, the second scenario, using `helm`. When you complete all the labs, you'll: 8 | 9 | * Understand the core concepts of Helm 10 | * Understand the advantages of deployment using Helm over Kubernetes directly, looking at: 11 | * Application management 12 | * Updates 13 | * Configuration 14 | * Revision management 15 | * Repositories and chart sharing 16 | 17 | ## Prerequisites 18 | 19 | * Have a running Kubernetes cluster. See the [IBM Cloud Kubernetes Service](https://cloud.ibm.com/docs/containers/cs_tutorials.html#cs_cluster_tutorial) or [Kubernetes Getting Started Guide](https://kubernetes.io/docs/setup/) for details about creating a cluster. 20 | * Have Helm installed and initialized with the Kubernetes cluster. See [Installing Helm on IBM Cloud Kubernetes Service](Lab0/README.md) or the [Helm Quickstart Guide](https://helm.sh/docs/intro/quickstart/) for getting started with Helm. 21 | 22 | ## Helm Overview 23 | 24 | Helm is a tool that streamlines installation and management of Kubernetes applications. It uses a packaging format called "charts", which are a collection of files that describe Kubernetes resources. It can run anywhere (laptop, CI/CD, etc.) and is available for various operating systems, like OSX, Linux and Windows. 25 | 26 | ![helm-architecture](images/helm-architecture.png) 27 | 28 | Helm 3 pivoted from the [Helm 2 client-server architecture](https://github.com/IBM/helm101/tree/helm-v2/tutorial#helm-overview) to a client architecture. The client is still called `helm` and, there is an improved Go library which encapsulates the Helm logic so that it can be leveraged by different clients. The client is a CLI which users interact with to perform different operations like install/upgrade/delete etc. The client interacts with the Kubernetes API server and the chart repository. It renders Helm template files into Kubernetes manifest files which it uses to perform operations on the Kubernetes cluster via the Kubernetes API. See the [Helm Architecture](https://helm.sh/docs/topics/architecture/) for more details. 29 | 30 | A [chart](https://helm.sh/docs/topics/charts/) is organized as a collection of files inside of a directory where the directory name is the name of the chart. It contains template YAML files which facilitates providing configuration values at runtime and eliminates the need of modifying YAML files. These templates provide programming logic as they are based on the [Go template language](https://golang.org/pkg/text/template/), functions from the [Sprig lib](https://github.com/Masterminds/sprig) and other [specialized functions](https://helm.sh/docs/howto/charts_tips_and_tricks/#know-your-template-functions). 31 | 32 | The chart repository is a location where packaged charts can be stored and shared. This is akin to the image repository in Docker. Refer to [The Chart Repository Guide](https://helm.sh/docs/topics/chart_repository/) for more details. 33 | 34 | ## Helm Abstractions 35 | 36 | Helm terms: 37 | 38 | * Chart - It contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. A chart is basically a package of pre-configured Kubernetes resources. 39 | * Config - Contains configuration information that can be merged into a packaged chart to create a releasable object. 40 | * helm - Helm client. It renders charts into manifest files. It interacts directly with the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) server to install, upgrade, query, and remove Kubernetes resources. 41 | * Release - An instance of a chart running in a Kubernetes cluster. 42 | * Repository - Place where charts reside and can be shared with others. 43 | 44 | To get started, head on over to [Lab 1](Lab1/README.md). 45 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | 4 | 5 | 6 | 7 | ### Workshop 8 | 9 | * [Lab 0](Lab0/README.md) 10 | * [Lab 1](Lab1/README.md) 11 | * [Lab 2](Lab2/README.md) 12 | * [Lab 3](Lab3/README.md) 13 | * [Lab 4](Lab4/README.md) 14 | 15 | ### Resources 16 | 17 | * [IBM Developer](https://developer.ibm.com) 18 | -------------------------------------------------------------------------------- /docs/images/guestbook-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/helm101/8e99de31f6e26cb0988b20a29da038344e5c4f35/docs/images/guestbook-page.png -------------------------------------------------------------------------------- /docs/images/helm-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/helm101/8e99de31f6e26cb0988b20a29da038344e5c4f35/docs/images/helm-architecture.png -------------------------------------------------------------------------------- /docs/index.yaml: -------------------------------------------------------------------------------- 1 | # Do not delete this file even though there is a duplicate in the repo/stable folder. 2 | # For the "helm repo add" command to work with a Helm chart repo in GH, the index 3 | # file must reside in the root of the repo. 4 | apiVersion: v1 5 | entries: 6 | guestbook: 7 | - apiVersion: v1 8 | created: "2020-02-20T14:45:38.552869382Z" 9 | description: A Helm chart to deploy Guestbook three tier web application. 10 | digest: 0750784ba35fb1ec808d877ea1b61b0869db2ba436950319f22aa8d932899480 11 | name: guestbook 12 | urls: 13 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.2.1.tgz 14 | version: 0.2.1 15 | - apiVersion: v1 16 | created: "2019-02-21T14:09:27.965528851Z" 17 | description: A Helm chart to deploy Guestbook three tier web application. 18 | digest: 74d7c81b83aeea22feb3c4710f86c42b5be61e3783da5fb649edd66f3df55f90 19 | name: guestbook 20 | urls: 21 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.2.0.tgz 22 | version: 0.2.0 23 | - apiVersion: v1 24 | created: "2018-05-10T21:50:41.837568406-04:00" 25 | description: A Helm chart to deploy Guestbook three tier web application. 26 | digest: 7f186687f43008ed68e9e4a09aa4e45586e2d6ed5f85287c64bda3f5a7ea4d12 27 | name: guestbook 28 | urls: 29 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.1.0.tgz 30 | version: 0.1.0 31 | generated: "2020-02-20T14:45:38.550903527Z" 32 | -------------------------------------------------------------------------------- /index.yaml: -------------------------------------------------------------------------------- 1 | # Do not delete this file even though there is a duplicate in the repo/stable folder. 2 | # For the "helm repo add" command to work with a Helm chart repo in GH, the index 3 | # file must reside in the root of the repo. 4 | apiVersion: v1 5 | entries: 6 | guestbook: 7 | - apiVersion: v1 8 | created: "2020-02-20T14:45:38.552869382Z" 9 | description: A Helm chart to deploy Guestbook three tier web application. 10 | digest: 0750784ba35fb1ec808d877ea1b61b0869db2ba436950319f22aa8d932899480 11 | name: guestbook 12 | urls: 13 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.2.1.tgz 14 | version: 0.2.1 15 | - apiVersion: v1 16 | created: "2019-02-21T14:09:27.965528851Z" 17 | description: A Helm chart to deploy Guestbook three tier web application. 18 | digest: 74d7c81b83aeea22feb3c4710f86c42b5be61e3783da5fb649edd66f3df55f90 19 | name: guestbook 20 | urls: 21 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.2.0.tgz 22 | version: 0.2.0 23 | - apiVersion: v1 24 | created: "2018-05-10T21:50:41.837568406-04:00" 25 | description: A Helm chart to deploy Guestbook three tier web application. 26 | digest: 7f186687f43008ed68e9e4a09aa4e45586e2d6ed5f85287c64bda3f5a7ea4d12 27 | name: guestbook 28 | urls: 29 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.1.0.tgz 30 | version: 0.1.0 31 | generated: "2020-02-20T14:45:38.550903527Z" 32 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Project information 2 | site_name: Helm 101 3 | site_url: https://ibm.github.io/helm101 4 | site_author: IBM Developer 5 | 6 | # Repository 7 | repo_name: helm101 8 | repo_url: https://github.com/ibm/helm101 9 | edit_uri: edit/master/docs 10 | 11 | # Navigation 12 | nav: 13 | - Welcome: 14 | - About the workshop: README.md 15 | - Workshop: 16 | - Lab 0. Installing Helm on IKS: Lab0/README.md 17 | - Lab 1. Deploy with Helm: Lab1/README.md 18 | - Lab 2. Make changes with Helm: Lab2/README.md 19 | - Lab 3. Keeping track of the deployed application: Lab3/README.md 20 | - Lab 4. Share Helm Charts: Lab4/README.md 21 | 22 | ## DO NOT CHANGE BELOW THIS LINE 23 | 24 | # Copyright 25 | copyright: Copyright © 2020 IBM Developer 26 | 27 | # Theme 28 | theme: 29 | name: material 30 | font: 31 | text: IBM Plex Sans 32 | code: IBM Plex Mono 33 | icon: 34 | logo: material/library 35 | features: 36 | - navigation.tabs 37 | #- navigation.instant 38 | palette: 39 | scheme: default 40 | primary: blue 41 | accent: blue 42 | 43 | # Plugins 44 | plugins: 45 | - search 46 | 47 | # Customization 48 | extra: 49 | social: 50 | - icon: fontawesome/brands/github 51 | link: https://github.com/ibm 52 | - icon: fontawesome/brands/twitter 53 | link: https://twitter.com/ibmdeveloper 54 | - icon: fontawesome/brands/linkedin 55 | link: https://www.linkedin.com/company/ibm/ 56 | - icon: fontawesome/brands/youtube 57 | link: https://www.youtube.com/user/developerworks 58 | - icon: fontawesome/brands/dev 59 | link: https://dev.to/ibmdeveloper 60 | 61 | # Extensions 62 | markdown_extensions: 63 | - abbr 64 | - admonition 65 | - attr_list 66 | - def_list 67 | - footnotes 68 | - meta 69 | - toc: 70 | permalink: true 71 | - pymdownx.arithmatex: 72 | generic: true 73 | - pymdownx.betterem: 74 | smart_enable: all 75 | - pymdownx.caret 76 | - pymdownx.critic 77 | - pymdownx.details 78 | - pymdownx.emoji: 79 | emoji_index: !!python/name:materialx.emoji.twemoji 80 | emoji_generator: !!python/name:materialx.emoji.to_svg 81 | - pymdownx.highlight 82 | - pymdownx.inlinehilite 83 | - pymdownx.keys 84 | - pymdownx.mark 85 | - pymdownx.smartsymbols 86 | - pymdownx.snippets: 87 | check_paths: true 88 | - pymdownx.superfences: 89 | custom_fences: 90 | - name: mermaid 91 | class: mermaid 92 | format: !!python/name:pymdownx.superfences.fence_code_format 93 | - pymdownx.tabbed 94 | - pymdownx.tasklist: 95 | custom_checkbox: true 96 | - pymdownx.tilde 97 | -------------------------------------------------------------------------------- /presentation/Helm.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/helm101/8e99de31f6e26cb0988b20a29da038344e5c4f35/presentation/Helm.pptx -------------------------------------------------------------------------------- /presentation/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | -------------------------------------------------------------------------------- /presentation/demosteps.md: -------------------------------------------------------------------------------- 1 | # Demo steps 2 | 3 | Provide steps to deploy, upgrade and rollback the guestbook chart. 4 | 5 | ## guestbook chart deployment 6 | 7 | Check existing installation of Helm chart: 8 | 9 | ```bash 10 | helm ls 11 | ``` 12 | 13 | Check what repo do you have: 14 | 15 | ```bash 16 | helm repo list 17 | ``` 18 | 19 | Add repo: 20 | 21 | ```bash 22 | helm repo add helm101 https://ibm.github.io/helm101/ 23 | ``` 24 | 25 | Verify that helm101/guestbook is now in your repo: 26 | 27 | ```bash 28 | helm repo list 29 | helm search helm101 30 | ``` 31 | 32 | Deploy: 33 | 34 | ```bash 35 | helm install helm101/guestbook --name myguestbook --set service.type=NodePort 36 | ``` 37 | 38 | Follow the output instructions to see your guestbook application. 39 | 40 | *Note: For chart v0.1.0, the service type is set as `--set serviceType=NodePort`.* 41 | 42 | Verify that your guestbook chart is deployed: 43 | 44 | ```bash 45 | helm ls 46 | ``` 47 | 48 | Check chart release history: 49 | 50 | ```bash 51 | helm history myguestbook 52 | ``` 53 | 54 | ## guestbook chart deployment upgrade 55 | 56 | Upgrade the deployment: 57 | 58 | ```bash 59 | helm upgrade myguestbook helm101/guestbook 60 | ``` 61 | 62 | Check the history: 63 | 64 | ```bash 65 | helm history myguestbook 66 | ``` 67 | 68 | ## guestbook chart deployment rollback 69 | 70 | Rollback to release 1: 71 | 72 | ```bash 73 | helm rollback myguestbook 1 74 | ``` 75 | 76 | Check the history: 77 | 78 | ```bash 79 | helm history myguestbook 80 | ``` 81 | -------------------------------------------------------------------------------- /repo/stable/guestbook-0.1.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/helm101/8e99de31f6e26cb0988b20a29da038344e5c4f35/repo/stable/guestbook-0.1.0.tgz -------------------------------------------------------------------------------- /repo/stable/guestbook-0.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/helm101/8e99de31f6e26cb0988b20a29da038344e5c4f35/repo/stable/guestbook-0.2.0.tgz -------------------------------------------------------------------------------- /repo/stable/guestbook-0.2.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/helm101/8e99de31f6e26cb0988b20a29da038344e5c4f35/repo/stable/guestbook-0.2.1.tgz -------------------------------------------------------------------------------- /repo/stable/index.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | entries: 3 | guestbook: 4 | - apiVersion: v1 5 | created: "2020-02-20T14:45:38.552869382Z" 6 | description: A Helm chart to deploy Guestbook three tier web application. 7 | digest: 0750784ba35fb1ec808d877ea1b61b0869db2ba436950319f22aa8d932899480 8 | name: guestbook 9 | urls: 10 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.2.1.tgz 11 | version: 0.2.1 12 | - apiVersion: v1 13 | created: "2019-02-21T14:09:27.965528851Z" 14 | description: A Helm chart to deploy Guestbook three tier web application. 15 | digest: 74d7c81b83aeea22feb3c4710f86c42b5be61e3783da5fb649edd66f3df55f90 16 | name: guestbook 17 | urls: 18 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.2.0.tgz 19 | version: 0.2.0 20 | - apiVersion: v1 21 | created: "2018-05-10T21:50:41.837568406-04:00" 22 | description: A Helm chart to deploy Guestbook three tier web application. 23 | digest: 7f186687f43008ed68e9e4a09aa4e45586e2d6ed5f85287c64bda3f5a7ea4d12 24 | name: guestbook 25 | urls: 26 | - https://raw.githubusercontent.com/ibm/helm101/master/repo/stable/guestbook-0.1.0.tgz 27 | version: 0.1.0 28 | generated: "2020-02-20T14:45:38.550903527Z" 29 | --------------------------------------------------------------------------------