<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://training-course-material.com/index.php?action=history&amp;feed=atom&amp;title=Kubernetes_%28KB%29</id>
	<title>Kubernetes (KB) - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://training-course-material.com/index.php?action=history&amp;feed=atom&amp;title=Kubernetes_%28KB%29"/>
	<link rel="alternate" type="text/html" href="https://training-course-material.com/index.php?title=Kubernetes_(KB)&amp;action=history"/>
	<updated>2026-05-13T23:13:06Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://training-course-material.com/index.php?title=Kubernetes_(KB)&amp;diff=87731&amp;oldid=prev</id>
		<title>Kbaran: /* Cluster initialisation */</title>
		<link rel="alternate" type="text/html" href="https://training-course-material.com/index.php?title=Kubernetes_(KB)&amp;diff=87731&amp;oldid=prev"/>
		<updated>2023-10-04T09:45:17Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Cluster initialisation&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en-GB&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 09:45, 4 October 2023&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l66&quot;&gt;Line 66:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 66:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* start cluster networking and check the status once again&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* start cluster networking and check the status once again&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;kubectl apply -f &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&quot;&lt;/del&gt;https://&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;cloud&lt;/del&gt;.weave.&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;works&lt;/del&gt;/&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;k8s/net?k8s&lt;/del&gt;-&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;version=$(kubectl version | base64 | tr &lt;/del&gt;-&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;d &#039;\n&#039;)&quot;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;kubectl apply -f https://&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;github&lt;/ins&gt;.&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;com/weaveworks/&lt;/ins&gt;weave&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;/releases/download/v2.8&lt;/ins&gt;.&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;1&lt;/ins&gt;/&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;weave&lt;/ins&gt;-&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;daemonset&lt;/ins&gt;-&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;k8s.yaml&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Kbaran</name></author>
	</entry>
	<entry>
		<id>https://training-course-material.com/index.php?title=Kubernetes_(KB)&amp;diff=84156&amp;oldid=prev</id>
		<title>Kbaran at 23:16, 20 October 2021</title>
		<link rel="alternate" type="text/html" href="https://training-course-material.com/index.php?title=Kubernetes_(KB)&amp;diff=84156&amp;oldid=prev"/>
		<updated>2021-10-20T23:16:49Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Category:Docker]]&lt;br /&gt;
