avatarJessica Donahue, PHR

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

9845

Abstract

<div id="017c"><pre><span class="hljs-built_in">echo</span> <span class="hljs-string">'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /'</span> | \ sudo <span class="hljs-built_in">tee</span> /etc/apt/sources.list.d/kubernetes.list</pre></div><p id="962b"><b>4. Update the package manager and install Kubernetes tools / CP-W</b></p><div id="1e40"><pre>sudo apt update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl</pre></div><p id="c402">At this point, we have installed all the necessary Kubernetes tools. Kubernetes services such as API server and kube-scheduler are running as containers. Also, pods we deploy run as containers. Therefore, we need a platform to manage these containers. Although Docker is the most popular container runtime, Kubernetes has recently switched to containerd as the default runtime. While Docker or CRI-O can still be configured as the runtime, this tutorial will focus on the containerd runtime</p><h2 id="abfe">Install containerd runtime</h2><p id="4f5d">If you are starting over with this tutorial, verify whether the overlay and br_netfilter kernel modules are loaded. If not, load them as we discussed earlier</p><div id="0b93"><pre>lsmod | grep <span class="hljs-string">"overlay\|br_netfilter"</span></pre></div><p id="8e80"><b>1. Add containerd repository key and add the repository to source list / CP-W</b></p><div id="b96d"><pre>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg</pre></div><div id="2434"><pre>sudo <span class="hljs-built_in">chmod</span> a+r /etc/apt/keyrings/docker.gpg</pre></div><div id="a513"><pre><span class="hljs-built_in">echo</span> \ <span class="hljs-string">"deb [arch="</span>$(dpkg --print-architecture)<span class="hljs-string">" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ "</span>$(. /etc/os-release &amp;&amp; <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$VERSION_CODENAME</span>"</span>)<span class="hljs-string">" stable"</span></pre></div><div id="b18d"><pre>sudo <span class="hljs-built_in">tee</span> /etc/apt/sources.list.d/docker.list &gt; /dev/null</pre></div><p id="d5e1"><b>2. Install containerd / CP-W</b></p><div id="78b8"><pre>sudo apt update sudo apt install -y containerd.io</pre></div><p id="9a21"><b>3. Configure containerd / CP-W</b></p><p id="911c">Create a directory to store containerd config file in <i>/etc/</i></p><div id="192f"><pre>sudo <span class="hljs-built_in">mkdir</span> -p /etc/containerd</pre></div><p id="2667">Generate the default config toml file</p><div id="8ce2"><pre>sudo containerd config default|sudo <span class="hljs-built_in">tee</span> /etc/containerd/config.toml</pre></div><p id="bf32">Open the generated file in any text editor and verify whether the following settings are present. If not, you should set them as shown below</p><div id="145d"><pre><span class="hljs-section">[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]</span> <span class="hljs-attr">runtime_type</span> = <span class="hljs-string">"io.containerd.runc.v2"</span> <span class="hljs-comment"># &lt;- note this, this line might have been missed</span> <span class="hljs-section">[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]</span> <span class="hljs-attr">SystemdCgroup</span> = <span class="hljs-literal">true</span> <span class="hljs-comment"># &lt;- note this, this could be set as false in the default configuration, please make it true</span></pre></div><figure id="9d05"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*7HKoBp4oOiDO_uY_oGeTBQ.png"><figcaption>/etc/containerd/config.toml</figcaption></figure><p id="b5a7">Additionally, at the beginning of this config file, you should see the ‘disabled_plugins’ set as an empty list ([ ]). Please verify that it is indeed empty</p><figure id="a2f6"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*IvO8AMQISh4HyTESNPziXA.png"><figcaption>/etc/containerd/config.toml beginning</figcaption></figure><p id="8eaa">Now save the config file, close it and restart the containerd service</p><div id="ac5e"><pre>sudo systemctl restart containerd sudo systemctl <span class="hljs-built_in">enable</span> containerd systemctl status containerd</pre></div><figure id="0cba"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*D7OzjnDOmmrxvv-SvRWCKg.png"><figcaption>containerd running status</figcaption></figure><p id="39a1">At this point, our runtime installation and configuration setup is completed. However, it’s beneficial to have <i>crictl </i>for debugging purposes. You can use this tool to inspect running containerd containers, their status, and images. So, let’s configure crictl as well</p><p id="cf4c"><b>4. Setup <i>crictl </i>for inspecting containers / CP-W</b></p><p id="b44f">First run the below command and check the output</p><div id="9261"><pre> sudo crictl ps</pre></div><p id="26cf">If the <i>crictl </i>is not present, install it using the below command</p><div id="688f"><pre>sudo apt install cri-tools</pre></div><p id="dfad">Once the installation is completed, re-run the <i>sudo crictl ps </i>command. You may encounter output with errors and warnings. To address these issues, we need to add configurations for crictl. Additionally, you can customize the debug output using this config file</p><figure id="2371"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*TbSquSrZs4O_xrCX-Fnf5w.png"><figcaption>crictl output with errors and warnings</figcaption></figure><p id="ed53">Create <i>crictl.yaml</i> file in <i>/etc/</i></p><div id="b57f"><pre>sudo vim /etc/crictl.yaml</pre></div><p id="5fa8">Paste below content, save and exit</p><div id="e878"><pre><span class="hljs-attr">runtime-endpoint:</span> <span class="hljs-string">unix:///run/containerd/containerd.sock</span> <span class="hljs-attr">image-endpoint:</span> <span class="hljs-string">unix:///run/containerd/containerd.sock</span> <span class="hljs-attr">timeout:</span> <span class="hljs-number">2</span> <span class="hljs-attr">debug:</span> <span class="hljs-literal">true</span> <span class="hljs-comment"># &lt;- if you don't want to see debug info you can set this to false</span> <span class="hljs-attr">pull-image-on-create:</span> <span class="hljs-literal">false</span></pre></div><p id="10d5">Run the <i>sudo crictl ps </i>again<i>,</i>and you shouldn’t encounter any errors or warnings</p><figure id="f553"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*2iZeLqYd75K7Bt9v5SE_hg.png"><figcaption>crictl ps output with debug info enabled</figcaption></figure><p id="84e2">If you prefer not to see debug information, set the <i>debug </i>parameter to <i>false </i>in the <i>crictl.yaml</i> file</p><p id="b8c4">At this point, you won’t find any running containers. You can verify container images using the <i>sudo crictl images</i> command, and there won’t be any images present</p><p id="8cdd"><b>5. Enable <i>kubelet</i> service / CW-P</b></p><div id="9213"><pre>sudo systemctl <span class="hljs-built_in">enable</span> kubelet</pre></div><p id="3236">However, attempting to run the <i>kubelet </i>service will not be successful as the <i>kubectl configs</i> are missing. We won’t need to create these manually; they will be added to the system using <i>kubeadm </i>commands. Therefore, refrain from trying to start the <i>kubelet </i>service at this stage. Our current focus is on enabling the service only</p><p id="e746">Now it is time to initiate our control plane node</p><h1 id="bae5">Initializing Control-Plane Node</h1><p id="4583"><b>1. Run the below command and check for existing images / CP</b></p><div id="4f6d"><pre>sudo crictl images</pre></div><p id="fba3">You won’t find any images at this point as it’s a fresh installation</p><p id="21f5"><b>2. Pull necessary Kubernets images / CP</b></p><p id="c12f">We don’t have to perform this as an isolated process, but for the sake of verifying each small step, we’ll proceed with it separately</p><p id="d5eb">Run below command to pull images</p><div id="5855"><pre>sudo kubeadm config images pull --cri-socket unix:///var/run/containerd/containerd.sock</pre></div><figure id="8284"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*6TaZq5om-6_jEFC_E8vznA.png"><figcaption>Kubernets control-plane images</figcaption></figure><p id="6b1a">Now, if you execute the following command, you’ll see a list of containerd images</p><div id="e371"><pre>sudo crictl images</pre></div><figure id="4dfe"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*G73Enxk6tGtjfVBKUBykAQ.png"><figcaption></figcaption></figure><p id="b5e3">If you’re encountering extensive debug information, you can disable it as previously discussed in the crictl configuration section</p><p id="a638"><b>3. Initialize the control-plane / CP</b></p><p id="7e84"><b>This command will take some time to complete. Do not clear the output as you’ll need to refer to instructions from the command output</b></p><div id="714e"><pre>sudo kubeadm init \ --pod-network-cidr=10.244.0.0/16 \ --cri-socket unix:///var/run/containerd/containerd.sock \ --v=5</pre></div><p id="6906">If you have multiple container runtimes like Docker and containerd installed, you’ll need to specify the correct CRI socket. You can find these values in the official documentation. However, in our case, specifying the containerd socket should suffice</p><div id="0ecc" class="link-block"> <a href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-runtime"> <div> <div> <h2>In # Options stalling kubeadm</h2> <div><h3>This page shows how to install the kubeadm toolbox. For information on how to create a cluster with kubeadm once you…</h3></div> <div><p>kubernetes.io</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*2gI423xnb-J9AWUw)"></div> </div> </div> </a> </div><p id="3a5d">When selecting the pod-network-cidr range, choose a range that does not conflict with your network’s IP range</p><p id="ed94"><i>v=5</i> or higher would print verbose messages. This is useful when there are issues to fix</p><p id="a28d">At the end of the command output, you will see something like the following</p><figure id="3441"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*d_rhOFztJg9mSV4yThHyNA.png"><figcaption>kubeadm init output</figcaption></figure><p id="cf2e"><b>DO NOT skip the instruction in the beginning (1)</b>. Otherwise your <i>kubectl </i>won’t be connected with the API server. Even if you are running the cluster using the root user, you still need to follow this step. <i>kubectl </i>fetch the config from this location by default</p><p id="3915">error :</p><p id="ab4f"><i>couldn’t get current server API group list: Get “<a href="http://localhost:8080/api?timeout=32s">http://localhost:8080/api?timeout=32s</a>": dial tcp 127.0.0.1:8080: connect: connection refused</i></p><p id="b987"><i>The connection to the server localhost:8080 was refused — did you specify the right host or port?</i></p><figure id="3472"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*nmQDIdbnL8Ukxn2y2dKvmQ.png"><figcaption>kubectl won’t connect to API server even with root user if you haven’t done config copy as instructed</figcaption></figure><p id="2409">You will need the kubeadm join command (2) to connect the worker node with the control plane. However, you can always generate this. We’ll generate a new join command later when connecting our worker node with the control plane node</p><p id="5809">Run below command to copy config. You should perform this as a normal user if you plan to run <i>kubectl </i>with a regular user account. If you intend to run kubectl as root, execute it under the root account</p><div id="be2a"><pre> <span class="hljs-built_in">mkdir</span> -p <span class="hljs-variable">$HOME</span>/.kube sudo <span class="hljs-built_in">cp</span> -i /etc/kubernetes/admin.conf <span class="hljs-variable">$HOME</span>/.kube/config sudo <span class="hljs-built_in">chown</span> $(<span class="hljs-built_in">id</span> -u):$(<span class="hljs-built_in">id</span> -g) <span class="hljs-variable">$HOME</span>/.kube/config</pre></div><p id="bca8">Now, if you run the command <i>kubectl get nodes</i>, it should work</p><p id="74d4">Run below <i>kubectl </i>command to get the cluster nodes</p><div id="1f4e"><pre>kubectl <span class="hljs-keyword">get</span> nodes</pre></div><figure id="504d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*g9_alLqV7vdkQYecRLMUGQ.png"><figcaption>kubectl get nodes output</figcaption></figure><p id="5f61">Note that you can see the control-plane node here, but the status is not ready. We need to apply the CNI plugin to make this control-plane ready. Also, if you check the running containers using <i>crictl ps</i>, you should see something similar to the following</p><figure id="10f5"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*-1lPbsnrzK9gsxr3_O25XQ.png"><figcaption>crictl ps output for freshly initialized kubernets control-plane node without CNI plugin</figcaption></figure><p id="bf09">We are going to use <b>Weave Net</b> in this tutorial as our CNI plugin</p><p id="50d0"><b>4. Add network add-on / CP</b></p><p id="4ede">You can get the latest add-on apply command from here</p><div id="f104" class="link-block"> <a href="https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#-installation"> <div> <div> <h2>Integrating Kubernetes via the Addon</h2> <div><h3>The following topics are discussed: Before installing Weave Net, you should make sure the following ports are not…</h3></div> <div><p>www.weave.works</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div> </div> </div> </a> </div><p id="c282">or you can use below command</p><div id="9e2b"><pre>kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml</pre></div><p id="9331">Once you run the above command and still see the control-plane node in Not Ready status check the <i>sudo</i> <i>crictl ps </i>output. If it shown as below,</p><figure id="c7ed"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*m1am9PLRazWwXwSRFYE5Tw.png"><figcaption>weave add-on no attempts</figcaption></figure><p id="4eb6">Just restart your control-plane server and check. <b>Before restarting your control-plane server, exercise caution</b>. If your node has a dynamic IP interface and its IP changes upon restarting, the control-plane may not function correctly. Kubernetes utilizes IP as a component to sign certificates for network security</p><p id="e3ad">You would now see there is one or more attempts and the control plane is ready</p><div id="fc25"><pre>sudo crictl ps</pre></div><figure id="6278"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*fpidOPp07ustv571k11rRg.png"><figcaption>weave add-on has added successfully</figcaption></figure><div id="9745"><pre>kubectl get nodes</pre></div><figure id="7a74"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*HuaU04lIBQuQ2kIWvewNSw.png"><figcaption>Kubernets control-plane node is ready</figcaption></figure><p id="7ad5">At this point, your control plane node is ready. Let’s proceed to configure the worker node</p><h1 id="16c4">Join the Worker Node to Kubernets Control-Plane</h1><p id="51e0">In this section, we’ll switch between the control plane and worker node to execute various commands. <b>Pay attention to the short codes for each</b></p><ol><li><b>Switch to the control-plane node and generate the join command / CP</b></li></ol><p id="069a">As you already know, during the initialization of the control-plane, there was a join command provided. You can use it instead of generating a new one. However, it’s advisable to generate a new one, considering that the token has a short lifespan</p><p id="a973">Use the below command in the control plane node to generate the join command</p><div id="bfb9"><pre>kubeadm token create --print-join-command</pre></div><p id="0f16">It would display something similar to the following in the console</p><p id="45d9"><i>kubeadm join 192.168.8.120:6443 — token dg67p7.wvt7n5zxx9pxbmaz — discovery-token-ca-cert-hash sha256:36f9eb64ef8a6d45254b8994108b0e3a56e856bcb3b07d46cd83554db4114490</i></p><p id="f869">Copy the entire command as we’ll need this to join the worker node with the control-plane.</p><p id="f78a"><b>2. Switch to the worker node and follow the below instructions / W</b></p><p id="ee75">Verify whether you’ve completed all the steps marked as <b>CP-W</b> or <b>W </b>in the previous sections</p><p id="a6ac">Execute the join command you copied from the control-plane console. You’ll receive something similar to the following</p><figure id="0357"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*IK0cU5NQu4-AgYam6KCvZw.png"><figcaption>Kubernets worker node join command output</figcaption></figure><p id="8bab"><b>3. Switch back to the control-plane node and run the below command to verify / CP</b></p><div id="8db5"><pre>kubectl get nodes -o wide</pre></div><figure id="1221"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*FkXlBH-dmvAaxdc53rWwUA.png"><figcaption>kubectl output for get nodes -o wide command</figcaption></figure><p id="8f3f">Congratulations! At this stage, you have a functional minimum Kubernetes cluster</p><h1 id="22ee">What is Next?</h1><p id="1a87">You might want to explore this simple official documentation section on deploying a simple Nginx pod to your cluster</p><div id="4d13" class="link-block"> <a href="https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/"> <div> <div> <h2>Run a Stateless Application Using a Deployment</h2> <div><h3>This page shows how to run an application using a Kubernetes Deployment object. Objectives Create an nginx deployment…</h3></div> <div><p>kubernetes.io</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*af-sBd8CqTyP8r6J)"></div> </div> </div> </a> </div><h1 id="1692">Needing some motivation to continue? Consider watching the following Honeypot documentary on Kubernetes</h1> <figure id="81bd"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FBE77h7dmoQU&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DBE77h7dmoQU&amp;image=http%3A%2F%2Fi.ytimg.com%2Fvi%2FBE77h7dmoQU%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" allowfullscreen="" frameborder="0" height="480" width="854"> </div> </div> </figure></iframe></div></div></figure></article></body>

How to Respond When You’re Put on a Performance Improvement Plan

It’s the conversation that no one wants to have at work.

Photo: Emiliano Vittoriosi/Unsplash

It’s the conversation that no one wants to have at work. Not you. Not your boss. Not even Human Resources.

It’s the dreaded Performance Improvement Plan or ‘PIP.’

A PIP is different from a Written Warning in that it isn’t about addressing an isolated incident. A Written Warning is for infractions like showing up 2 hours late or unknowingly violating a policy.

This is unacceptable. Don’t let it happen again. Move on.

Sure, it doesn’t make you feel warm and fuzzy inside but mistakes happen, and you can avoid repeating this one fairly easily.

A PIP, on the other hand, feels more personal. It addresses a pattern of behaviors or shortcomings that cut to the core of your professional identity.

You’re not meeting expectations as a [insert job title].

We need to see immediate, consistent, and sustained improvement to avoid further disciplinary action.

Ouch. Now that hurts. But, feedback is a gift, right?

After all, if you aren’t meeting your boss’ expectations, wouldn’t you rather know now and be given a chance to improve?

I have sat through my fair share of PIP conversations over the course of my HR career, and have seen employees receive and respond to this kind of feedback in dozens of ways.

There are definite differences in the responses of those to go on to successfully turn things around and those who don’t.

So, if you find yourself being put on a PIP, here are some productive (and some not so productive) ways to respond.

The Productive Response

  • Be a sponge: Being told that you’re not doing a good enough job is likely to elicit an emotional response, and it’s hard for us to think clearly when we’re flooded with emotions. Instead of trying to respond, focus on soaking in the feedback, and seeking to understand the crux of the issue.
  • Take time to reflect: Ask to take the evening to review the PIP and have a follow-up discussion tomorrow. This will give you time to calm down, read through the examples your boss outlined, and reflect on what you might need to ask for support, training, or clarification on.
  • Demonstrate self-awareness: If you agree with any of the concerns your boss outlined in the PIP, say so. Doing this demonstrates self-awareness which will make your boss more invested in helping you be successful.
  • Advocate for yourself: If, after you have reviewed the plan, you are still unclear on what needs to change, it is your responsibility to advocate for the information you need to be successful. If you don’t understand something, talk it over with your boss until you have a clear idea of what you need to do differently.
  • Ask questions: Asking questions can help you understand what ‘meeting expectations’ looks like if you’re still not quite sure. Questions like, “What was missing from this piece of work?” or “What do you think I should have done differently in this situation?” will allow your boss to paint a picture of what ‘good’ looks like in the context of your job.
  • Overcommunicate: Most PIPs are written as 60 to 90-day plans that list specific milestones you need to hit along the way. But don’t wait for your boss to ask for an update. The best employees proactively check-in to report progress without being asked.
  • Say ‘thank you’: Feedback is a gift, remember? Trust me, there are thousands of managers who blindside their employees with termination without ever giving them feedback. If your boss is generous enough to give you a chance to improve, genuinely thank them for the opportunity to do so.

The Unproductive Response

  • “But what about that one time…?”: Avoid the temptation to chronicle every single time you did or didn’t do something. Meeting some of the expectations of the job some of the time is not enough.
  • Get caught up in the details: Focus on the big picture. Your boss is telling you that you aren’t meeting the expectations of the job in its entirety. Your energy is better spent trying to improve holistically than it is disputing the small stuff.
  • Attack your boss’ motives: No manager I have ever worked with enjoys the process of putting an employee on a PIP — it’s a lot of work and is generally an unpleasant experience. They’re not doing it for fun or to ‘get back at you’ for something. Assume good intentions.
  • Make excuses: Acknowledge any mistakes and take accountability for your performance. Doing so will garner respect and credibility while making excuses will erode it.

Whether we like it or not, we are all beholden to our manager’s assessment of our performance and our potential. They write our reviews, decide whether to recommend us for promotions and have the power to terminate our employment.

If you enjoy your job and the company you work for, your best bet is to internalize the feedback, maintain a positive can-do attitude, and do everything you can to rise to the occasion.

At the same time, remember that your boss’s opinion is just one in a world of many. There may be times when, despite your best efforts, your best is just not enough to change your boss’s opinion of your fit for the job.

And guess what? That’s okay. Really, it is. It doesn’t make you a ‘bad’ person.

There are plenty of jobs with different bosses at other companies. Good people always land on their feet. You will, too.

Not a member of Medium yet?

Join here to directly support my work and get access to every story on Medium. You can also subscribe to my free newsletter or connect with me on Linkedin.

Work
Life
Productivity
Self Improvement
Careers
Recommended from ReadMedium