[[Category:course_code_dockcm]]&lt;br /&gt;
&lt;br /&gt;
{{Copyright Notice}}&lt;br /&gt;
&lt;br /&gt;
== Author ==&lt;br /&gt;
* [http://www.kamilbaran.pl Kamil Baran]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment preparation - local virtual machines ==&lt;br /&gt;
* Change &amp;#039;&amp;#039;server-s1, server-s2 and server-s3&amp;#039;&amp;#039; network configuration from DHCP into static IP (edit &amp;#039;&amp;#039;&amp;#039;/etc/network/interfaces&amp;#039;&amp;#039;&amp;#039;). &lt;br /&gt;
* Verify the host names and IP addresses in &amp;#039;&amp;#039;&amp;#039;/etc/hostname&amp;#039;&amp;#039;&amp;#039; and &amp;#039;&amp;#039;&amp;#039;/etc/hosts&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Remove SWAP partition from &amp;#039;&amp;#039;&amp;#039;/etc/fstab&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
# on your client machine generate keys, then transfer public key to server-s1, server-s2, server-s2&lt;br /&gt;
$ ssh-keygen&lt;br /&gt;
$ ssh-copy-id student@server-s1&lt;br /&gt;
$ ssh-copy-id student@server-s2&lt;br /&gt;
$ ssh-copy-id student@server-s2&lt;br /&gt;
# check the connection&lt;br /&gt;
$ ssh student@server-s1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to create a secure Kubernetes cluster? ==&lt;br /&gt;
=== Docker installation ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -&lt;br /&gt;
sudo add-apt-repository &amp;quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable&amp;quot;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; apt-cache madison docker-ce&lt;br /&gt;
sudo apt-get install -y docker-ce=5:20.10.8~3-0~ubuntu-focal&lt;br /&gt;
sudo usermod -aG docker nobleprog&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* more info: docs.docker.com/engine/installation/linux/docker-ce/ubuntu/ and kubernetes.io/docs/setup/production-environment/container-runtimes/&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Kubernetes installation ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y apt-transport-https bash-completion curl&lt;br /&gt;
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -&lt;br /&gt;
sudo add-apt-repository &amp;quot;deb http://apt.kubernetes.io/ kubernetes-xenial main&amp;quot;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y kubeadm=1.21.5-00 kubectl=1.21.5-00 kubelet=1.21.5-00&lt;br /&gt;
source &amp;lt;(kubectl completion bash) &amp;amp;&amp;amp; echo &amp;quot;source &amp;lt;(kubectl completion bash)&amp;quot; &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
source &amp;lt;(kubeadm completion bash) &amp;amp;&amp;amp; echo &amp;quot;source &amp;lt;(kubeadm completion bash)&amp;quot; &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* more info: kubernetes.io/docs/setup/independent/create-cluster-kubeadm/&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cluster initialisation ===&lt;br /&gt;
* initialise the master on server-s0 and configure kubectl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo kubeadm init&lt;br /&gt;
mkdir -p $HOME/.kube&lt;br /&gt;
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config&lt;br /&gt;
sudo chown $(id -u):$(id -g) $HOME/.kube/config&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* check the status of the master node and pods running in the kube-system namespace&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl get node,pod --namespace=kube-system&lt;br /&gt;
kubectl describe pod --namespace=kube-system kube-dns-86f...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* start cluster networking and check the status once again&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f &amp;quot;https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d &amp;#039;\n&amp;#039;)&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* optionally allow pods to be scheduled on the master node (useful if you need a single-node Kubernetes cluster)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl taint nodes --all node-role.kubernetes.io/master-&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* join server-s1 and server-s2 to the cluster as worker nodes (aka minions) &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh ubuntu@server-s1&lt;br /&gt;
sudo kubeadm join --token bf37a8... 11.0.2.10:6443 --discovery-token-ca-cert-hash sha256:9dfed...&lt;br /&gt;
exit&lt;br /&gt;
ssh ubuntu@server-s2&lt;br /&gt;
sudo kubeadm join --token bf37a8... 11.0.2.10:6443 --discovery-token-ca-cert-hash sha256:9dfed...&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* check the status of all nodes&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl get nodes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* more info: kubernetes.io/docs/setup/independent/create-cluster-kubeadm/&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Deploying sample applications in Kubernetes cluster ==&lt;br /&gt;
&lt;br /&gt;
=== Deploy Training App ===&lt;br /&gt;
* deploy an app by creating Deployment and Service resource, then check the status of both objects&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;YAML&amp;quot;&amp;gt;&lt;br /&gt;
apiVersion: apps/v1&lt;br /&gt;
kind: Deployment&lt;br /&gt;
metadata:&lt;br /&gt;
  name: training&lt;br /&gt;
  labels:&lt;br /&gt;
    app: training&lt;br /&gt;
spec:&lt;br /&gt;
  selector:&lt;br /&gt;
    matchLabels:&lt;br /&gt;
      app: training&lt;br /&gt;
  replicas: 3&lt;br /&gt;
  template:&lt;br /&gt;
    metadata:&lt;br /&gt;
      labels:&lt;br /&gt;
        app: training&lt;br /&gt;
    spec:&lt;br /&gt;
      containers:&lt;br /&gt;
      - name: training&lt;br /&gt;
        image: kamilbaran/training:app-v1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;YAML&amp;quot;&amp;gt;&lt;br /&gt;
apiVersion: v1&lt;br /&gt;
kind: Service&lt;br /&gt;
metadata:&lt;br /&gt;
  name: training&lt;br /&gt;
  labels:&lt;br /&gt;
    app: training&lt;br /&gt;
spec:&lt;br /&gt;
  type: ClusterIP&lt;br /&gt;
  selector:&lt;br /&gt;
    app: training&lt;br /&gt;
  ports:&lt;br /&gt;
  - port: 80&lt;br /&gt;
    protocol: TCP&lt;br /&gt;
    targetPort: 80&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-base.yaml&lt;br /&gt;
kubectl get service,deployment,pod&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* run the following loop in the second terminal window to see the application responses&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
while :; &lt;br /&gt;
do&lt;br /&gt;
  ((i++))&lt;br /&gt;
  curl --connect-timeout 2 $(kubectl get service -o go-template=&amp;#039;{{(.spec.clusterIP)}}&amp;#039; training):80/?count=$i;&lt;br /&gt;
  sleep 1;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* scale the deployment up to five pods by changing spec.replicas in training-app-base.yaml and re-applying the file or by running the following command&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl scale deployment --replicas=5 simple-app&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Rolling update ====&lt;br /&gt;
* imagine that you have the newer version of the application and you want to replace the current one&lt;br /&gt;
** current one is based on training-app-base.yaml&lt;br /&gt;
** new version is using image kamilbaran/training:app-v2&lt;br /&gt;
** make sure that you have multiple replicas of the current version&lt;br /&gt;
* update the deployment by changing .spec.template.spec.containers[0].image in training-app-base.yaml and re-applying the file or by running the following command&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl set image deployment/training training=kamilbaran/training:app-v2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* before and after every step you can display all objects that are affected&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl get deployment,replicaset,pod -l app=training&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* run the commands below to check the current status&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl rollout status deployment training&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* to go back to the previous working configuration and check the status once again&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl rollout undo deployment training&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Exercise&amp;#039;&amp;#039;&amp;#039;: upgrade the app to image kamilbaran/training:app-v3&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Blue-Green deployment ====&lt;br /&gt;
* using B/G deployment in Kubernetes is easy and helpful when you need to upgrade many components of your app at once&lt;br /&gt;
* to achieve this, you will need two deployments (training and training-new) and one service (training)&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
* the general idea is as follows:&lt;br /&gt;
# create the current version that needs to be updated (use training-app-base.yaml as a starting point)&lt;br /&gt;
# before creating the second deployment (training-new) use labels and selectors to make sure that the service will use pods only from the first deployment (training)&lt;br /&gt;
# create the second deployment (training-new) and wait for all pods being available&lt;br /&gt;
# change the selectors in the service to use pods only from the second deployment (training-new)&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* blue/green deployment can be implemented in Kubernetes cluster as follows:&lt;br /&gt;
** start the current/base version&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-base.yaml&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
** before and after every step you can display all objects that are affected (keep an eye also at the results returned by the loop)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl get service,deployment,pod -l app=training -L app -L release -o wide&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
** before creating the second deployment (training-new) use labels and selectors to make sure that the service will use pods only from the first deployment (training)&lt;br /&gt;
** step 1: add new label release=stable to deployment&lt;br /&gt;
** step 2: change service selector to include the release label&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-bg-step1.yaml&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-bg-step2.yaml&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
** step 3: create the second deployment training-new (it is using an image with the new version and two labels: app=training, release=new&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f http://www.kamilbaran.pl/download/kubernetes/training-app-bg-step3.yaml&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
** now the service is using still only pods from training service&lt;br /&gt;
** step 4: change the value of label release from stable to new to switch to the pods with a new version&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-bg-step4.yaml&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
** at this point service is using the new version, but there are still two deployments and pods that are wasting resources&lt;br /&gt;
** you should clean-up the cluster, and this is one of the possible ways:&lt;br /&gt;
** step 5: update the training deployment to new version&lt;br /&gt;
** step 6: switch the service to use the release=stable selector&lt;br /&gt;
** step 7: delete or downscale training-new to zero and leave it for the next image update&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-bg-step5.yaml&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-bg-step6.yaml&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-bg-step7.yaml&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Canary deployment ====&lt;br /&gt;
* using Canary deployment in Kubernetes is useful if you want to try the new version on a selected subset of requests&lt;br /&gt;
* for example, let&amp;#039;s say that you want to send only 10% of all requests to the new version of your app and if everything is OK to increase the ratio from 9:1 to 7:3&lt;br /&gt;
* to achieve this, you will need two deployments (training and training-new) and one service (training)&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
* the general idea is as follows:&lt;br /&gt;
# create the current version that needs to be updated (use training-app-base.yaml as a starting point)&lt;br /&gt;
# before creating the second deployment (training-new) use labels and selectors to make sure that the service will use pods only from the first deployment (training)&lt;br /&gt;
# create the second deployment (training-new) and wait for all pods being available&lt;br /&gt;
# change the selectors in the service to &amp;#039;&amp;#039;&amp;#039;use pods from both deployments&amp;#039;&amp;#039;&amp;#039; in the same time&lt;br /&gt;
# modify the ratio by changing the number of pods in the first and second deployment (you will send 20% of requests to the new version if you start eight pods in the first deployment and only two pods in the second deployment)&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Exercise&amp;#039;&amp;#039;&amp;#039;: write Canary deployment step-by-step config files for the Training app (like in the B/G deployment presented above)&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Deploy Wordpress ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl create secret generic mysql-pass --from-literal=password=NobleProg&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/kube-wp-volumes.yaml&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/kube-wp-mysql.yaml&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/kube-wp-wordpress.yaml&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* display all related objects to Wordpress&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl get secret,service,deployment,pod,pvc,pv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* display logs of mysql container running in mysql-bcc89f687-hn2tl pod&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl logs mysql-bcc89f687-hn2tl mysql&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* get more details about the current state of wordpress-57955d6d4f-9qxvz pod (including pod related events)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl describe pod wordpress-57955d6d4f-9qxvz&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit persistent volume to increase it&amp;#039;s size&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl edit pv pv-1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* delete pod with mysql to check if the app is able to persist the data&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl delete pod mysql-bcc89f687-hn2tl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Kubernetes objects ==&lt;br /&gt;
=== StatefulSet ===&lt;br /&gt;
&lt;br /&gt;
* deploy sample StatefulSet and related Service&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/kube-statefulset.yaml&lt;br /&gt;
kubectl get service,statefulset,pod -o wide -l example=StatefulSet&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* start a pod based on the alpine image (or attach to existing one) and install curl&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl run -i -t alpine --image=alpine --namespace=default&lt;br /&gt;
apk add --update curl&lt;br /&gt;
kubectl attach -i -t alpine-695c86655b-xfnzg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* use curl to access simple-app pods&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
curl simple-app-0.simple-app&lt;br /&gt;
curl simple-app-0.simple-app.default.svc.cluster.local&lt;br /&gt;
curl simple-app.default.svc.cluster.local&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* remove everything related to StatefulSet example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl delete all -l example=StatefulSet&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Exercise&amp;#039;&amp;#039;&amp;#039;: start the MongoDB Counter App using StatefulSet with three replicas&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== NetworkPolicy ===&lt;br /&gt;
&lt;br /&gt;
* deploy sample Training App and make sure there are no existing network policies&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-app-base.yaml&lt;br /&gt;
kubectl get svc,deploy,pod,networkpolicy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* use wget to access deployed application from another container&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl run alpine -it --rm --image=alpine /bin/sh&lt;br /&gt;
wget --spider --timeout 1 training&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* apply network policy that will allow connections to Training App only from pods labeled trusted=yes&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-network-policy.yaml&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* try to access the application again, then change the label trusted=yes and try one more time&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
wget --spider --timeout 1 training&lt;br /&gt;
kubectl label pod --overwrite alpine-... trusted=&amp;quot;yes&amp;quot;&lt;br /&gt;
wget --spider --timeout 1 training&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* more info: kubernetes.io/docs/concepts/services-networking/network-policies/&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ingress ===&lt;br /&gt;
&lt;br /&gt;
* deploy Nginx as Ingress Controller&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v1.3.0/install/common/ns-and-sa.yaml&lt;br /&gt;
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v1.3.0/install/common/default-server-secret.yaml&lt;br /&gt;
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v1.3.0/install/common/nginx-config.yaml&lt;br /&gt;
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v1.3.0/install/rbac/rbac.yaml&lt;br /&gt;
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v1.3.0/install/daemon-set/nginx-ingress.yaml&lt;br /&gt;
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v1.3.0/install/service/nodeport.yaml (or /loadbalancer.yaml)&lt;br /&gt;
kubectl get all --namespace=nginx-ingress&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* deploy sample Training App and Ingress Resource and try to access the app&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-ingress-backend.yaml&lt;br /&gt;
kubectl apply -f https://www.kamilbaran.pl/training/kubernetes/training-ingress.yaml&lt;br /&gt;
kubectl get ingress,svc,deploy,pod&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* more info: kubernetes.io/docs/concepts/services-networking/ingress/&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helm ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://get.helm.sh/helm-v2.16.3-linux-386.tar.gz&lt;br /&gt;
tar -xvpf helm-v2.16.3-linux-386.tar.gz&lt;br /&gt;
sudo mv linux-386/helm /usr/local/bin/helm&lt;br /&gt;
kubectl apply -f rbac-config.yaml&lt;br /&gt;
helm init --service-account tiller&lt;br /&gt;
source &amp;lt;(helm completion bash) &amp;amp;&amp;amp; echo &amp;quot;source &amp;lt;(helm completion bash)&amp;quot; &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
# rbac-config.yaml&lt;br /&gt;
apiVersion: v1&lt;br /&gt;
kind: ServiceAccount&lt;br /&gt;
metadata:&lt;br /&gt;
  name: tiller&lt;br /&gt;
  namespace: kube-system&lt;br /&gt;
---&lt;br /&gt;
apiVersion: rbac.authorization.k8s.io/v1&lt;br /&gt;
kind: ClusterRoleBinding&lt;br /&gt;
metadata:&lt;br /&gt;
  name: tiller&lt;br /&gt;
roleRef:&lt;br /&gt;
  apiGroup: rbac.authorization.k8s.io&lt;br /&gt;
  kind: ClusterRole&lt;br /&gt;
  name: cluster-admin&lt;br /&gt;
subjects:&lt;br /&gt;
  - kind: ServiceAccount&lt;br /&gt;
    name: tiller&lt;br /&gt;
    namespace: kube-system&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Kbaran</name></author>
	</entry>
</feed>