<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://gbaniaki.github.io//feed.xml" rel="self" type="application/atom+xml" /><link href="https://gbaniaki.github.io//" rel="alternate" type="text/html" /><updated>2024-10-15T07:20:29+00:00</updated><id>https://gbaniaki.github.io//feed.xml</id><title type="html">Gerves Francois BANIAKINA</title><subtitle>Welcome to Gerves&apos;s Tech Hub!
Embark on an exciting journey into the world of software development, artificial intelligence, and full-stack engineering. As a recent graduate passionate about technology and innovation, I am eager to share my experiences in coding, AI, and machine learning. Here, you will find insights, tutorials, and best practices for building robust and scalable applications using cutting-edge technologies.
Explore the dynamic intersection of front-end innovations and back-end architectures, and discover how I bring ideas to life with impactful digital solutions. Dive into my projects, explore the latest industry trends, and connect with me to advance technology. Whether you&apos;re a fellow developer, an entrepreneur with a tech vision, or someone keen to learn, you&apos;ll find valuable resources here. Let&apos;s shape the future together by coding and harnessing the transformative power of AI and machine learning!
As I seek entry-level opportunities, I invite you to join me on this journey of discovery and growth in the tech world.</subtitle><entry><title type="html">Explore your ROSA Environment</title><link href="https://gbaniaki.github.io//work/2024/10/10/how-to-explore-rosa.html" rel="alternate" type="text/html" title="Explore your ROSA Environment" /><published>2024-10-10T08:48:27+00:00</published><updated>2024-10-10T08:48:27+00:00</updated><id>https://gbaniaki.github.io//work/2024/10/10/how-to-explore-rosa</id><content type="html" xml:base="https://gbaniaki.github.io//work/2024/10/10/how-to-explore-rosa.html"><![CDATA[<h1 id="background">Background</h1>
<p>On Octiber 1st, 2024, I attended an in-person Red Hat summit entitled “Connect in Chicago”. The summit consisted of visionary keynotes, hands-on labs and demos, breakout sessions, and networkings. Thus, one of favorite hands-on labs was exploring the Red Hat OpenShift service on AWS environment(ROSA Environment) that has been pre-deployed. This project was so inspiring that i decided to continue work on it after the summit to explore more feature of ROSA.</p>

<h1 id="approach">Approach</h1>
<p>In colaborations with hands-on lab leaders, I used Red Hat hybrid cloud console to configure node and cluster scaling policies, managed upgrades, single sign-on for the cluster using Amazon Cognito, and forward logs to Amazon CloudWatch.
In addition, I deployed an application that uses AWS IAM Roles for service Accounts and AWS STS to connect to an Amazon DynamoDB table. Besides, I made an application on OpenShift scalable and resisteant to node failures and upgrades. Finally, I deployed application using CI/CD tooling, including OpenShift GitOps and source-to-image, and use labels for deterministic app placement on nodes. Learned how to use Open Shift Service Mesh for application observability and tracing.
You can get the detailed approached used here <a href="/2024/10/10/hands-on-lab-rosa-1.html">Hands-on-lab</a> directly.</p>

<h1 id="result">Result</h1>
<p>The outcome of the project was splandid, but I was not  successful to use Open Shift Mesh to observe and trace application. You can find below the detailed outcome of  my work for this project:
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%206.24.31%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%207.09.56%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%207.10.30%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.17.25%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.18.18%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.19.30%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.20.12%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.36.08%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.47.31%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.50.30%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-08%20at%2011.59.17%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%201.02.58%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%201.30.34%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%201.30.54%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%201.31.12%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%201.31.36%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%202.00.20%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%202.01.58%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%202.19.50%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%202.38.13%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%202.40.26%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%207.13.14%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%207.13.40%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%207.27.34%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%207.58.39%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%207.59.06%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%208.00.10%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%208.01.57%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%208.02.52%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%208.03.46%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%208.04.31%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%208.05.08%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%209.04.56%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%209.05.12%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%209.18.57%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%209.25.32%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.47.40%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.47.56%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.48.06%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.48.17%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.48.26%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.48.35%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.52.32%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.52.51%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.53.06%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.53.21%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.53.33%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.53.45%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.53.58%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.54.13%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.54.27%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.54.45%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.55.07%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.55.24%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.55.38%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.55.52%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.56.04%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.56.16%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.56.30%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.56.45%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.57.00%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.57.22%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.57.37%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.57.49%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.58.06%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2010.58.20%20PM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2011.05.48%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2011.13.43%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2011.49.27%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2012.06.17%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2012.19.11%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2012.19.36%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2012.19.59%20AM.png" alt="My helpful screenshot 0 " />
<img src="/assets/images/Screen%20Shot%202024-10-09%20at%2012.20.21%20AM.png" alt="My helpful screenshot 0 " /></p>

<h2 id="next-steps">Next Steps</h2>
<p>Ideally, I would have preferred to continue working on this project and further correct mistakes to repeat the experience. Unfortunately, due to the conclusion of the contract, I was unable to pursue these improvements.However, I would next like to work on “Enhance LLMs and streamline MLOps using instructLab
and KitOps”.</p>]]></content><author><name>gerves Baniakina</name></author><category term="work" /><category term="leadership" /><summary type="html"><![CDATA[This article showcases the game Red Hat Hybrid cloud.]]></summary></entry><entry><title type="html">Hands On Lab Rosa 1</title><link href="https://gbaniaki.github.io//2024/10/10/hands-on-lab-rosa-1.html" rel="alternate" type="text/html" title="Hands On Lab Rosa 1" /><published>2024-10-10T00:00:00+00:00</published><updated>2024-10-10T00:00:00+00:00</updated><id>https://gbaniaki.github.io//2024/10/10/hands-on-lab-rosa-1</id><content type="html" xml:base="https://gbaniaki.github.io//2024/10/10/hands-on-lab-rosa-1.html"><![CDATA[<p>1.List all deployed ROSA clusters in the AWS account:</p>

<p>Warning: Permanently added ‘bastion.km7lp.sandbox2370.opentlc.com’ (ED25519) to the list of known hosts.<br />
-—————————————————————————<br />
  Welcome to the Red Hat OpenShift Service on AWS Ops Hands-on Experience!<br />
-—————————————————————————</p>

<p>By continuing to use this service you agree to use this environment<br />
solely for the purposes of completing the steps in the lab guide.</p>

<p>Any other use is a violation of this service and appropriate action<br />
will be taken. If you disagree with these terms you must disconnect now.<br />
-—————————————————————————<br />
[rosa@bastion ~]$ rosa list clusters<br />
ID                                NAME        STATE  TOPOLOGY<br />
2e9les6f8l4p9mikfeamcd4eiei5n4vk  rosa-km7lp  ready  Hosted CP<br />
[rosa@bastion ~]$</p>

<p>2. Now let’s examine this cluster a bit more by describing the cluster (the $GUID environment variable is already set for you so you can immediately describe your individual cluster):<br />
[rosa@bastion ~]$ rosa  describe cluster --cluster rosa-$GUID</p>

<p>Name:                       rosa-km7lp<br />
ID:                         2e9les6f8l4p9mikfeamcd4eiei5n4vk<br />
External ID:                c61a45db-fbeb-45b9-a932-71f091da827c<br />
Control Plane:              ROSA Service Hosted<br />
OpenShift Version:          4.14.37<br />
Channel Group:              stable<br />
DNS:                        rosa-km7lp.vmzc.p3.openshiftapps.com<br />
AWS Account:                245462772522<br />
AWS Billing Account:        017310218799<br />
API URL:                    https://api.rosa-km7lp.vmzc.p3.openshiftapps.com:443<br />
Console URL:                https://console-openshift-console.apps.rosa.rosa-km7lp.vmzc.p3.openshiftapps.com<br />
Region:                     us-east-2<br />
Availability:<br />
 - Control Plane:           MultiAZ<br />
 - Data Plane:              SingleAZ<br />
Nodes:<br />
 - Compute (desired):       2<br />
 - Compute (current):       2<br />
Network:<br />
 - Type:                    OVNKubernetes<br />
 - Service CIDR:            172.30.0.0/16<br />
 - Machine CIDR:            10.0.0.0/16<br />
 - Pod CIDR:                10.128.0.0/14<br />
 - Host Prefix:             /23<br />
Workload Monitoring:        Enabled<br />
Ec2 Metadata Http Tokens:   optional<br />
STS Role ARN:               arn:aws:iam::245462772522:role/ManagedOpenShift-HCP-ROSA-Installer-Role<br />
Support Role ARN:           arn:aws:iam::245462772522:role/ManagedOpenShift-HCP-ROSA-Support-Role<br />
Instance IAM Roles:<br />
 - Worker:                  arn:aws:iam::245462772522:role/ManagedOpenShift-HCP-ROSA-Worker-Role<br />
Operator IAM Roles:<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-kube-system-kube-controller-manager<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-kube-system-capa-controller-manager<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-kube-system-control-plane-operator<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-kube-system-kms-provider<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-openshift-cloud-network-config-controller-cloud-crede<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-openshift-image-registry-installer-cloud-credentials<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-openshift-ingress-operator-cloud-credentials<br />
 - arn:aws:iam::245462772522:role/rosa-km7lp-openshift-cluster-csi-drivers-ebs-cloud-credentials<br />
Managed Policies:           Yes<br />
State:                      ready <br />
Private:                    No<br />
Created:                    Oct  8 2024 21:34:45 UTC<br />
Details Page:               https://console.redhat.com/openshift/details/s/2nAkUfVykWryE47reIpZdvFNJGC<br />
OIDC Endpoint URL:          https://oidc.op1.openshiftapps.com/2e9lenkmbpkojog2k1euo2mqase12l51 (Managed)<br />
Audit Log Forwarding:       disabled</p>

<p>[rosa@bastion ~]$</p>

<p>3. Get the API URL for your cluster:<br />
[rosa@bastion ~]$ rosa describe cluster --cluster rosa-$GUID --output json | jq -r .api.url<br />
https://api.rosa-km7lp.vmzc.p3.openshiftapps.com:443<br />
[rosa@bastion ~]$</p>

<p>4. Get the OpenShift Console URL for your cluster:</p>

<p>[rosa@bastion ~]$ rosa describe cluster --cluster rosa-$GUID --output json | jq -r .console.url<br />
https://console-openshift-console.apps.rosa.rosa-km7lp.vmzc.p3.openshiftapps.com<br />
[rosa@bastion ~]$</p>

<p>5. A temporary admin user has already been created for you on the ROSA OpenShift cluster:</p>

<p>6. Now that you have the information about the Admin credentials and the API URL for your cluster you can log into your cluster:</p>

<p>[rosa@bastion ~]$ oc login --username cluster-admin --password 9byx3-J9ftX-96NXu-bu5Ln https://api.rosa-km7lp.vmzc.p3.openshiftapps.com:443<br />
Login successful.</p>

<p>You have access to 78 projects, the list has been suppressed. You can list all projects with ‘oc projects’</p>

<p>Using project “default”.<br />
Welcome! See ‘oc help’ to get started.<br />
[rosa@bastion ~]$ <br />
[rosa@bastion ~]$ oc help<br />
OpenShift Client</p>

<p>This client helps you develop, build, deploy, and run your applications on any<br />
OpenShift or Kubernetes cluster. It also includes the administrative<br />
commands for managing a cluster under the ‘adm’ subcommand.</p>

<p>Basic Commands:<br />
  login             Log in to a server<br />
  new-project       Request a new project<br />
  new-app           Create a new application<br />
  status            Show an overview of the current project<br />
  project           Switch to another project<br />
  projects          Display existing projects<br />
  explain           Get documentation for a resource</p>

<p>Build and Deploy Commands:<br />
  rollout           Manage a Kubernetes deployment or OpenShift deployment config<br />
  rollback          Revert part of an application back to a previous deployment<br />
  new-build         Create a new build configuration<br />
  start-build       Start a new build<br />
  cancel-build      Cancel running, pending, or new builds<br />
  import-image      Import images from a container image registry<br />
  tag               Tag existing images into image streams</p>

<p>Application Management Commands:<br />
  create            Create a resource from a file or from stdin<br />
  apply             Apply a configuration to a resource by file name or stdin<br />
  get               Display one or many resources<br />
  describe          Show details of a specific resource or group of resources<br />
  edit              Edit a resource on the server<br />
  set               Commands that help set specific features on objects<br />
  label             Update the labels on a resource<br />
  annotate          Update the annotations on a resource<br />
  expose            Expose a replicated application as a service or route<br />
  delete            Delete resources by file names, stdin, resources and names, or by resources and label selector<br />
  scale             Set a new size for a deployment, replica set, or replication controller<br />
  autoscale         Autoscale a deployment config, deployment, replica set, stateful set, or replication controller<br />
  secrets           Manage secrets</p>

<p>Troubleshooting and Debugging Commands:<br />
  logs              Print the logs for a container in a pod<br />
  rsh               Start a shell session in a container<br />
  rsync             Copy files between a local file system and a pod<br />
  port-forward      Forward one or more local ports to a pod<br />
  debug             Launch a new instance of a pod for debugging<br />
  exec              Execute a command in a container<br />
  proxy             Run a proxy to the Kubernetes API server<br />
  attach            Attach to a running container<br />
  run               Run a particular image on the cluster<br />
  cp                Copy files and directories to and from containers<br />
  wait              Experimental: Wait for a specific condition on one or many resources<br />
  events            List events</p>

<p>Advanced Commands:<br />
  adm               Tools for managing a cluster<br />
  replace           Replace a resource by file name or stdin<br />
  patch             Update fields of a resource<br />
  process           Process a template into list of resources<br />
  extract           Extract secrets or config maps to disk<br />
  observe           Observe changes to resources and react to them (experimental)<br />
  policy            Manage authorization policy<br />
  auth              Inspect authorization<br />
  image             Useful commands for managing images<br />
  registry          Commands for working with the registry<br />
  idle              Idle scalable resources<br />
  api-versions      Print the supported API versions on the server, in the form of “group/version”<br />
  api-resources     Print the supported API resources on the server<br />
  cluster-info      Display cluster information<br />
  diff              Diff the live version against a would-be applied version<br />
  kustomize         Build a kustomization target from a directory or URL</p>

<p>Settings Commands:<br />
  logout            End the current server session<br />
  config            Modify kubeconfig files<br />
  whoami            Return information about the current session<br />
  completion        Output shell completion code for the specified shell (bash, zsh, fish, or powershell)</p>

<p>Other Commands:<br />
  plugin            Provides utilities for interacting with plugins<br />
  version           Print the client and server version information</p>

<p>Usage:<br />
  oc [flags] [options]</p>

<p>Use “oc &lt;command&gt; --help” for more information about a given command.<br />
Use “oc options” for a list of global command-line options (applies to all commands).<br />
[rosa@bastion ~]$ <br />
7.To check that you are logged in as the admin user you can run oc whoami<br />
rosa@bastion ~]$ oc whoami<br />
cluster-admin<br />
[rosa@bastion ~]$</p>

<p>8. You can now use the cluster as an admin user, which would suffice for this hands-on experience. Though, for any other use, it is highly recommended to set up an IdP. Which is why you will set up external authentication in the next module.</p>

<h3 id="login-to-the-openshift-web-console">Login to the OpenShift Web Console</h3>

<p>Next, let’s log in to the OpenShift Web Console. Remember that you used the rosa command before to retrieve the console URL.<br />
However once you are logged into the cluster you can also use the OpenShift command to find out the console URL.</p>

<ol>
  <li>Grab your cluster’s web console URL. To do so, run the following command:</li>
</ol>

<p>rosa@bastion ~]$ oc whoami --show-console<br />
https://console-openshift-console.apps.rosa.rosa-km7lp.vmzc.p3.openshiftapps.com<br />
[rosa@bastion ~]$</p>

<ol>
  <li>
    <p>Next, open the printed URL in a web browser.</p>
  </li>
  <li>
    <p>Enter the credentials from the previous section:</p>
    <ul>
      <li>Username: cluster-admin</li>
      <li>Password: 9byx3-J9ftX-96NXu-bu5Ln</li>
    </ul>
  </li>
</ol>

<p>If you don’t see an error, congratulations! You’re now logged into the cluster and ready to move on to the workshop content.</p>

<p><strong>Upgrade your ROSA Cluster</strong></p>

<h2 id="1-upgrade-using-the-rosa-command-line-interface">1. Upgrade using the rosa command line interface</h2>

<p>1.1 Remind yourself of the version of your cluster:<br />
  [rosa@bastion ~]$ oc version<br />
  Client Version: 4.14.37<br />
  Kustomize Version: v5.0.1<br />
  Server Version: 4.14.37<br />
  Kubernetes Version: v1.27.16+03a907c<br />
  [rosa@bastion ~]$</p>

<p>1.2. List available versions for the ROSA upgrade (depending on when you run this command there may not be any upgrades available):</p>

<p>[rosa@bastion ~]$ rosa list upgrades -c rosa-$GUID<br />
VERSION  NOTES<br />
4.15.34  recommended<br />
4.15.33  <br />
[rosa@bastion ~]$</p>

<p>1.3. You can also use the OpenShift CLI to list available versions - but for ROSA it’s preferred to use the rosa cli.:<br />
[rosa@bastion ~]$ oc adm upgrade<br />
Cluster version is 4.14.37</p>

<p>Upstream is unset, so the cluster will use an appropriate default.<br />
Channel: stable-4.14 (available channels: candidate-4.14, candidate-4.15, eus-4.14, eus-4.16, fast-4.14, fast-4.15, stable-4.14, stable-4.15)<br />
No updates available. You may still upgrade to a specific release image with --to-image or wait for new updates to be available.<br />
[rosa@bastion ~]$</p>

<p>1.4.Set a variable for the cluster version you want to upgrade to. For the example above this would be:<br />
[rosa@bastion ~]$ export CLUSTER_VERSION=”4.15.33”<br />
[rosa@bastion ~]$ <br />
1.5.You probably don’t want to actually upgrade the cluster right now since that may disrupt your lab environment. Luckily it is possible to schedule an update at a less inconvenient time.</p>

<p>Get a date and time that is 24 hours from now:<br />
[rosa@bastion ~]$ export CLUSTER_VERSION=”4.15.33”<br />
[rosa@bastion ~]$ export UPGRADE_DATE=$(date -d “+24 hours” ‘+%Y-%m-%d’)<br />
export UPGRADE_TIME=$(date ‘+%H:%M’)</p>

<p>echo Date: $UPGRADE_DATE, Time: $UPGRADE_TIME<br />
Date: 2024-10-10, Time: 05:04<br />
[rosa@bastion ~]$</p>

<p>1.6. Now schedule the cluster upgrade to the latest version that is shown in the list of available versions:</p>

<p>[rosa@bastion ~]$ rosa upgrade cluster \<br />
  -c rosa-$GUID \<br />
  --version $CLUSTER_VERSION \<br />
  --mode auto \<br />
  --schedule-date $UPGRADE_DATE \<br />
  --schedule-time $UPGRADE_TIME \<br />
  --control-plane \<br />
  --yes<br />
I: Ensuring account and operator role policies for cluster ‘2e9les6f8l4p9mikfeamcd4eiei5n4vk’ are compatible with upgrade.<br />
I: Account roles with the prefix ‘ManagedOpenShift’ have attached managed policies.<br />
I: Cluster ‘rosa-km7lp’ operator roles have attached managed policies. An upgrade isn’t needed<br />
I: Account and operator roles for cluster ‘rosa-km7lp’ are compatible with upgrade<br />
I: Upgrade successfully scheduled for cluster ‘rosa-km7lp’<br />
[rosa@bastion ~]$</p>

<p><strong>Managing Worker Nodes</strong></p>

<p>##</p>

<h2 id="1-scaling-worker-nodes">1. Scaling worker nodes</h2>

<h3 id="11-via-the-cli">1.1. Via the CLI</h3>

<h3 id="111-first-lets-see-what-machinepools-already-exist-in-our-cluster-to">1.1.1 First, let’s see what MachinePools already exist in our cluster. To</h3>

<p>do so, run the following command:<br />
sa@bastion ~]$ rosa list machinepools -c rosa-$GUID<br />
ID       AUTOSCALING  REPLICAS  INSTANCE TYPE  LABELS    TAINTS    AVAILABILITY ZONE  SUBNET                    VERSION  AUTOREPAIR  <br />
workers  No           2/2       m6a.xlarge                         us-east-2a         subnet-0f9639acc5cd103d9  4.14.37  Yes         <br />
[rosa@bastion ~]$</p>

<p>1.1.2 Now, let’s scale up our MachinePool from two to three machines. To do so, run        the following command:<br />
  [rosa@bastion ~]$ rosa update machinepool -c rosa-$GUID --replicas 3 workers<br />
I: Updated machine pool ‘workers’ on hosted cluster ‘rosa-km7lp’<br />
[rosa@bastion ~]$</p>

<p>1.1.3 It will take about 5 minutes for the additional worker node to be available. You can either continue to the next step - or if you want to see the worker node just run the following command until you see three worker nodes (then hit CTRL+c to abort the watch):<br />
osa@bastion ~]$ watch -n 10 oc get nodes<br />
[rosa@bastion ~]$</p>

<p>1.1.4. Double check your machine pool to validate that it also is now showing 3 replicas:</p>

<p>[rosa@bastion ~]$ rosa list machinepools -c rosa-$GUID<br />
ID       AUTOSCALING  REPLICAS  INSTANCE TYPE  LABELS    TAINTS    AVAILABILITY ZONE  SUBNET                    VERSION  AUTOREPAIR  <br />
workers  No           3/3       m6a.xlarge                         us-east-2a         subnet-0f9639acc5cd103d9  4.14.37  Yes         <br />
[rosa@bastion ~]$ <br />
1.1.5 We don’t actually need this extra worker node so let’s scale the cluster back down to a total of 2 worker nodes by scaling down the Machine Pool.</p>

<p>[rosa@bastion ~]$ rosa update machinepool -c rosa-$GUID --replicas 2 workers<br />
I: Updated machine pool ‘workers’ on hosted cluster ‘rosa-km7lp’<br />
[rosa@bastion ~]$ <br />
If you want to wait until the additional node has been removed repeat the previous command (oc get nodes) until you see just two worker nodes again.<br />
0-0-0-100.us-east-2.compute.internal   Ready                         worker   23m   v1.27.16+03a907c<br />
ip-10-0-0-249.us-east-2.compute.internal   NotReady,SchedulingDisabled   worker   8h    v1.27.16+03a907c<br />
ip-10-0-0-43.us-east-2.compute.internal    Ready                         worker   8h    v1.27.16+03a907c<br />
[rosa@bastion ~]$</p>

<p><strong>AutoScale Your ROSA Cluster</strong></p>

<p>##</p>

<h2 id="1-enable-autoscaling-on-the-default-machinepool">1. Enable Autoscaling on the Default MachinePool</h2>

<p>You can enable autoscaling on your cluster using either the rosa CLI or the Red Hat OpenShift Cluster Manager. Because you do not have credentials for the Red Hat OpenShift Cluster Manager you will be using the CLI in this lab. There are instructions at the end of the lab showing how to do it in the console.<br />
You will need to set up autoscaling for each MachinePool in the cluster separately.<br />
1.1 To identify the machine pool IDs in a cluster, enter the following command:<br />
sa@bastion ~]$ rosa list machinepools --cluster rosa-$GUID<br />
ID       AUTOSCALING  REPLICAS  INSTANCE TYPE  LABELS    TAINTS    AVAILABILITY ZONE  SUBNET                    VERSION  AUTOREPAIR  <br />
workers  No           2/2       m6a.xlarge   <br />
The ID of the MachinePool that you want to add autoscaling to is workers.</p>

<p>1.2. To enable autoscaling on a machine pool, enter the following command:<br />
[rosa@bastion ~]$ rosa edit machinepool --cluster rosa-$GUID workers --enable-autoscaling --min-replicas=2 --max-replicas=4<br />
I: Updated machine pool ‘workers’ on hosted cluster ‘rosa-km7lp’<br />
[rosa@bastion ~]$</p>

<h2 id="2-test-the-cluster-autoscaler">2. Test the Cluster Autoscaler</h2>

<p>Now let’s test the cluster autoscaler and see it in action. To do so, we’ll deploy a job with a load that this cluster cannot handle. This should force the cluster to scale to handle the load.</p>

<p>2.1. First, let’s create a namespace (also known as a project in OpenShift). To do so, run the following command:<br />
[rosa@bastion ~]$ oc new-project autoscale-ex<br />
Now using project “autoscale-ex” on server “https://api.rosa-km7lp.vmzc.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>[rosa@bastion ~]$</p>

<p>2.2. Next, let’s deploy our job that will exhaust the cluster’s resources and cause it to scale more worker nodes. To do so, run the following command:</p>

<p>[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: batch/v1<br />
kind: Job<br />
metadata:<br />
  name: maxscale<br />
  namespace: autoscale-ex<br />
spec:<br />
  template:<br />
    spec:<br />
      containers:<br />
      - name: work<br />
        image: busybox<br />
        command: [“sleep”,  “300”]<br />
        resources:<br />
          requests:<br />
            memory: 500Mi<br />
            cpu: 500m<br />
        securityContext:<br />
          allowPrivilegeEscalation: false<br />
          capabilities:<br />
            drop:<br />
            - ALL<br />
      restartPolicy: Never<br />
  backoffLimit: 4<br />
  completions: 50<br />
  parallelism: 50<br />
EOF<br />
job.batch/maxscale created</p>

<p>2.3. After a few seconds, run the following to see what pods have been created.</p>

<p>[rosa@bastion ~]$ oc -n autoscale-ex get pods<br />
NAME             READY   STATUS    RESTARTS   AGE<br />
maxscale-2dl29   0/1     Pending   0          2m16s<br />
maxscale-2jgph   1/1     Running   0          2m16s<br />
maxscale-2xcdb   1/1     Running   0          2m16s<br />
maxscale-42k7k   0/1     Pending   0          2m16s<br />
maxscale-47rlx   0/1     Pending   0          2m16s<br />
maxscale-4zq5n   1/1     Running   0          2m16s<br />
maxscale-5ft69   0/1     Pending   0          2m16s<br />
maxscale-68xws   0/1     Pending   0          2m16s<br />
maxscale-6dxwj   0/1     Pending   0          2m16s<br />
maxscale-78m54   0/1     Pending   0          2m16s<br />
maxscale-7gfsk   0/1     Pending   0          2m16s<br />
maxscale-b4gtk   0/1     Pending   0          2m16s<br />
maxscale-b5kv4   1/1     Running   0          2m16s<br />
maxscale-ccjj5   0/1     Pending   0          2m16s<br />
maxscale-cw859   0/1     Pending   0          2m16s<br />
maxscale-d27ws   0/1     Pending   0          2m16s<br />
maxscale-dxpwc   0/1     Pending   0          2m16s<br />
maxscale-dzj67   0/1     Pending   0          2m16s<br />
maxscale-fmzrc   0/1     Pending   0          2m16s<br />
maxscale-fpvsq   0/1     Pending   0          2m16s<br />
maxscale-fv8bp   0/1     Pending   0          2m16s<br />
maxscale-hdm67   0/1     Pending   0          2m16s<br />
maxscale-hjrft   1/1     Running   0          2m16s<br />
maxscale-hnzdj   0/1     Pending   0          2m16s<br />
maxscale-k8dhc   0/1     Pending   0          2m16s<br />
maxscale-ksrvk   1/1     Running   0          2m16s<br />
maxscale-kzxqr   1/1     Running   0          2m16s<br />
maxscale-lp6hs   0/1     Pending   0          2m16s<br />
maxscale-lv4lm   0/1     Pending   0          2m16s<br />
maxscale-mlw2j   0/1     Pending   0          2m16s<br />
maxscale-mpx5x   0/1     Pending   0          2m16s<br />
maxscale-mr4lf   0/1     Pending   0          2m16s<br />
maxscale-n28m5   0/1     Pending   0          2m16s<br />
maxscale-nllqg   0/1     Pending   0          2m16s<br />
maxscale-p78h7   1/1     Running   0          2m16s<br />
maxscale-phclj   0/1     Pending   0          2m16s<br />
maxscale-pncbj   1/1     Running   0          2m16s<br />
maxscale-psrsn   0/1     Pending   0          2m16s<br />
maxscale-qrt8s   1/1     Running   0          2m16s<br />
maxscale-rqbgn   0/1     Pending   0          2m16s<br />
maxscale-rscbl   0/1     Pending   0          2m16s<br />
maxscale-srfwh   0/1     Pending   0          2m16s<br />
maxscale-szzsh   0/1     Pending   0          2m16s<br />
maxscale-tb6rw   0/1     Pending   0          2m16s<br />
maxscale-vlbhd   0/1     Pending   0          2m16s<br />
maxscale-vllpk   0/1     Pending   0          2m16s<br />
maxscale-wnmc7   0/1     Pending   0          2m16s<br />
maxscale-wvw79   0/1     Pending   0          2m16s<br />
maxscale-zqbcj   0/1     Pending   0          2m16s<br />
maxscale-zrtd9   0/1     Pending   0          2m16s<br />
[rosa@bastion ~]$</p>

<p>2.3. It will take a few minutes (around 5 minutes) for the new nodes to be available.<br />
2.4. Check the number of nodes in your cluster. Repeat this command until you see 4 nodes - the maximum that you configured for autoscaling the Machinepool. It will take a few minutes (around 5 minutes) for the new nodes to be available.<br />
[rosa@bastion ~]$ oc get nodes<br />
NAME                                       STATUS   ROLES    AGE     VERSION<br />
ip-10-0-0-100.us-east-2.compute.internal   Ready    worker   68m     v1.27.16+03a907c<br />
ip-10-0-0-43.us-east-2.compute.internal    Ready    worker   9h      v1.27.16+03a907c<br />
ip-10-0-0-64.us-east-2.compute.internal    Ready    worker   8m32s   v1.27.16+03a907c<br />
ip-10-0-0-70.us-east-2.compute.internal    Ready    worker   8m31s   v1.27.16+03a907c<br />
[rosa@bastion ~]$</p>

<h3 id="once-the-nodes-are-available-re-run-the-command-to-display-the-pods-for-the-job-you-should-see-that-more-pods-are-now-running-if-you-still-see-some-pods-in-pending-state-that-is-normal-because-even-4-worker-nodes-may-not-be-enough-to-handle-the-node---but-you-limited-the-autoscaler-to-4-worker-nodes">Once the nodes are available re-run the command to display the pods for the job. You should see that more pods are now running. If you still see some pods in Pending state that is normal because even 4 worker nodes may not be enough to handle the node - but you limited the autoscaler to 4 worker nodes.</h3>

<p>NAME             READY   STATUS    RESTARTS   AGE<br />
maxscale-4hwnz   0/1     Pending   0          50s<br />
maxscale-4mzln   0/1     Pending   0          50s<br />
maxscale-5tv2v   0/1     Pending   0          50s<br />
maxscale-76sgq   0/1     Pending   0          51s<br />
maxscale-89spz   0/1     Pending   0          50s<br />
maxscale-8q9sk   1/1     Running   0          51s<br />
maxscale-9726r   0/1     Pending   0          50s<br />
maxscale-9d7gq   1/1     Running   0          51s<br />
maxscale-9ng7f   0/1     Pending   0          50s<br />
maxscale-cxhzr   0/1     Pending   0          50s<br />
maxscale-dmdh9   1/1     Running   0          51s<br />
maxscale-fh8b8   0/1     Pending   0          51s<br />
maxscale-fqfst   1/1     Running   0          51s<br />
maxscale-fs65w   0/1     Pending   0          50s<br />
maxscale-fsfgl   1/1     Running   0          51s<br />
maxscale-fsl9n   0/1     Pending   0          51s<br />
maxscale-fxqxd   0/1     Pending   0          50s<br />
maxscale-gc92v   0/1     Pending   0          50s<br />
maxscale-gdccz   1/1     Running   0          51s<br />
maxscale-hpn5d   0/1     Pending   0          51s<br />
maxscale-j2b78   0/1     Pending   0          51s<br />
maxscale-jkxh7   0/1     Pending   0          50s<br />
maxscale-jsl45   0/1     Pending   0          50s<br />
maxscale-jxd4g   0/1     Pending   0          50s<br />
maxscale-k5gmn   0/1     Pending   0          50s<br />
maxscale-k66fj   1/1     Running   0          51s<br />
maxscale-kbhbz   0/1     Pending   0          50s<br />
maxscale-kls7k   0/1     Pending   0          50s<br />
maxscale-kpfln   0/1     Pending   0          50s<br />
maxscale-kthlh   0/1     Pending   0          50s<br />
maxscale-l7jr2   0/1     Pending   0          50s<br />
maxscale-l8xm4   1/1     Running   0          51s<br />
maxscale-m57r6   0/1     Pending   0          50s<br />
maxscale-mks4g   0/1     Pending   0          50s<br />
maxscale-p8kst   0/1     Pending   0          50s<br />
maxscale-pm486   0/1     Pending   0          50s<br />
maxscale-r2mkx   0/1     Pending   0          51s<br />
maxscale-rcwr2   0/1     Pending   0          51s<br />
maxscale-rqhjd   1/1     Running   0          51s<br />
maxscale-rsr6h   0/1     Pending   0          51s<br />
maxscale-rz8cd   0/1     Pending   0          50s<br />
maxscale-s9xlj   0/1     Pending   0          50s<br />
maxscale-schv7   0/1     Pending   0          50s<br />
maxscale-stxqs   0/1     Pending   0          50s<br />
maxscale-txkln   0/1     Pending   0          51s<br />
maxscale-w8h8c   0/1     Pending   0          51s<br />
maxscale-wkjmp   0/1     Pending   0          50s<br />
maxscale-x47hp   0/1     Pending   0          50s<br />
maxscale-zdm4m   1/1     Running   0          51s<br />
maxscale-zjtk4   0/1     Pending   0          50s</p>

<h3 id="21-turn-off-autoscaling">2.1. Turn off autoscaling</h3>

<p>[rosa@bastion ~]$ rosa edit machinepool --cluster rosa-$GUID workers  -–enable-autoscaling=false --replicas=2<br />
I: Updated machine pool ‘workers’ on hosted cluster ‘rosa-88qgb’<br />
[rosa@bastion ~]$</p>

<h2 id="enable-autoscaling-via-red-hat-openshift-cluster-manager-console">Enable Autoscaling via Red Hat OpenShift Cluster Manager Console</h2>

<p><strong>Labeling your Worker Nodes</strong></p>

<p>##</p>

<h2 id="1-set-a-label-for-the-machine-pool">1. Set a label for the Machine Pool</h2>

<p>1.Just like the last section, let’s use the default machine pool to add our label. To do so, run the following command:<br />
[rosa@bastion ~]$ rosa edit machinepool -c rosa-$GUID --labels tier=frontend workers<br />
I: Updated machine pool ‘workers’ on hosted cluster ‘rosa-88qgb’<br />
[rosa@bastion ~]$</p>

<p>2. Label the nodes manually:<br />
[rosa@bastion ~]$ oc label nodes $(oc get nodes|grep -v NAME|cut -d’ ‘ -f1) tier=frontend<br />
node/ip-10-0-0-139.us-east-2.compute.internal labeled<br />
node/ip-10-0-0-231.us-east-2.compute.internal labeled<br />
[rosa@bastion ~]$</p>

<p>3.Now, let’s verify the nodes are properly labeled. To do so, run the following command:<br />
[rosa@bastion ~]$ oc get nodes --selector=’tier=frontend’ -o name<br />
node/ip-10-0-0-139.us-east-2.compute.internal<br />
node/ip-10-0-0-231.</p>

<h2 id="deploy-an-app-to-the-labeled-nodes"><strong>Deploy an app to the labeled nodes</strong></h2>

<p>1.First, let’s create a project (or namespace) for our application. To do so, run the following command:<br />
rosa@bastion ~]$ oc new-project nodeselector-ex<br />
Now using project “nodeselector-ex” on server “https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>[rosa@bastion ~]$</p>

<p>2. Next, let’s deploy our application and associated resources that will target our labeled nodes. To do so, run the following command:</p>

<p>[rosa@bastion ~]$ oc new-project nodeselector-ex<br />
Now using project “nodeselector-ex” on server “https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
kind: Deployment<br />
apiVersion: apps/v1<br />
metadata:<br />
  name: nodeselector-app<br />
  namespace: nodeselector-ex<br />
spec:<br />
  replicas: 1<br />
  selector:<br />
    matchLabels:<br />
      app: nodeselector-app<br />
  template:<br />
    metadata:<br />
      labels:<br />
        app: nodeselector-app<br />
    spec:<br />
      nodeSelector:<br />
        tier: frontend<br />
      containers:<br />
      - name: hello-openshift<br />
        image: “docker.io/openshift/hello-openshift”<br />
        ports:<br />
        - containerPort: 8080<br />
          protocol: TCP<br />
        - containerPort: 8888<br />
          protocol: TCP<br />
        securityContext:<br />
          allowPrivilegeEscalation: false<br />
          capabilities:<br />
            drop:<br />
            - ALL<br />
EOF<br />
deployment.apps/nodeselector-app created</p>

<p>3. Now, let’s validate that the application has been deployed to one of the labeled nodes. To do so, run the following command:<br />
[rosa@bastion ~]$ oc -n nodeselector-ex get pod -l app=nodeselector-app -o json \<br />
  | jq -r .items[0].spec.nodeName<br />
ip-10-0-0-231.us-east-2.compute.internal</p>

<p>4. Double check the name of the node to compare it to the output above to ensure the node selector worked to put the pod on the correct node.<br />
a@bastion ~]$ oc get nodes --selector=’tier=frontend’ -o name<br />
node/ip-10-0-0-139.us-east-2.compute.internal<br />
node/ip-10-0-0-231.us-east-2.compute.internal<br />
[rosa@bastion ~]$</p>

<p>5. Next create a service using the oc expose command<br />
a@bastion ~]$ oc expose deployment nodeselector-app<br />
service/nodeselector-app exposed</p>

<p>6. Fetch the URL for the newly created route</p>

<p>&gt; <br />
-rbash: unexpected EOF while looking for matching `’’<br />
-rbash: syntax error: unexpected end of file<br />
[rosa@bastion ~]$ echo “https://$(oc get routes/nodeselector-app -o json | jq -r ‘.spec.host’)”<br />
Error from server (NotFound): routes.route.openshift.io “nodeselector-app” not found<br />
https://<br />
[rosa@bastion ~]$</p>

<p><a href="https://bastion.88qgb.sandbox2714.opentlc.com/showroom/modules/200-ops/lab_5_configure_idp_keycloak.html">Configure Red Hat SSO IDP for ROSA</a></p>

<p>##</p>

<h2 id="1-deploy-red-hat-sso">1. Deploy Red Hat SSO</h2>

<p>1.1. Deploy the operator</p>

<p>1.1.1. Set an environment variable to specify the project into which to deploy the operator and Red Hat SSO:<br />
[rosa@bastion ~]$ export SSO_NAMESPACE=keycloak<br />
[rosa@bastion ~]$</p>

<p>1.1.2. Create the project where your operator will be installed to:<br />
rosa@bastion ~]$ oc new-project $SSO_NAMESPACE<br />
Now using project “keycloak” on server “https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>[rosa@bastion ~]$</p>

<dl>
  <dt>1.1.3. To install, first create an Operator Group for the operator (the Operator Group allows the operator to manage a set of projects - in this case our keycloak project):</dt>
  <dd>operators.coreos.com/v1<br />
kind: OperatorGroup<br />
metadata:<br />
name: keycloak-operator<br />
namespace: $SSO_NAMESPACE<br />
spec:<br />
targetNamespaces:<br />
- $SSO_NAMESPACE<br />
EOF<br />
operatorgroup.operators.coreos.com/keycloak-operator created<br />
[rosa@bastion ~]$</dd>
</dl>

<p>1.1.4. Next, install the subscription - this tells the Operator Lifecycle Manager in ROSA to install the Red Hat SSO operator. The most important setting is the channel - we are using the latest available version in the stable channel:<br />
rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: operators.coreos.com/v1alpha1<br />
kind: Subscription<br />
metadata:<br />
  name: rhsso-operator<br />
  namespace: $SSO_NAMESPACE<br />
spec:<br />
  channel: stable<br />
  installPlanApproval: Automatic<br />
  name: rhsso-operator<br />
  source: redhat-operators<br />
  sourceNamespace: openshift-marketplace<br />
EOF<br />
subscription.operators.coreos.com/rhsso-operator created</p>

<p>1.1.5. Wait until the operator pod is running (repeat until it is and your output looks similar to the one below):<br />
ME                              READY   STATUS    RESTARTS   AGE<br />
rhsso-operator-56b4c6ccb9-xj9nw   1/1     Running   0          71s</p>

<p>###</p>

<h3 id="12-deploy-red-hat-sso">1.2. Deploy Red Hat SSO</h3>

<p>1.2.1. Create the Keycloak object - which deploys the Red Hat SSO server. Note that we are using 2 instances of the server for redundancy:<br />
[rosa@bastion ~]$ cat &lt;&lt;EOF | oc apply -f -<br />
-–<br />
apiVersion: keycloak.org/v1alpha1<br />
kind: Keycloak<br />
metadata:<br />
  name: keycloak<br />
  namespace: $SSO_NAMESPACE<br />
  labels:<br />
    app: sso<br />
spec:<br />
  instances: 2<br />
  externalAccess:<br />
    enabled: True<br />
EOF<br />
keycloak.keycloak.org/keycloak created</p>

<p>1.2.2. Wait until Keycloak is fully deployed (repeat until the output looks like the example output):<br />
[osa@bastion ~]$ oc get pod -n $SSO_NAMESPACE<br />
NAME                                  READY   STATUS    RESTARTS   AGE<br />
keycloak-0                            1/1     Running   0          2m3s<br />
keycloak-1                            0/1     Running   0          32s<br />
keycloak-postgresql-d495f8747-lpvhl   1/1     Running   0          2m3s<br />
rhsso-operator-56b4c6ccb9-xj9nw       1/1     Running   0          7m25s<br />
[rosa@bastion ~]$ oc get pod -n $SSO_NAMESPACE<br />
NAME                                  READY   STATUS    RESTARTS   AGE<br />
keycloak-0                            1/1     Running   0          3m21s<br />
keycloak-1                            1/1     Running   0          110s<br />
keycloak-postgresql-d495f8747-lpvhl   1/1     Running   0          3m21s<br />
rhsso-operator-56b4c6ccb9-xj9nw       1/1     Running   0          8m43s<br />
[rosa@bastion ~]$</p>

<p>1.2.3. Validate that in fact the Keycloak server is ready (if you get false then wait a few seconds and retry the command - eventually it will be ready):<br />
rosa@bastion ~]$ oc get keycloak keycloak -n $SSO_NAMESPACE -o json | jq .status.ready<br />
True</p>

<p>###</p>

<h3 id="13-retrieve-information-about-your-red-hat-sso-installation">1.3. Retrieve Information about your Red Hat SSO Installation</h3>

<p>1.3.1. Set some environment variables to use when setting up the Keycloak Client on Red Hat SSO:<br />
1.3.2. Set your OAuth Callback URL base variable.<br />
1.3.2.a. Your cluster is a ROSA cluster using a hosted control plane. Therefore the command to determine the OAuth Callback URL is the following:<br />
osa@bastion ~]$ export CALLBACK_URL_BASE=https://oauth.$CLUSTER_DOMAIN:443/oauth2callback<br />
[rosa@bastion ~]$</p>

<p>###</p>

<h3 id="14-configure-red-hat-sso">1.4. Configure Red Hat SSO</h3>

<p>In order to set up Red Hat SSO you need to create the following objects:</p>

<ul>
  <li>Keycloak Realm</li>
  <li>Keycloak Client</li>
  <li>Keycloak User(s)</li>
</ul>

<p>1.4. 1. Create a Keycloak Realm to use with ROSA:<br />
 KeycloakRealm<br />
metadata:<br />
  name: rosa<br />
  namespace: $SSO_NAMESPACE<br />
  labels:<br />
    app: sso<br />
spec:<br />
  instanceSelector:<br />
    matchLabels:<br />
      app: sso<br />
  realm:<br />
    realm: rosa<br />
    enabled: true<br />
    loginTheme: rh-sso<br />
EOF<br />
keycloakrealm.keycloak.org/rosa created</p>

<p>1.4. 2. Create the Keycloak Client. The most important setting to get right is the redirectUri which points back to the ROSA OAuth endpoint (remember you set a variable before for this URL):</p>

<p>[rosa@bastion ~]$ cat &lt;&lt;EOF | oc apply -f -<br />
-–<br />
apiVersion: keycloak.org/v1alpha1<br />
kind: KeycloakRealm<br />
metadata:<br />
  name: rosa<br />
  namespace: $SSO_NAMESPACE<br />
  labels:<br />
    app: sso<br />
spec:<br />
  instanceSelector:<br />
    matchLabels:<br />
      app: sso<br />
  realm:<br />
    realm: rosa<br />
    enabled: true<br />
    loginTheme: rh-sso<br />
EOF<br />
keycloakrealm.keycloak.org/rosa created<br />
[rosa@bastion ~]$ cat &lt;&lt;EOF | oc apply -f -<br />
-–<br />
apiVersion: keycloak.org/v1alpha1<br />
kind: KeycloakClient<br />
metadata:<br />
  name: rosa<br />
  namespace: $SSO_NAMESPACE<br />
  labels:<br />
    app: sso<br />
spec:<br />
  realmSelector:<br />
    matchLabels:<br />
      app: sso<br />
  client:<br />
    clientId: rosa<br />
    name: rosa<br />
    description: “Red Hat OpenShift Service on AWS”<br />
    protocol: openid-connect<br />
    enabled: true<br />
    publicClient: false<br />
    directAccessGrantsEnabled: true<br />
    implicitFlowEnabled: true<br />
    standardFlowEnabled: true<br />
    serviceAccountsEnabled: true<br />
    loginTheme: rh-sso<br />
    redirectUris:<br />
    - $CALLBACK_URL_BASE/RosaKeycloak<br />
    webOrigins:<br />
    - “/*”<br />
    defaultClientScopes:<br />
    - acr<br />
    - email<br />
    - profile<br />
    - roles<br />
    - web-origins<br />
    optionalClientScopes:<br />
    - address<br />
    - microprofile-jwt<br />
    - offline_access<br />
    - phone<br />
  serviceAccountRealmRoles:<br />
  - default-roles-rosa<br />
EOF<br />
keycloakclient.keycloak.org/rosa created<br />
[rosa@bastion ~]$</p>

<p>1.4.3. Now that your Keycloak has been configured you can create a user which will become the ROSA admin (for security reasons you are using a random password for this user):<br />
echo “<br />
-–<br />
apiVersion: keycloak.org/v1alpha1<br />
kind: KeycloakUser<br />
metadata:<br />
  name: rosa-admin<br />
  namespace: $SSO_NAMESPACE<br />
  labels:<br />
    app: sso<br />
spec:<br />
  realmSelector:<br />
    matchLabels:<br />
      app: sso<br />
  user:<br />
    enabled: true<br />
    username: rosa-admin<br />
    firstName: ROSA<br />
    lastName: Admin<br />
    email: rosa-admin@example.com<br />
    credentials:<br />
    - temporary: false<br />
      type: password<br />
      value: ‘HjfBY6oRi9ydiXDv’<br />
“ | oc apply -f -<br />
keycloakuser.keycloak.org/rosa-admin created<br />
1.4.4.Then create a user which will become the just a regular developer user:<br />
echo “<br />
-–<br />
apiVersion: keycloak.org/v1alpha1<br />
kind: KeycloakUser<br />
metadata:<br />
  name: rosa-developer<br />
  namespace: $SSO_NAMESPACE<br />
  labels:<br />
    app: sso<br />
spec:<br />
  realmSelector:<br />
    matchLabels:<br />
      app: sso<br />
  user:<br />
    enabled: true<br />
    username: rosa-developer<br />
    firstName: ROSA<br />
    lastName: Developer<br />
    email: rosa-developer@example.com<br />
    credentials:<br />
    - temporary: false<br />
      type: password<br />
      value: ‘HjfBY6oRi9ydiXDv’<br />
“ | oc apply -f -<br />
cloakuser.keycloak.org/rosa-developer created</p>

<p>##</p>

<h2 id="2-set-up-openshift-authentication-to-use-red-hat-sso">2. Set up OpenShift authentication to use Red Hat SSO</h2>

<p>2.1. First retrieve the client secret for your configured Keycloak Client:<br />
[rosa@bastion ~]$ export SSO_CLIENT_SECRET=$(oc get secret keycloak-client-secret-rosa -o json | jq -r ‘.data.CLIENT_SECRET’ | base64 -d)</p>

<p>2.2. Now you can set up the identity provider in ROSA:<br />
[rosa@bastion ~]$ rosa create idp \<br />
--cluster rosa-$GUID \<br />
--type openid \<br />
--name RosaKeycloak \<br />
--client-id rosa \<br />
--client-secret $SSO_CLIENT_SECRET \<br />
--issuer-url $SSO_ADMIN_CONSOLE/auth/realms/rosa \<br />
--email-claims email \<br />
--name-claims name \<br />
--username-claims preferred_username<br />
I: Configuring IDP for cluster ‘rosa-88qgb’<br />
I: Identity Provider ‘RosaKeycloak’ has been created.<br />
   It may take several minutes for this access to become active.<br />
   To add cluster administrators, see ‘rosa grant user --help’.</p>

<p>I: Callback URI: https://oauth.rosa-88qgb.zpku.p3.openshiftapps.com:443/oauth2callback/RosaKeycloak<br />
I: To log in to the console, open https://console-openshift-console.apps.rosa.rosa-88qgb.zpku.p3.openshiftapps.com and click on ‘RosaKeycloak’.<br />
[rosa@bastion ~]$ <br />
See screenshot</p>

<p>2.2.1.Logout from your OpenShift Web Console and browse back to the Console URL (rosa describe cluster -c rosa-$GUID -o json | jq -r ‘.console.url’ if you have forgotten it) and you should see a new option to login called RosaKeycloak.(If you do not see the RosaKeycloak option wait a few seconds and refresh the screen.)<br />
2.2.2 Click on RosaKeycloak and use the userid rosa-admin with password HjfBY6oRi9ydiXDv.<br />
See  screeshot<br />
2.2.3.Let’s give Cluster Admin permissions to your RosaKeycloak admin.<br />
Find out the existing users in OpenShift (note for this to work you must have logged in via the web console before - OpenShift does not create user objects until a user has logged in).<br />
rosa@bastion ~]$ rosa describe cluster -c rosa-$GUID -o json | jq -r ‘.console.url’<br />
https://console-openshift-console.apps.rosa.rosa-88qgb.zpku.p3.openshiftapps.com<br />
[rosa@bastion ~]$ oc get users<br />
NAME                      UID                                    FULL NAME    IDENTITIES<br />
backplane-cluster-admin   02ba374e-09e9-4152-b90c-4d33a5326064                <br />
cluster-admin             65f1deec-98cf-4184-a8a5-278868946cf3                cluster-admin:cluster-admin<br />
rosa-admin                5ab970ff-6278-4d40-a343-f2bc6d7814dc   ROSA Admin   RosaKeycloak:f8a9d17a-de2d-4585-bdea-6305de06a103<br />
[rosa@bastion ~]$</p>

<p>2.2.4. Since this is ROSA you can’t just use oc adm policy to grant cluster-admin permissions to your rosa-admin user. You have to use the rosa CLI instead. If you don’t then you may run into issues later on where some commands are prohibited by the ROSA web hook. So use the rosa CLI:<br />
[rosa@bastion ~]$ rosa grant user cluster-admin --user=rosa-admin --cluster=rosa-$GUID<br />
I: Granted role ‘cluster-admins’ to user ‘rosa-admin’ on cluster ‘rosa-88qgb’<br />
[rosa@bastion ~]$</p>

<p>2.2.5. Refresh the OpenShift web console - you should now be able to switch to the Administrator view. If you don’t see the Administrator view log out and back into the web console.<br />
See  screenshot</p>

<p>2.2.6. Log into the API using the new user:<br />
rosa@bastion ~]$ oc login -u rosa-admin -p HjfBY6oRi9ydiXDv https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443<br />
Login successful.</p>

<p>You have access to 81 projects, the list has been suppressed. You can list all projects with ‘oc projects’</p>

<p>Using project “keycloak”.<br />
[rosa@bastion ~]$ oc projects<br />
You have access to the following projects and can switch between them with ‘ project &lt;projectname&gt;’:</p>

<p>2.2.7 . The final step is to delete the temporary ROSA admin user:<br />
osa@bastion ~]$ rosa delete admin -c rosa-$GUID --yes<br />
I: Admin user ‘cluster-admin’ has been deleted from cluster ‘rosa-88qgb’<br />
[rosa@bastion ~]$</p>

<p>2.2.8.You can delete the cluster-admin user object and it’s associated identity:<br />
[rosa@bastion ~]$ oc delete user cluster-admin<br />
user.user.openshift.io “cluster-admin” deleted<br />
[rosa@bastion ~]$ oc delete identity cluster-admin:cluster-admin<br />
identity.user.openshift.io “cluster-admin:cluster-admin” deleted<br />
[rosa@bastion ~]$</p>

<p><a href="https://bastion.88qgb.sandbox2714.opentlc.com/showroom/modules/200-ops/lab_6_cloudwatch.html"><strong>Configure Red Hat OpenShift Logging with AWS Cloudwatch</strong></a></p>

<p>##</p>

<h2 id="1-prepare-amazon-cloudwatch">1. Prepare Amazon CloudWatch</h2>

<p>1.1.Validate that a policy RosaCloudWatch-$GUID already exists:<br />
[rosa@bastion ~]$ POLICY_ARN=$(aws iam list-policies --query “Policies[?PolicyName==’RosaCloudWatch-$GUID’].{ARN:Arn}” --output text<br />
)<br />
[rosa@bastion ~]$ echo $POLICY_ARN<br />
arn:aws:iam::965696256290:policy/RosaCloudWatch-88qgb</p>

<p>1.2. As part of the hands on experience an AWS IAM role has been set up for the OpenShift Logging infrastructure to use.<br />
Examine the role that has been created:<br />
osa@bastion ~]$ aws iam get-role --role-name RosaCloudWatch-$GUID --output json<br />
{<br />
    “Role”: {<br />
        “Path”: “/”,<br />
        “RoleName”: “RosaCloudWatch-88qgb”,<br />
        “RoleId”: “AROA6BV73PERATCC6DV3Z”,<br />
        “Arn”: “arn:aws:iam::965696256290:role/RosaCloudWatch-88qgb”,<br />
        “CreateDate”: “2024-10-09T07:26:55+00:00”,<br />
        “AssumeRolePolicyDocument”: {<br />
            “Version”: “2012-10-17”,<br />
            “Statement”: [<br />
                {<br />
                    “Effect”: “Allow”,<br />
                    “Principal”: {<br />
                        “Federated”: “arn:aws:iam::965696256290:oidc-provider/rh-oidc.s3.us-east-1.amazonaws.com/2e9tm35qg5orqaeqjvfjn0nnk9885st3”<br />
                    },<br />
                    “Action”: “sts:AssumeRoleWithWebIdentity”,<br />
                    “Condition”: {<br />
                        “StringEquals”: {<br />
                            “rh-oidc.s3.us-east-1.amazonaws.com/2e9tm35qg5orqaeqjvfjn0nnk9885st3:sub”: “system:serviceaccount:openshift-logging:logcollector”<br />
                        }<br />
                    }<br />
                }<br />
            ]<br />
        },<br />
        “Description”: “Cloud Watch Role (88qgb)”,<br />
        “MaxSessionDuration”: 3600,<br />
        “Tags”: [<br />
            {<br />
                “Key”: “rosa-workshop”,<br />
                “Value”: “true”<br />
            }<br />
        ],<br />
        “RoleLastUsed”: {}<br />
    }<br />
}<br />
[rosa@bastion ~]$</p>

<p>1.3.Get the ARN of the Role - we will use that later to configure the log collector: <br />
[rosa@bastion ~]$ ROLE_ARN=$(aws iam get-role --role-name RosaCloudWatch-$GUID --output json | jq -r .Role.Arn)<br />
[rosa@bastion ~]$ echo $ROLE_ARN<br />
arn:aws:iam::965696256290:role/RosaCloudWatch-88qgb</p>

<p>2. Configure Cluster Logging<br />
2.1. Now, we need to deploy the OpenShift Cluster Logging Operator. First we need to create an OperatorGroup for the operator:<br />
[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: operators.coreos.com/v1<br />
kind: OperatorGroup<br />
metadata:<br />
  name: openshift-logging<br />
  namespace: openshift-logging<br />
spec:<br />
  targetNamespaces:<br />
  - openshift-logging<br />
EOF<br />
operatorgroup.operators.coreos.com/openshift-logging created<br />
[rosa@bastion ~]$</p>

<p>2.2. Now we can create the Operator Subscription. To do so, run the following command:<br />
cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: operators.coreos.com/v1alpha1<br />
kind: Subscription<br />
metadata:<br />
  labels:<br />
   operators.coreos.com/cluster-logging.openshift-logging: “”<br />
  name: cluster-logging<br />
  namespace: openshift-logging<br />
spec:<br />
  channel: stable<br />
  installPlanApproval: Automatic<br />
  name: cluster-logging<br />
  source: redhat-operators<br />
  sourceNamespace: openshift-marketplace<br />
EOF<br />
subscription.operators.coreos.com/cluster-logging created</p>

<p>2.3. Now, we will wait for the OpenShift Cluster Logging Operator to install. To do so, we can run the following command to watch the status of the installation:<br />
rosa@bastion ~]$ oc -n openshift-logging rollout status deployment cluster-logging-operator<br />
deployment “cluster-logging-operator” successfully rolled out</p>

<p>2.4. Next, we need to create a secret containing the ARN of the IAM role that was previously created. To do so, run the following command:<br />
[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: v1<br />
kind: Secret<br />
metadata:<br />
  name: cloudwatch-credentials<br />
  namespace: openshift-logging<br />
stringData:<br />
  role_arn: $ROLE_ARN<br />
EOF<br />
secret/cloudwatch-credentials created</p>

<p>2.5. Next, let’s configure the OpenShift Cluster Logging Operator by creating a Cluster Log Forwarding custom resource that will forward logs to Amazon CloudWatch. To do so, run the following command:<br />
[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: v1<br />
kind: Secret<br />
metadata:<br />
  name: cloudwatch-credentials<br />
  namespace: openshift-logging<br />
stringData:<br />
  role_arn: $ROLE_ARN<br />
EOF<br />
secret/cloudwatch-credentials created<br />
[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: logging.openshift.io/v1<br />
kind: ClusterLogForwarder<br />
metadata:<br />
  name: instance<br />
  namespace: openshift-logging<br />
spec:<br />
  outputs:<br />
  - name: cw<br />
    type: cloudwatch<br />
    cloudwatch:<br />
      groupBy: namespaceName<br />
      groupPrefix: rosa-$GUID<br />
      region: $(aws configure get region)<br />
    secret:<br />
      name: cloudwatch-credentials<br />
  pipelines:<br />
  - name: to-cloudwatch<br />
    inputRefs:<br />
    - infrastructure<br />
    - audit<br />
    - application<br />
    outputRefs:<br />
    - cw<br />
EOF<br />
clusterlogforwarder.logging.openshift.io/instance created<br />
[rosa@bastion ~]$</p>

<p>2.6. Next, let’s create a Cluster Logging custom resource which will enable the OpenShift Cluster Logging Operator to start collecting logs.<br />
[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: logging.openshift.io/v1<br />
kind: ClusterLogging<br />
metadata:<br />
  name: instance<br />
  namespace: openshift-logging<br />
spec:<br />
  collection:<br />
    logs:<br />
      type: fluentd<br />
  forwarder:<br />
    fluentd: {}<br />
  managementState: Managed<br />
EOF<br />
clusterlogging.logging.openshift.io/instance created</p>

<p>2.7. After a few minutes, you should begin to see log groups inside of Amazon CloudWatch. Repeat this command until you see output resembling the example output below.<br />
[rosa@bastion ~]$ aws logs describe-log-groups --log-group-name-prefix rosa-$GUID<br />
{<br />
    “logGroups”: []<br />
}<br />
[rosa@bastion ~]$ aws logs describe-log-groups --log-group-name-prefix rosa-$GUID<br />
{<br />
    “logGroups”: []<br />
}<br />
[rosa@bastion ~]$ aws logs describe-log-groups --log-group-name-prefix rosa-$GUID<br />
{<br />
    “logGroups”: []<br />
}<br />
[rosa@bastion ~]$ aws logs describe-log-groups --log-group-name-prefix rosa-$GUID<br />
{<br />
    “logGroups”: []<br />
}<br />
[rosa@bastion ~]$</p>

<p><a href="https://bastion.88qgb.sandbox2714.opentlc.com/showroom/modules/300-apps/lab_1_deploy_app.html"><strong>Deploy an Application with AWS Database</strong></a></p>

<p>It’s time for us to put our cluster to work and deploy a workload! We’re going to build an example Java application, <a href="https://github.com/redhat-mw-demos/microsweeper-quarkus/tree/ROSA">microsweeper</a>, using <a href="https://quarkus.io/">Quarkus</a> (a Kubernetes-native Java stack) and <a href="https://aws.amazon.com/dynamodb">Amazon DynamoDB</a>. We’ll then deploy the application to our ROSA cluster and connect to the database over AWS’s secure network.<br />
This lab demonstrates how ROSA (an AWS native service) can easily and securely access and utilize other AWS native services using AWS Secure Token Service (STS). To achieve this, we will be using AWS IAM, Amazon DynamoDB, and a service account within OpenShift. After configuring the latter, we will use both Quarkus - a Kubernetes-native Java framework optimized for containers - and Source-to-Image (S2I) - a toolkit for building container images from source code - to deploy the microsweeper application.</p>

<p>|  | You are working in an environment where your AWS credentials have been set up with exactly the permissions you need to complete this lab. AWS commands other than the ones in this lab will fail with missing authorization. |
| :—- | :—- |</p>

<p>##</p>

<h2 id="1-create-an-amazon-dynamodb-instance">1. Create an Amazon DynamoDB instance</h2>

<p>1.1. First, let’s create a project (also known as namespace). A project is a unit of organization within OpenShift that provides isolation for applications and resources. To do so, run the following command:<br />
osa@bastion ~]$ oc new-project microsweeper-ex<br />
Now using project “microsweeper-ex” on server “https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>[rosa@bastion ~]$</p>

<p>1.2. Next, create the Amazon DynamoDB table resource. Amazon DynamoDB will be used to store information from our application and ROSA will utilize AWS Secure Token Service(STS) to access this native service. More information on STS and how it is utilized in ROSA will be provided in the next section. For now lets create the Amazon DynamoDB table, To do so, run the following command:<br />
rosa@bastion ~]$ aws dynamodb create-table \<br />
  --table-name microsweeper-scores-$GUID \<br />
  --attribute-definitions AttributeName=name,AttributeType=S \<br />
  --key-schema AttributeName=name,KeyType=HASH \<br />
  --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1<br />
{<br />
    “TableDescription”: {<br />
        “AttributeDefinitions”: [<br />
            {<br />
                “AttributeName”: “name”,<br />
                “AttributeType”: “S”<br />
            }<br />
        ],<br />
        “TableName”: “microsweeper-scores-88qgb”,<br />
        “KeySchema”: [<br />
            {<br />
                “AttributeName”: “name”,<br />
                “KeyType”: “HASH”<br />
            }<br />
        ],<br />
        “TableStatus”: “CREATING”,<br />
        “CreationDateTime”: “2024-10-09T17:52:27.423000+00:00”,<br />
        “ProvisionedThroughput”: {<br />
            “NumberOfDecreasesToday”: 0,<br />
            “ReadCapacityUnits”: 1,<br />
            “WriteCapacityUnits”: 1<br />
        },<br />
        “TableSizeBytes”: 0,<br />
        “ItemCount”: 0,<br />
        “TableArn”: “arn:aws:dynamodb:us-east-2:965696256290:table/microsweeper-scores-88qgb”,<br />
        “TableId”: “5164562c-eb93-416b-9f51-61e76a5397bb”,<br />
        “DeletionProtectionEnabled”: false<br />
    }<br />
}<br />
[rosa@bastion ~]$</p>

<p>##</p>

<h2 id="2-iam-roles-for-service-account-irsa-configuration">2. IAM Roles for Service Account (IRSA) Configuration</h2>

<p>Our application uses AWS Secure Token Service(STS) to establish connections with Amazon DynamoDB. Traditionally, one would use static IAM credentials for this purpose, but this approach goes against AWS’ recommended best practices. Instead, AWS suggests utilizing their Secure Token Service (STS). Fortunately, our ROSA cluster has already been deployed using AWS STS, making it effortless to adopt IAM Roles for Service Accounts (IRSA), also known as pod identity.<br />
Service accounts play a crucial role in managing the permissions and access control of applications running within ROSA. They act as identities for pods and allow them to interact securely with various AWS services.<br />
IAM roles, on the other hand, define a set of permissions that can be assumed by trusted entities within AWS. By associating an AWS IAM role with a service account, we enable the pods in our ROSA cluster to leverage the permissions defined within that role. This means that instead of relying on static IAM credentials, our application can obtain temporary security tokens from AWS STS by assuming the associated IAM role.<br />
This approach aligns with AWS’ recommended best practices and provides several benefits. Firstly, it enhances security by reducing the risk associated with long-lived static credentials. Secondly, it simplifies the management of access controls by leveraging IAM roles, which can be centrally managed and easily updated. Finally, it enables seamless integration with AWS services, such as DynamoDB, by granting the necessary permissions to the service accounts associated with our pods.</p>

<p>2.1. First, create a service account to use to assume an IAM role. To do so, run the following command:<br />
sa@bastion ~]$ oc -n microsweeper-ex create serviceaccount microsweeper<br />
serviceaccount/microsweeper created</p>

<p>2.2. An AWS IAM role has been set up for your service account to use. This role includes permissions to access the DynamoDB database that you created in the previous section. The role that has been created is called irsa-$GUID. You will need the ARN of that role to associate it with the microsweeper service account.</p>

<p>2.3. Examine the role that has been created for you:<br />
[rosa@bastion ~]$ aws iam get-role --role-name irsa-$GUID --output json<br />
{<br />
    “Role”: {<br />
        “Path”: “/”,<br />
        “RoleName”: “irsa-88qgb”,<br />
        “RoleId”: “AROA6BV73PERGC5UMTEIE”,<br />
        “Arn”: “arn:aws:iam::965696256290:role/irsa-88qgb”,<br />
        “CreateDate”: “2024-10-09T07:26:46+00:00”,<br />
        “AssumeRolePolicyDocument”: {<br />
            “Version”: “2012-10-17”,<br />
            “Statement”: [<br />
                {<br />
                    “Effect”: “Allow”,<br />
                    “Principal”: {<br />
                        “Federated”: “arn:aws:iam::965696256290:oidc-provider/rh-oidc.s3.us-east-1.amazonaws.com/2e9tm35qg5orqaeqjvfjn0nnk9885st3”<br />
                    },<br />
                    “Action”: “sts:AssumeRoleWithWebIdentity”,<br />
                    “Condition”: {<br />
                        “StringEquals”: {<br />
                            “rh-oidc.s3.us-east-1.amazonaws.com/2e9tm35qg5orqaeqjvfjn0nnk9885st3:sub”: “system:serviceaccount:microsweeper-ex:microsweeper”<br />
                        }<br />
                    }<br />
                }<br />
            ]<br />
        },<br />
        “Description”: “IRSA Role (88qgb)”,<br />
        “MaxSessionDuration”: 3600,<br />
        “RoleLastUsed”: {}<br />
    }<br />
}<br />
[rosa@bastion ~]$ <br />
Note how the service account microsweeper in the namespace microsweeper-ex has been granted the permissions to assume the role. Also note that creating this service account in another namespace would therefore not work to elevate the service account’s permissions.</p>

<p>2.4.Get the Role ARN:<br />
[rosa@bastion ~]$ ROLE_ARN=$(aws iam get-role --role-name irsa-$GUID --output json | jq -r .Role.Arn)<br />
[rosa@bastion ~]$ echo $ROLE_ARN<br />
arn:aws:iam::965696256290:role/irsa-88qgb<br />
[rosa@bastion ~]$</p>

<p>2.5. Now you can annotate the service account with the ARN of the pre-created IAM role. To do so, run the following command:<br />
osa@bastion ~]$ oc -n microsweeper-ex annotate serviceaccount microsweeper eks.amazonaws.com/role-arn=$ROLE_ARN<br />
serviceaccount/microsweeper annotate</p>

<p>##</p>

<h2 id="3-deploy-the-microsweeper-app">3. Deploy the Microsweeper app</h2>

<p>Now that we’ve got a DynamoDB instance up and running and our IRSA configuration completed, let’s deploy our application.<br />
The example application that we use is a Quarkus application. You can find the source code for the application at <a href="https://github.com/rhpds/rosa-workshop-app.git">https://github.com/rhpds/rosa-workshop-app.git</a>. But for the purposes of this experience you will be deploying a pre-built container image.<br />
3.1.Create the microsweeper-appservice Deployment:<br />
osa@bastion ~]$ cat &lt;&lt;EOF | oc apply -f -<br />
-–<br />
apiVersion: apps/v1<br />
kind: Deployment<br />
metadata:<br />
  name: microsweeper-appservice<br />
  namespace: microsweeper-ex<br />
spec:<br />
  replicas: 1<br />
  selector:<br />
    matchLabels:<br />
      deployment: microsweeper-appservice<br />
      app.kubernetes.io/name: microsweeper-appservice<br />
  template:<br />
    metadata:<br />
      labels:<br />
        deployment: microsweeper-appservice<br />
        app.kubernetes.io/name: microsweeper-appservice<br />
    spec:<br />
      serviceAccountName: microsweeper<br />
      containers:<br />
      - name: microsweeper-appservice<br />
        env:<br />
        - name: AWS_REGION<br />
          value: $(aws configure get region)<br />
        - name: DYNAMODB_AWS_CREDENTIALS_TYPE<br />
          value: default<br />
        - name: DYNAMODB_TABLE<br />
          value: microsweeper-scores-$GUID<br />
        image: quay.io/rhpds/microsweeper:1.0.0<br />
        imagePullPolicy: IfNotPresent<br />
        ports:<br />
        - containerPort: 8080<br />
          protocol: TCP<br />
EOF<br />
deployment.apps/microsweeper-appservice created<br />
[rosa@bastion ~]$ <br />
The application is configured using environment variables and the service account name.</p>

<ul>
  <li>serviceAccountName: microsweeper tells OpenShift to use the service account that you configured previously to run this pod.</li>
  <li>AWS_REGION tells the application in which region the database table is deployed.</li>
  <li>DYNAMODB_AWS__CREDENTIALS_TYPE tells the Quarkus database client to look for credentials in the usual places (amongst which is our service account)</li>
  <li>DYNAMODB_TABLE is the name of the database table that you previously created.</li>
</ul>

<p>3.2.Now that your application is running we need to make the application accessible outside of your OpenShift clusterso that you can test it..<br />
Create the Service for the application:<br />
rosa@bastion ~]$ oc -n microsweeper-ex expose deployment microsweeper-appservice<br />
service/microsweeper-appservice exposed<br />
[rosa@bastion ~]$</p>

<p>3.3. And finally create a Route that publishes this application. This particular route will have TLS encryption (edge) and redirect http requests to https (Redirect).</p>

<p>###</p>

<h3 id="331-test-the-application">3.3.1. Test the application</h3>

<p>3.3.1.1. Get the the URL for your application route:<br />
3.3.1.1.1. Use the returned URL to open the Microsweeper application in a web browser of your choice.<br />
You should be able to play a few games and have the score persist in the database.</p>

<p>See  the screenshot(unforntunately my game failed due to computer)</p>

<h3 id="332-application-ip">3.3.2. Application IP</h3>

<p>Let’s take a quick look at what IP the application resolves to.<br />
Back in your terminal, run the following command:<br />
osa@bastion ~]$ nslookup $(oc -n microsweeper-ex get route microsweeper-appservice -o jsonpath=’{.spec.host}’)<br />
Server:         192.168.0.2<br />
Address:        192.168.0.2#53</p>

<p>Non-authoritative answer:<br />
Name:   microsweeper-appservice-microsweeper-ex.apps.rosa.rosa-88qgb.zpku.p3.openshiftapps.com<br />
Address: 3.128.126.201</p>

<p>[rosa@bastion ~]$ <br />
Notice the IP address; can you guess where it comes from?<br />
It comes from the ROSA Load Balancer. In this workshop, we are using a public cluster which means the load balancer is exposed to the Internet. If this was a private cluster, you would have to have connectivity to the VPC ROSA is running on. This could be via a VPN connection, AWS DirectConnect, or something else.</p>

<p><a href="https://bastion.88qgb.sandbox2714.opentlc.com/showroom/modules/300-apps/lab_2_openshift_gitops.html"><strong>Deploy an Application with Red Hat OpenShift GitOps</strong></a></p>

<p>Red Hat® OpenShift® GitOps is an operator that provides tools to enable continuous deployment (CD). Making GitOps workflows available to your platform and development teams, OpenShift GitOps helps you to realize faster, more secure, and more scalable software development, without compromising on quality.<br />
OpenShift GitOps enables customers to build and integrate declarative, git-driven CD workflows directly into their development lifecycle.<br />
There’s no single tool that converts a development pipeline to “DevOps”, but implementing a GitOps framework starts you on the path. Updates and changes are made declaratively in code, bringing automation and a single source of truth to your infrastructure, configuration, and application deployments.<br />
OpenShift GitOps is built on <a href="https://argoproj.github.io/cd">Argo CD</a>, integrating it into Red Hat OpenShift to deliver a consistent, fully supported, declarative, cloud native platform for deployment using GitOps principles.<br />
OpenShift with OpenShift GitOps enables you to:</p>

<ul>
  <li>Apply consistency across cluster and deployment lifecycles</li>
  <li>Consolidate administration and management of applications across on-premises and cloud environments</li>
  <li>Monitor the state deployed applications across your clusters</li>
  <li>Roll back code changes across clusters</li>
  <li>Roll out new changes submitted via Git</li>
  <li>Have confidence in the state of your resources</li>
</ul>

<h2 id="1-deploying-your-application-with-openshift-gitops">1. Deploying your Application with OpenShift GitOps</h2>

<p>1.1.From the OpenShift Console Administrator view click through HOME -&gt; Operators -&gt; Operator Hub, search for “openshift gitops” and click Install.</p>

<p>See  screen shot<br />
For the update channel select gitops-1.10. Leave all other defaults and click Install.</p>

<p>See  screen shot</p>

<p>1.2.Wait until the operator shows as successfully installed (Installed operator - ready for use).<br />
See the screenshot</p>

<p>1.3. In your terminal create a new project:</p>

<p>[rosa@bastion ~]$ oc new-project bgd<br />
Now using project “bgd” on server “https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>[rosa@bastion ~]$</p>

<p>1.4. The OpenShift GitOps operator includes the capability to deploy individual instances of Argo CD for developers.<br />
Deploy your personal Argo CD into your development project:<br />
osa@bastion ~]$ cat &lt;&lt;EOF | oc apply -f -<br />
-–<br />
apiVersion: argoproj.io/v1beta1<br />
kind: ArgoCD<br />
metadata:<br />
  name: argocd<br />
  namespace: bgd<br />
spec:<br />
  sso:<br />
    dex:<br />
      openShiftOAuth: true<br />
      resources:<br />
        limits:<br />
          cpu: 500m<br />
          memory: 256Mi<br />
        requests:<br />
          cpu: 250m<br />
          memory: 128Mi<br />
    provider: dex<br />
  rbac:<br />
    defaultPolicy: “role:readonly”<br />
    policy: “g, system:authenticated, role:admin”<br />
    scopes: “[groups]”<br />
  server:<br />
    insecure: true<br />
    route:<br />
      enabled: true<br />
      tls:<br />
        insecureEdgeTerminationPolicy: Redirect<br />
        termination: edge<br />
EOF<br />
argocd.argoproj.io/argocd created<br />
[rosa@bastion ~]$</p>

<p>1.5. Wait for your Argo CD server to be ready:<br />
[rosa@bastion ~]$ oc rollout status deploy/argocd-server -n bgd<br />
deployment “argocd-server” successfully rolled out</p>

<p>1.6.Now that your Argo CD server is ready you can use it to deploy an application from a git repository. In this case the Kubernetes / OpenShift definition of the application is in the git repository <a href="https://github.com/rhpds/gitops-bgd-app">https://github.com/rhpds/gitops-bgd-app</a>. We won’t have time to go into all the options, but creating the Application tells Argo CD to deploy the application from the git repository into the namespace bgd.<br />
Create the Application:<br />
[rosa@bastion ~]$ cat &lt;&lt;EOF | oc apply -f -<br />
-–<br />
apiVersion: argoproj.io/v1alpha1<br />
kind: Application<br />
metadata:<br />
  name: bgd-app<br />
  namespace: bgd<br />
spec:<br />
  destination:<br />
    namespace: bgd<br />
    server: https://kubernetes.default.svc<br />
  project: default<br />
  source:<br />
    path: apps/bgd/base<br />
    repoURL: https://github.com/rhpds/gitops-bgd-app<br />
    targetRevision: main<br />
  syncPolicy:<br />
    automated:<br />
      prune: true<br />
      selfHeal: false<br />
    syncOptions:<br />
    - CreateNamespace=false<br />
EOF<br />
application.argoproj.io/bgd-app created<br />
[rosa@bastion ~]$</p>

<p>1.7. Retrieve the URL for your Argo CD dashboard and navigate to it in your web browser:<br />
[rosa@bastion ~]$ echo “https://$(oc -n bgd get route argocd-server -o jsonpath=’{.spec.host}’)”<br />
https://argocd-server-bgd.apps.rosa.rosa-88qgb.zpku.p3.openshiftapps.com<br />
[rosa@bastion ~]$</p>

<p>1.8. Argo CD is configured for single sign on with OpenShift. Therefore your admin credentials also work in Argo CD. Click on the Log in via OpenShift button and use the admin credentials to log in (you may need to click on Allow selected permissions after the login step):<br />
 (It  fials because of unknown reasons)</p>

<p>1.9. Once you have logged into Argo CD you should see the Argo CD application dashboard.</p>

<p>1.10. Click on the Application bgd-app to show its topology.<br />
1.11. Verify that OpenShift sees the Deployment as rolled out:<br />
[rosa@bastion ~]$ oc rollout status deploy/bgd<br />
deployment “bgd” successfully rolled out</p>

<p>1.12. Get the route and browse to it in your browser:<br />
[rosa@bastion ~]$ echo “https://$(oc -n bgd get route bgd -o jsonpath=’{.spec.host}’)”<br />
https://bgd-bgd.apps.rosa.rosa-88qgb.zpku.p3.openshiftapps.com<br />
[rosa@bastion ~]$ <br />
 See  the screenshot</p>

<p>1.13. Patch the OpenShift resource to force it to be out of sync with the GitHub repository:<br />
[rosa@bastion ~]$ oc -n bgd patch deploy/bgd --type=’json’ \<br />
  -p=’[{“op”: “replace”, “path”:<br />
  “/spec/template/spec/containers/0/env/0/value”, “value”:”blue”}]’<br />
deployment.apps/bgd patched<br />
[rosa@bastion ~]$</p>

<p>1.14. Refresh your browser and you should see a blue box in the website like so:</p>

<p>See screen shot</p>

<p>1.15. Meanwhile check Argo CD - it should show the application as out of sync. Click the Sync button and then click on Synchronize to have it revert the change you made in OpenShift:<br />
It failed</p>

<p>1,16.Check again, you should see a green box in the website like so:</p>

<p><a href="https://bastion.88qgb.sandbox2714.opentlc.com/showroom/modules/300-apps/lab_3_network_policy.html">Secure your applications with Network Policies</a></p>

<h2 id="1-create-networkpolicies">1. Create Networkpolicies</h2>

<p>1.1. Create a new project and a new app. We will be using this pod for testing network connectivity to the microsweeper application<br />
rosa@bastion ~]$ oc new-project networkpolicy-test<br />
Now using project “networkpolicy-test” on server “https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>[rosa@bastion ~]$</p>

<p>1.2. Create a new application within this namespace:<br />
[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: v1<br />
kind: Pod<br />
metadata:<br />
  name: networkpolicy-pod<br />
  namespace: networkpolicy-test<br />
  labels:<br />
    app: networkpolicy<br />
spec:<br />
  securityContext:<br />
    allowPrivilegeEscalation: false<br />
    runAsNonRoot: true<br />
    seccompProfile:<br />
      type: RuntimeDefault<br />
    capabilities:<br />
    drop:<br />
    - ALL<br />
  containers:<br />
  - name: networkpolicy-pod<br />
    image: registry.access.redhat.com/ubi9/ubi-minimal<br />
    command: [“sleep”, “infinity”]<br />
EOF<br />
pod/networkpolicy-pod created<br />
[rosa@bastion ~]$</p>

<p>1.3. Now we will change to the microsweeper-ex project to start applying the network policies:<br />
[rosa@bastion ~]$ oc project microsweeper-ex<br />
Now using project “microsweeper-ex” on server “https://api.rosa-88qgb.zpku.p3.openshiftapps.com:443”.<br />
[rosa@bastion ~]$</p>

<p>1.4. Fetch the IP address of the microsweeper pod:<br />
[rosa@bastion ~]$ MS_IP=$(oc -n microsweeper-ex get pod -l \<br />
  “app.kubernetes.io/name=microsweeper-appservice” \<br />
  -o jsonpath=”{.items[0].status.podIP}”)<br />
echo $MS_IP<br />
10.130.0.38<br />
[rosa@bastion ~]$</p>

<p>1.5. Check to see if the networkpolicy-pod can access the microsweeper pod:<br />
[rosa@bastion ~]$ oc -n networkpolicy-test exec -ti pod/networkpolicy-pod -- curl $MS_IP:8080 | head<br />
&lt;!DOCTYPE html&gt;<br />
&lt;html lang=”en”&gt;<br />
&lt;head&gt;<br />
    &lt;meta charset=”UTF-8”&gt;<br />
    &lt;meta name=”viewport” content=”width=device-width, initial-scale=1.0”&gt;<br />
    &lt;meta http-equiv=”X-UA-Compatible” content=”ie=edge”&gt;<br />
    &lt;title&gt;Microsweeper&lt;/title&gt;<br />
    &lt;link rel=”stylesheet” href=”css/main.css”&gt;<br />
    &lt;script<br />
            src=”https://code.jquery.com/jquery-3.2.1.min.js”</p>

<p>1.6. It’s common to want to not allow Pods from another Project.<br />
This can be done by a fairly simple Network Policy.</p>

<p>This Network Policy will restrict Ingress to the pods in the project microsweeper-ex to just the OpenShift Ingress pods which run in the project with label <a href="http://network.openshift.io/policy-group=ingress">network.openshift.io/policy-group=ingress</a></p>

<p>[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: networking.k8s.io/v1<br />
kind: NetworkPolicy<br />
metadata:<br />
  name: allow-from-openshift-ingress<br />
  namespace: microsweeper-ex<br />
spec:<br />
  ingress:<br />
  - from:<br />
    - namespaceSelector:<br />
        matchLabels:<br />
          network.openshift.io/policy-group: ingress<br />
  podSelector: {}<br />
  policyTypes:<br />
  - Ingress<br />
EOF<br />
networkpolicy.networking.k8s.io/allow-from-openshift-ingress created<br />
[rosa@bastion ~]$</p>

<p>1.7. Try to access microsweeper from the networkpolicy-pod again<br />
osa@bastion ~]$ oc -n networkpolicy-test exec -ti pod/networkpolicy-pod -- curl $MS_IP:8080 | head<br />
command terminated with exit code 130<br />
^C[rosa@bastion ~]$ <br />
This time it should fail to connect - it will just sit there. Hit CTRL+c to avoid having to wait until a timeout.</p>

<p>|  | If you have your browser still open to the microsweeper app, you can refresh and see that you can still access it. This is because your web browser connect to the Ingress controllers - which per the NetworkPolicy are allowed to connect to this project. |
| :—- | :—- |</p>

<p>Sometimes you want your application to be accessible to other namespaces. You can allow access to just your microsweeper frontend from the networkpolicy-pod in the networkpolicy-test namespace like so:<br />
C[rosa@bastion ~]cat &lt;&lt;EOF | oc apply -f - -<br />
-–<br />
kind: NetworkPolicy<br />
apiVersion: networking.k8s.io/v1<br />
metadata:<br />
  name: allow-networkpolicy-pod-ap<br />
  namespace: microsweeper-ex<br />
spec:<br />
  podSelector:<br />
    matchLabels:<br />
      app.kubernetes.io/name: microsweeper-appservice<br />
  ingress:<br />
  - from:<br />
    - namespaceSelector:<br />
        matchLabels:<br />
          kubernetes.io/metadata.name: networkpolicy-test<br />
      podSelector:<br />
        matchLabels:<br />
          app: networkpolicy<br />
EOF<br />
networkpolicy.networking.k8s.io/allow-networkpolicy-pod-ap created</p>

<p>1.9.Check to see if networkpolicy-pod can access the pod:<br />
[rosa@bastion ~]$ oc -n networkpolicy-test exec -ti pod/networkpolicy-pod -- curl $MS_IP:8080 | head<br />
&lt;!DOCTYPE html&gt;<br />
&lt;html lang=”en”&gt;<br />
&lt;head&gt;<br />
    &lt;meta charset=”UTF-8”&gt;<br />
    &lt;meta name=”viewport” content=”width=device-width, initial-scale=1.0”&gt;<br />
    &lt;meta http-equiv=”X-UA-Compatible” content=”ie=edge”&gt;<br />
    &lt;title&gt;Microsweeper&lt;/title&gt;<br />
    &lt;link rel=”stylesheet” href=”css/main.css”&gt;<br />
    &lt;script<br />
            src=”https://code.jquery.com/jquery-3.2.1.min.js”<br />
[rosa@bastion ~]$</p>

<p>1.10. To verify that only the networkpolicy-pod app can access the microsweeper app, create a new pod with a different label in the networkpolicy-test namespace.<br />
[rosa@bastion ~]$ cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: v1<br />
kind: Pod<br />
metadata:<br />
  name: new-test<br />
  namespace: networkpolicy-test<br />
  labels:<br />
    app: new-test<br />
spec:<br />
  securityContext:<br />
    allowPrivilegeEscalation: false<br />
    runAsNonRoot: true<br />
    seccompProfile:<br />
      type: RuntimeDefault<br />
    capabilities:<br />
    drop:<br />
    - ALL<br />
  containers:<br />
    - name: new-test<br />
      image: registry.access.redhat.com/ubi9/ubi-minimal<br />
      command: [“sleep”, “infinity”]<br />
EOF<br />
pod/new-test created<br />
1.11. Try to curl the microsweeper-ex pod from our new pod.:<br />
This will fail with a timeout again. Hit CTRL+c to avoid waiting for a timeout.<br />
[rosa@bastion ~]$ oc -n networkpolicy-test exec -ti pod/new-test -- curl $MS_IP:8080 | head<br />
command terminated with exit code 130<br />
^C[rosa@bastion ~]$ <br />
For information on setting default network policies for new projects you can read the OpenShift documentation on <a href="https://docs.openshift.com/container-platform/4.13/networking/network_policy/default-network-policy.html">modifying the default project template</a>.</p>

<p><a href="https://bastion.88qgb.sandbox2714.opentlc.com/showroom/modules/300-apps/lab_4_resilient_app.html"><strong>Make your application resilient</strong></a></p>

<p>##</p>

<h2 id="1-setting-limits--requests-on-an-application">1. Setting Limits &amp; Requests on an Application</h2>

<p><strong>1</strong>.1. First, let’s set limits and requests on the previously deployed microsweeper application.<br />
^C[rosa@bastion ~]oc -n microsweeper-ex set resources deployment/microsweeper-appservice \ \<br />
  --limits=cpu=60m,memory=250Mi \<br />
  --requests=cpu=50m,memory=200Mi<br />
deployment.apps/microsweeper-appservice resource requirements updated<br />
[rosa@bastion ~]$ <br />
Requests state the minimum CPU and memory requirements for a container. This will ensure that the pod is placed on a node that can meet those requirements. Limits set the maximum amount of CPU and Memory that can be consumed by a container and ensure that a whole container does not consume all of the resources on a node. Setting limits and requests for deployments is best practice for resource management and ensuring the stability and reliability of your applications.</p>

<p>|  | It is important to know the resource needs of the application before setting limits and requests to avoid resource starvation or over allocating resources. If you are unsure of the resource consumption of your application, you can use ‘oc adm top pods’ to view the current memory and CPU being currently consumed by each pod. Running the following command multiple times while the application is running can help set a general picture. If you get an error that no metrics are available yet wait a few seconds and try again. It may take a few minutes for the metrics to be available. |
| :—- | :—- |</p>

<p>[rosa@bastion ~]$ oc adm top pod -n microsweeper-ex -l app.kubernetes.io/name=microsweeper-appservice<br />
NAME                                       CPU(cores)   MEMORY(bytes)   <br />
microsweeper-appservice-6f59cf55d5-pgq64   0m           62Mi</p>

<p>1.2. Now that we’ve updated the resource, we can see that a new pod was automatically rolled out with these new limits and requests. To do so, run the following command:<br />
[rosa@bastion ~]$ oc get pods -n microsweeper-ex<br />
NAME                                       READY   STATUS    RESTARTS   AGE<br />
microsweeper-appservice-6f59cf55d5-pgq64   1/1     Running   0          9m1s<br />
[rosa@bastion ~]$ <br />
To see what the limits and requests added to the pod, run the following command, being sure to change the Pod name to the name shown in the above output:<br />
rosa@bastion ~]$ oc get pods -l app.kubernetes.io/name=microsweeper-appservice \<br />
 -o yaml -n microsweeper-ex | grep limits -A5<br />
        limits:<br />
          cpu: 60m<br />
          memory: 250Mi<br />
        requests:<br />
          cpu: 50m<br />
          memory: 200Mi<br />
[rosa@bastion ~]$ <br />
1.3. We can now use the route of the application to ensure the application is functioning with the new limits and requests. To get the route, run the following command:<br />
[rosa@bastion ~]$ oc -n microsweeper-ex get route microsweeper-appservice \<br />
  -o jsonpath=’http://{.spec.host}{“\n”}’<br />
http://microsweeper-appservice-microsweeper-ex.apps.rosa.rosa-88qgb.zpku.p3.openshiftapps.com<br />
[rosa@bastion ~]$ <br />
Then visit the URL presented in a new tab in your web browser (using HTTP). For example, your output will look something similar to:<br />
In that case, you’d visit http://microsweeper-appservice-microsweeper-ex.apps.test-cluster.2ubs.p1.openshiftapps.com in your browser.</p>

<p>1.4.Initially, this application is deployed with only one pod. In the event a worker node goes down or the pod crashes, there will be an outage of the application. To prevent that, let’s scale the number of instances of our applications up to three. To do so, run the following command:<br />
[rosa@bastion ~]$ oc -n microsweeper-ex get route microsweeper-appservice \<br />
  -o jsonpath=’http://{.spec.host}{“\n”}’<br />
http://microsweeper-appservice-microsweeper-ex.apps.rosa.rosa-f8jdx.5wl4.p3.openshiftapps.com<br />
[rosa@bastion ~]$ oc -n microsweeper-ex scale deployment \<br />
  microsweeper-appservice --replicas=3<br />
deployment.apps/microsweeper-appservice scaled<br />
[rosa@bastion ~]$</p>

<p>1.5. Next, let’s check to see that the application has scaled. To do so, run the following command to see the pods:<br />
[rosa@bastion ~]$ oc -n microsweeper-ex get pods<br />
NAME                                      READY   STATUS    RESTARTS   AGE<br />
microsweeper-appservice-cdcc86df9-4snkq   1/1     Running   0          7m42s<br />
microsweeper-appservice-cdcc86df9-blrhz   1/1     Running   0          83s<br />
microsweeper-appservice-cdcc86df9-zml6r   1/1     Running   0          83s<br />
[rosa@bastion ~]$</p>

<p>1.6. In addition you can see the number of pods, how many are on the current version, and how many are available by running the following:<br />
osa@bastion ~]$ oc -n microsweeper-ex get deployment microsweeper-appservice<br />
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE<br />
microsweeper-appservice   3/3     3            3           35m<br />
[rosa@bastion ~]$</p>

<h2 id="2-pod-disruption-budget">2. Pod Disruption Budget</h2>

<p>2.1.Let’s create a Pod Disruption Budget for our microsweeper-appservice application. To do so, run the following command:<br />
[rosa@bastion ~]$ cat &lt;&lt;EOF | oc apply -f -<br />
apiVersion: policy/v1<br />
kind: PodDisruptionBudget<br />
metadata:<br />
  name: microsweeper-appservice-pdb<br />
  namespace: microsweeper-ex<br />
spec:<br />
  minAvailable: 1<br />
  selector:<br />
    matchLabels:<br />
      deployment: microsweeper-appservice<br />
EOF<br />
poddisruptionbudget.policy/microsweeper-appservice-pdb created<br />
[rosa@bastion ~]$ <br />
After creating the PDB, the OpenShift API will ensure at least one pod of microsweeper-appservice is running all the time, even when maintenance is going on within the cluster.</p>

<p>2.2. Next, let’s check the status of Pod Disruption Budget. To do so, run the following command:<br />
[rosa@bastion ~]$ oc -n microsweeper-ex get poddisruptionbudgets<br />
NAME                          MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE<br />
microsweeper-appservice-pdb   1               N/A               2                     75s<br />
[rosa@bastion ~]$</p>

<h2 id="3-horizontal-pod-autoscaler-hpa">3. Horizontal Pod Autoscaler (HPA)</h2>

<p>As a developer, you can utilize a horizontal pod autoscaler (HPA) in ROSA clusters to automate scaling of replication controllers or deployment configurations. The HPA adjusts the scale based on metrics gathered from the associated pods. It is applicable to deployments, replica sets, replication controllers, and stateful sets.<br />
The HPA (Horizontal Pod Autoscaler) provides you with automated scaling capabilities, optimizing resource management and improving application performance. By leveraging an HPA, you can ensure your applications dynamically scale up or down based on workload. This automation reduces the manual effort of adjusting application scale and ensures efficient resource utilization, by only using resources that are needed at a certain time. Additionally, the HPA’s ease of configuration and compatibility with various workload types make it a flexible and scalable solution for developers in managing their applications.<br />
In this exercise we will scale the microsweeper-appservice application based on CPU utilization:</p>

<ul>
  <li>Scale out when average CPU utilization is greater than 50% of CPU limit</li>
  <li>Maximum pods is 4</li>
  <li>Scale down to min replicas if utilization is lower than threshold for 60 sec</li>
</ul>

<p>3.1. First, we should create the HorizontalPodAutoscaler. To do so, run the following command:</p>

<ol>
  <li>
    <table>
      <tbody>
        <tr>
          <td>[rosa@bastion ~]$ cat &lt;&lt;EOF</td>
          <td>oc apply -f -</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>apiVersion: autoscaling/v2</li>
  <li>kind: HorizontalPodAutoscaler</li>
  <li>metadata:</li>
  <li>name: microsweeper-appservice-cpu</li>
  <li>namespace: microsweeper-ex</li>
  <li>spec:</li>
  <li>scaleTargetRef:</li>
  <li>apiVersion: apps/v1</li>
  <li>kind: Deployment</li>
  <li>name: microsweeper-appservice</li>
  <li>minReplicas: 2</li>
  <li>maxReplicas: 4</li>
  <li>metrics:</li>
  <li>- type: Resource</li>
  <li>resource:</li>
  <li>name: cpu</li>
  <li>target:</li>
  <li>averageUtilization: 50</li>
  <li>type: Utilization</li>
  <li>behavior:</li>
  <li>scaleDown:</li>
  <li>stabilizationWindowSeconds: 60</li>
  <li>policies:</li>
  <li>- type: Percent</li>
  <li>value: 100</li>
  <li>periodSeconds: 15</li>
  <li>EOF</li>
  <li>horizontalpodautoscaler.autoscaling/microsweeper-appservice-cpu created</li>
  <li>[rosa@bastion ~]$</li>
  <li></li>
</ol>

<p>3.2. Next, check the status of the HPA. To do so, run the following command:<br />
[rosa@bastion ~]$ oc -n microsweeper-ex get horizontalpodautoscaler/microsweeper-appservice-cpu<br />
NAME                          REFERENCE                            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE<br />
microsweeper-appservice-cpu   Deployment/microsweeper-appservice   0%/50%    2         4         2          94s</p>

<p>Next, let’s generate some load against the microsweeper-appservice application. To do so, run the following command:<br />
[rosa@bastion ~]$ FRONTEND_URL=http://$(oc -n microsweeper-ex get route microsweeper-appservice -o jsonpath=’{.spec.host}’)/</p>

<p>ab -c100 -n10000 ${FRONTEND_URL}<br />
This is ApacheBench, Version 2.3 &lt;$Revision: 1903618 $&gt;<br />
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br />
Licensed to The Apache Software Foundation, http://www.apache.org/</p>

<p>Benchmarking microsweeper-appservice-microsweeper-ex.apps.rosa.rosa-f8jdx.5wl4.p3.openshiftapps.com (be patient)<br />
Completed 1000 requests<br />
Completed 2000 requests<br />
Completed 3000 requests<br />
Completed 4000 requests<br />
Completed 5000 requests<br />
Completed 6000 requests<br />
Completed 7000 requests<br />
Completed 8000 requests<br />
Completed 9000 requests<br />
Completed 10000 requests<br />
Finished 10000 requests</p>

<p>Server Software:        <br />
Server Hostname:        microsweeper-appservice-microsweeper-ex.apps.rosa.rosa-f8jdx.5wl4.p3.openshiftapps.com<br />
Server Port:            80</p>

<p>Document Path:          /<br />
Document Length:        0 bytes</p>

<p>Concurrency Level:      100<br />
Time taken for tests:   0.752 seconds<br />
Complete requests:      10000<br />
Failed requests:        0<br />
Non-2xx responses:      10000<br />
Total transferred:      1920000 bytes<br />
HTML transferred:       0 bytes<br />
Requests per second:    13290.33 [#/sec] (mean)<br />
Time per request:       7.524 [ms] (mean)<br />
Time per request:       0.075 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          2491.94 [Kbytes/sec] received</p>

<p>Connection Times (ms)<br />
              min  mean[+/-sd] median   max<br />
Connect:        1    3   0.8      3       9<br />
Processing:     1    4   2.7      4      41<br />
Waiting:        1    4   2.6      3      41<br />
Total:          3    7   2.9      7      44</p>

<p>Percentage of the requests served within a certain time (ms)<br />
  50%      7<br />
  66%      7<br />
  75%      8<br />
  80%      8<br />
  90%      9<br />
  95%     13<br />
  98%     16<br />
  99%     20<br />
 100%     44 (longest request)<br />
[rosa@bastion ~]$</p>

<p>3.4. Apache Bench will take around 100 seconds to complete (you can also hit CTRL+c to kill the ab command). Then immediately check the status of Horizontal Pod Autoscaler. To do so, run the following command:</p>

<p>a@bastion ~]$ oc -n microsweeper-ex get horizontalpodautoscaler/microsweeper-appservice-cpu<br />
NAME                          REFERENCE                            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE<br />
microsweeper-appservice-cpu   Deployment/microsweeper-appservice   0%/50%    2         4         2          11m<br />
[rosa@bastion ~]$ <br />
This means you are now running 4 replicas, instead of the original three that we started with.</p>

<p>3.5. Once you’ve killed the ab command, the traffic going to microsweeper-appservice service will cool down and after a 60 second cool down period, your application’s replica count will drop back down to two. To demonstrate this, run the following command:<br />
^C[rosa@bastion ~]oc -n microsweeper-ex get horizontalpodautoscaler/microsweeper-appservice-cpu --watchch<br />
NAME                          REFERENCE                            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE<br />
microsweeper-appservice-cpu   Deployment/microsweeper-appservice   0%/50%    2         4         2          16m</p>

<ul>
  <li><a href="https://bastion.f8jdx.sandbox629.opentlc.com/showroom/modules/400-service-mesh/lab_1_service_mesh_introduction.html"><strong>Service Mesh Introduction</strong></a></li>
</ul>

<p>As your applications evolve into collections of decentralized microservices, monitoring and managing the network communications and security among those multiple services becomes more challenging.<br />
Red Hat OpenShift Service Mesh is based on the open source project Istio. It provides a uniform way to connect, manage, and observe microservices based applications. It provides behavioral insight into and control of the networked microservices in your service mesh.</p>

<p>##</p>

<h2 id="why-red-hat-service-mesh">Why Red Hat Service Mesh?</h2>

<p>Applications are changing from monoliths into collections of small, independent, and loosely coupled services often referred to as cloud-native applications. These services are organized in a microservices architecture.<br />
Managing the communication between different services, and analyzing and maintaining security, can be a challenge. This can be greatly simplified and optimized by using a service mesh to route requests from one service to another, and optimizing how the different services work with one another.<br />
With Red Hat OpenShift Service Mesh, you get a uniform way to connect, manage, and observe your microservices, without requiring you to redesign your application. As your containers and services evolve, Service Mesh allows you control of—​the networked microservices through the use of a sidecar proxy that intercepts network communication between microservices. OpenShift Service Mesh provides integrated metrics, logging, and tracing, traditionally available only deep within the application or service.</p>

<h2 id="red-hat-service-mesh-benefits">Red Hat Service Mesh Benefits</h2>

<h3 id="ready-for-production">Ready for production</h3>

<p>Installs easily on Red Hat OpenShift, the hybrid cloud enterprise Kubernetes platform trusted by thousands of organizations around the globe. Red Hat OpenShift Service Mesh is pre-validated and fully supported to work on Red Hat OpenShift, straight out of the box.</p>

<h3 id="security-focused">Security-focused</h3>

<p>Red Hat OpenShift Service Mesh provides comprehensive application networking security. This is achieved through transparent mTLS encryption and fine-grained policies that facilitate zero-trust networking.</p>

<p>###</p>

<h3 id="based-on-open-source">Based on open source</h3>

<p>Based on the open source Istio project, Red Hat OpenShift Service Mesh provides additional functionality with the inclusion of other open source projects like Kiali (Istio console) and Jaeger (distributed tracing), which supports collaboration with leading members of the Istio community.</p>

<p>##</p>

<h2 id="use-cases">Use Cases</h2>

<ul>
  <li>Connectivity: Connect Traffic Flow, Blue/Green Deployments, Circuit Breaking, Virtual Services</li>
  <li>Security: Data-in-transit Encryption, Authentication, Authorization, Secure Naming</li>
  <li>Control: Configuration, Apply/Enforce Policies, Fair Resource Distribution</li>
  <li>Observability: Layer 7 Visibility, Monitoring, Logging, Distributed Tracing</li>
</ul>

<p>##</p>

<h2 id="differences-to-istio">Differences to Istio</h2>

<ul>
  <li>OpenShift Service Mesh installs a multi-tenant control plane by default</li>
  <li>OpenShift Service Mesh extends Role Based Access Control (RBAC) features</li>
  <li>OpenShift Service Mesh replaces BoringSSL with OpenSSL</li>
  <li>Kiali and Jaeger are enabled by default in OpenShift Service Mesh</li>
</ul>

<p>##</p>

<h2 id="what-is-the-advantage-of-choosing-red-hat-service-mesh">What is the advantage of choosing Red Hat Service Mesh?</h2>

<ul>
  <li>Red Hat helps you get started faster because OpenShift Service Mesh is engineered to be ready for production.</li>
  <li>With OpenShift Service Mesh developers can increase productivity by integrating communication policies without changing application code or integrating language-specific libraries.</li>
  <li>
    <p>OpenShift Service Mesh can also make things easier for operations because it installs easily on Red Hat OpenShift, has been tested with other Red Hat products, and comes with access to award-winning support.</p>
  </li>
  <li>
    <p><a href="https://bastion.f8jdx.sandbox629.opentlc.com/showroom/modules/400-service-mesh/lab_2_service_mesh_deploy_operator.html"><strong>Install Service Mesh Operator</strong></a></p>
  </li>
  <li>
    <p>##</p>
  </li>
  <li>
    <h2 id="1-operator-overview">1. Operator Overview</h2>
  </li>
  <li>OpenShift Elasticsearch Operator - Provides database storage for tracing and logging with the distributed tracing platform. It is based on the open core Elasticsearch project. Use the stable channel.</li>
  <li>Red Hat OpenShift distributed tracing platform - Provides distributed tracing to monitor and troubleshoot transactions in complex distributed systems. It is based on the open source Jaeger project. Use the stable channel.</li>
  <li>Kiali Operator - Provides observability for your service mesh. Allows you to view configurations, monitor traffic, and analyze traces in a single console. It is based on the open source Kiali project. Use the stable channel.</li>
  <li>
    <p>Red Hat OpenShift Service Mesh - Allows you to connect, secure, control, and observe the microservices that comprise your applications. The Service Mesh Operator defines and monitors the ServiceMeshControlPlane resources that manage the deployment, updating, and deletion of the Service Mesh components. It is based on the open source Istio project. Use the stable channel.</p>
  </li>
  <li>
    <p>###</p>
  </li>
  <li>
    <h3 id="11-operator-installation-procedure">1.1. Operator installation Procedure</h3>
  </li>
  <li>1.1.1. If you are not still there open the OpenShift Container Platform web console. If you need to remind yourself of the URL you can use one of the following two commands in your terminal:</li>
  <li>osa@bastion ~]oc whoami --show-consolele</li>
  <li>https://console-openshift-console.apps.rosa.rosa-f8jdx.5wl4.p3.openshiftapps.com</li>
  <li>[rosa@bastion ~]$</li>
  <li></li>
  <li>1.2.In the OpenShift Container Platform web console, click Operators → OperatorHub.</li>
  <li></li>
  <li>1.3.For each operator in this list install the operator in the order listed.
    <ul>
      <li>OpenShift Elasticsearch Operator</li>
      <li>Red Hat OpenShift distributed tracing platform (careful! There is a second one with a very similar name!)</li>
      <li>Kiali Operator</li>
      <li>Red Hat OpenShift Service Mesh</li>
    </ul>
  </li>
  <li>1.4.Repeat the following steps to install the operator:
    <ol>
      <li>Type the name of the Operator into the filter box and select the Red Hat version of the Operator. Community versions of the Operators are not supported.</li>
      <li>Click Install.</li>
      <li>On the Install Operator page for each Operator, double check the channel and otherwise accept the default settings.</li>
      <li>Click Install.</li>
      <li>Wait until the Operator has installed before repeating the steps for the next Operator in the list.</li>
    </ol>
  </li>
</ul>

<p>1.5.After all you have installed all four Operators, click Operators → Installed Operators to verify that your Operators installed (you may need to select the openshift-operators project to see all operators).</p>

<ul>
  <li><a href="https://bastion.f8jdx.sandbox629.opentlc.com/showroom/modules/400-service-mesh/lab_3_service_mesh_deploy_control_plane.html"><strong>Deploy Service Mesh Control Plane</strong></a></li>
</ul>

<p>Based on the open source Istio project, Red Hat OpenShift Service Mesh adds a transparent layer on existing distributed applications without requiring any changes to the service code. You add Red Hat OpenShift Service Mesh support to services by deploying a special sidecar proxy to relevant services in the mesh that intercepts all network communication between microservices. You configure and manage the Service Mesh using the Service Mesh control plane features. To learn more about the OpenShift Service Mesh, review the <a href="https://docs.openshift.com/rosa/service_mesh/v2x/ossm-about.html">OpenShift documentation</a>.</p>

<p>##</p>

<h2 id="1-deploy-control-plane">1. Deploy Control Plane</h2>

<p>1.1 First, let’s create a project (namespace) for us to deploy the service mesh control plane into. To do so, run the following command:</p>

<p>w using project “istio-system” on server “https://api.rosa-f8jdx.5wl4.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>1.2. Next, let’s deploy the service mesh control plane. To do so, run the following command:</p>

<table>
  <tbody>
    <tr>
      <td>[rosa@bastion ~]$ cat &lt;&lt; EOF</td>
      <td>oc apply -f -</td>
    </tr>
  </tbody>
</table>

<p>-–</p>

<p>apiVersion: maistra.io/v2</p>

<p>kind: ServiceMeshControlPlane</p>

<p>metadata:</p>

<p>name: basic</p>

<p>namespace: istio-system</p>

<p>spec:</p>

<p>version: v2.2</p>

<p>security:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>identity:

  type: ThirdParty
</code></pre></div></div>

<p>tracing:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type: Jaeger

sampling: 10000
</code></pre></div></div>

<p>addons:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jaeger:

  name: jaeger

  install:

    storage:

      type: Memory

kiali:

  enabled: true

  name: kiali

grafana:

  enabled: true
</code></pre></div></div>

<p>EOF</p>

<p>Error from server (BadRequest): error when creating “STDIN”: admission webhook “smcp.validation.maistra.io” denied the request: Only ‘[v2.5 v2.3 v2.4 v2.6]’ versions are supported</p>

<p>[rosa@bastion ~]$</p>

<ul>
  <li><a href="https://bastion.f8jdx.sandbox629.opentlc.com/showroom/modules/400-service-mesh/lab_4_service_mesh_deploy_app.html"><strong>Deploy a Service Mesh example application</strong></a></li>
</ul>

<h2 id="1-create-and-configure-a-project-for-the-service-mesh">1. Create and configure a project for the service mesh</h2>

<p>1.1. First, let’s create a project (namespace) for us to deploy our workload into. To do so, run the following command:</p>

<p>[rosa@bastion ~]$ oc new-project bookinfo</p>

<p>Now using project “bookinfo” on server “https://api.rosa-f8jdx.5wl4.p3.openshiftapps.com:443”.</p>

<p>You can add applications to this project with the ‘new-app’ command. For example, try:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oc new-app rails-postgresql-example
</code></pre></div></div>

<p>to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname

kubectl create deployment hello-node \--image=registry.k8s.io/e2e-test-images/agnhost:2.43 \-- /agnhost serve-hostname
</code></pre></div></div>

<p>1,2, Next, let’s label that project (namespace) to enable the service mesh injection for all applications in the project.</p>

<p>[rosa@bastion ~]$ oc label namespace bookinfo istio-injection=enabled</p>

<p>namespace/bookinfo labeled</p>

<p>[rosa@bastion ~]$</p>

<p>1.3. Even though we’ve enabled service mesh injection in the project, we also need to add our project (namespace) to the ServiceMeshMemberRoll, which limits the scope of the service mesh control plane to only projects in the member roll. To add the project to the ServiceMeshMemberRoll, run the following command:</p>

<table>
  <tbody>
    <tr>
      <td>rosa@bastion ~]$ cat &lt;&lt; EOF</td>
      <td>oc apply -f -</td>
    </tr>
  </tbody>
</table>

<p>-–</p>

<p>apiVersion: maistra.io/v1</p>

<p>kind: ServiceMeshMemberRoll</p>

<p>metadata:</p>

<p>name: default</p>

<p>namespace: istio-system</p>

<p>spec:</p>

<p>members:</p>

<p>- bookinfo</p>

<p>EOF</p>

<p>servicemeshmemberroll.maistra.io/default created</p>

<p>[rosa@bastion ~]$</p>

<p>1.4. Next, let’s verify the ServiceMeshMemberRoll was created successfully. To do so, run the following command:</p>

<p>rosa@bastion ~]$ oc -n istio-system get smmr -o wide</p>

<p>NAME      READY   STATUS           AGE   MEMBERS</p>

<p>default   0/1     ErrSMCPMissing   66s   [“bookinfo”]</p>

<p>[rosa@bastion ~]$</p>

<p>The service mesh member roll was successfully configured when the STATUS column is Configured and your project shows up in the MEMBERS column.</p>

<h3 id="21-deploy-our-test-workload">2.1. Deploy our test workload</h3>

<p>2,1,1.Now that we’ve configured the service mesh for our project, let’s deploy our bookinfo workload into our project. To do so, run the following command to create the necessary resources:</p>

<p>rosa@bastion ~]$ oc -n bookinfo apply -f \</p>

<p>https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo.yaml</p>

<p>service/details created</p>

<p>serviceaccount/bookinfo-details created</p>

<p>deployment.apps/details-v1 created</p>

<p>service/ratings created</p>

<p>serviceaccount/bookinfo-ratings created</p>

<p>deployment.apps/ratings-v1 created</p>

<p>service/reviews created</p>

<p>serviceaccount/bookinfo-reviews created</p>

<p>deployment.apps/reviews-v1 created</p>

<p>deployment.apps/reviews-v2 created</p>

<p>deployment.apps/reviews-v3 created</p>

<p>service/productpage created</p>

<p>serviceaccount/bookinfo-productpage created</p>

<p>deployment.apps/productpage-v1 created</p>

<p>[rosa@bastion ~]$</p>

<p>Interested in seeing the configuration you’re deploying? Check it out on GitHub <a href="https://github.com/rh-mobb/rosa-workshop-content/blob/main/rosa-content/assets/scripts/bookinfo.yaml">here</a>.</p>

<p>2.2.Now, let’s create the service mesh ingress gateway. To do so, run the following command:</p>

<p>[rosa@bastion ~]$ oc -n bookinfo apply -f \</p>

<p>https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo-gateway.yaml</p>

<p>resource mapping not found for name: “bookinfo-gateway” namespace: “” from “https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo-gateway.yaml”: no matches for kind “Gateway” in version “networking.istio.io/v1alpha3”</p>

<p>ensure CRDs are installed first</p>

<p>resource mapping not found for name: “bookinfo” namespace: “” from “https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo-gateway.yaml”: no matches for kind “VirtualService” in version “networking.istio.io/v1alpha3”</p>

<p>ensure CRDs are installed first</p>

<p>[rosa@bastion ~]$</p>

<p>2.3. Next, let’s add some destination rules. Destination rules define policies that apply to traffic intended for a service after routing has occurred. To create the rules, run the following command:</p>

<p>osa@bastion ~]$ oc -n bookinfo apply -f \</p>

<p>https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/destination-rule-all.yaml</p>

<p>resource mapping not found for name: “productpage” namespace: “” from “https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/destination-rule-all.yaml”: no matches for kind “DestinationRule” in version “networking.istio.io/v1alpha3”</p>

<p>ensure CRDs are installed first</p>

<p>resource mapping not found for name: “reviews” namespace: “” from “https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/destination-rule-all.yaml”: no matches for kind “DestinationRule” in version “networking.istio.io/v1alpha3”</p>

<p>ensure CRDs are installed first</p>

<p>resource mapping not found for name: “ratings” namespace: “” from “https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/destination-rule-all.yaml”: no matches for kind “DestinationRule” in version “networking.istio.io/v1alpha3”</p>

<p>ensure CRDs are installed first</p>

<p>resource mapping not found for name: “details” namespace: “” from “https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/destination-rule-all.yaml”: no matches for kind “DestinationRule” in version “networking.istio.io/v1alpha3”</p>

<p>ensure CRDs are installed first</p>

<p>[rosa@bastion ~]$</p>

<ul>
  <li><a href="https://bastion.f8jdx.sandbox629.opentlc.com/showroom/modules/400-service-mesh/lab_4_service_mesh_deploy_app.html"><strong>Deploy a Service Mesh example application</strong></a></li>
  <li>
    <p>Now that your Red Hat Service Mesh has been deployed on your ROSA cluster you can actually use it to connect the microservices of an example application. You will use the standard Service Mesh example application called Bookinfo.</p>
  </li>
  <li>
    <p>##</p>
  </li>
  <li>
    <h2 id="1-create-and-configure-a-project-for-the-service-mesh-1">1. Create and configure a project for the service mesh</h2>
  </li>
  <li>1.1. First, let’s create a project (namespace) for us to deploy our workload into. To do so, run the following command:</li>
  <li>

    <p>oc new-project bookinfo</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  1.2. Next, let’s label that project (namespace) to enable the service mesh      injection for all applications in the project.
</code></pre></div>    </div>
  </li>
</ul>

<p>oc label namespace bookinfo istio-injection=enabled</p>

<p>1.3. Even though we’ve enabled service mesh injection in the project, we also need to add our project (namespace) to the ServiceMeshMemberRoll, which limits the scope of the service mesh control plane to only projects in the member roll. To add the project to the ServiceMeshMemberRoll, run the following command:</p>

<table>
  <tbody>
    <tr>
      <td>cat &lt;&lt; EOF</td>
      <td>oc apply -f -</td>
    </tr>
  </tbody>
</table>

<p>-–</p>

<p>apiVersion: maistra.io/v1</p>

<p>kind: ServiceMeshMemberRoll</p>

<p>metadata:</p>

<p>name: default</p>

<p>namespace: istio-system</p>

<p>spec:</p>

<p>members:</p>

<p>- bookinfo</p>

<p>EOF</p>

<p>Next, let’s verify the ServiceMeshMemberRoll was created successfully. To do so, run the following command:</p>

<p>oc -n istio-system get smmr -o wide</p>

<p>###</p>

<h3 id="11-deploy-our-test-workload">1.1. Deploy our test workload</h3>

<p>Now that we’ve configured the service mesh for our project, let’s deploy our bookinfo workload into our project. To do so, run the following command to create the necessary resources:</p>

<p>1.3.oc -n bookinfo apply -f \</p>

<p><a href="https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo.yaml">https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo.yaml</a></p>

<p>Interested in seeing the configuration you’re deploying? Check it out on GitHub <a href="https://github.com/rh-mobb/rosa-workshop-content/blob/main/rosa-content/assets/scripts/bookinfo.yaml">here</a>.</p>

<p>1.2. Now, let’s create the service mesh ingress gateway. To do so, run the following command:</p>

<p>oc -n bookinfo apply -f \</p>

<p><a href="https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo-gateway.yaml">https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/bookinfo-gateway.yaml</a></p>

<p>Next, let’s add some destination rules. Destination rules define policies that apply to traffic intended for a service after routing has occurred. To create the rules, run the following command:</p>

<p>oc -n bookinfo apply -f \</p>

<p><a href="https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/destination-rule-all.yaml">https://raw.githubusercontent.com/rh-mobb/rosa-workshop-content/main/rosa-content/assets/scripts/destination-rule-all.yaml</a></p>

<h2 id="verifying-the-bookinfo-installation">Verifying the Bookinfo installation</h2>

<p>oc -n bookinfo get pods</p>

<p>Next, let’s get the URL for the product page. To do so, run the following command:</p>

<p>echo “http://$(oc -n istio-system get route istio-ingressgateway -o jsonpath=’{.spec.host}’)/productpage”</p>

<p>This is a http URL. Some browsers convert that automatically to https and will not show the page.</p>

<p>Copy and paste the URL provided in the previous step into your web browser and verify the Bookinfo product page is successfully deployed.<br />
You should see a book review of “The Comedy of Errors”. If you see an “Error fetching product reviews!” message wait a little bit and then refresh the browser window. It takes a moment for the reviews service to be fully available.</p>

<ul>
  <li><a href="https://bastion.f8jdx.sandbox629.opentlc.com/showroom/modules/400-service-mesh/lab_5_service_mesh_observe.html"><strong>Configure and observe Service Mesh traffic</strong></a></li>
</ul>

<p>In this section you will configure and observe traffic between the micro services that make up the example application.<br />
Requests are routed to services within a service mesh with virtual services. Each virtual service consists of a set of routing rules that are evaluated in order. Red Hat OpenShift Service Mesh matches each given request to the virtual service to a specific real destination within the mesh.<br />
Without virtual services, Red Hat OpenShift Service Mesh distributes traffic using round-robin load balancing between all service instances. With a virtual service, you can specify traffic behavior for one or more hostnames. Routing rules in the virtual service tell Red Hat OpenShift Service Mesh how to send the traffic for the virtual service to appropriate destinations. Route destinations can be versions of the same service or entirely different services.</p>

<p>##</p>

<h2 id="1-configuring-virtual-services-with-weighted-load-balancing">1. Configuring virtual services with weighted load balancing</h2>

<p>1,1, Weighted load balancing requests are forwarded to instances in the pool according to a specific percentage. In this example 80% to v1, 20% to v2. To create a virtual service with this configuration, run the following command:<br />
cat &lt;&lt; EOF | oc apply -f -<br />
-–<br />
apiVersion: networking.istio.io/v1alpha3<br />
kind: VirtualService<br />
metadata:<br />
  name: reviews<br />
spec:<br />
  hosts:<br />
  - reviews<br />
  http:<br />
  - route:<br />
    - destination:<br />
        host: reviews<br />
        subset: v1<br />
      weight: 80<br />
    - destination:<br />
        host: reviews<br />
        subset: v2<br />
      weight: 20<br />
EOF</p>

<p>1.2.  Refresh your browser tab containing the Bookinfo URL a few times and you’ll see that occasionally you’ll see the v2 of the book review app which has star ratings.<br />
Accidentally close out of the tab? No problem, run the following command to get the product page URL:<br />
echo “http://$(oc -n istio-system get route istio-ingressgateway -o jsonpath=’{.spec.host}’)/productpage”</p>

<h2 id="2-observe-traffic-using-the-kiali-web-console">2. Observe traffic using the Kiali web console</h2>

<p>Kiali is an observability console for the OpenShift Service Mesh with service mesh configuration and validation capabilities. It helps you understand the structure and health of your service mesh by monitoring traffic flow to infer the topology and report errors.<br />
2.1.First, grab the Kiali web console URL. To do so, run the following command:<br />
echo “https://$(oc get routes -n istio-system kiali -o jsonpath=’{.spec.host}</p>

<p>2.2.Next, navigate to that URL in your web browser and click the Login With OpenShift button.</p>

<p>Once logged in, the Kiali Overview screen presents tiles for each project namespace.</p>

<p>2.3. Now, let’s generate some traffic against the product page service. To do so, run the following command in your terminal:<br />
while true; do curl -sSL “http://$(oc -n istio-system get route istio-ingressgateway -o jsonpath=’{.spec.host}’)/productpage” | head -n 5; sleep 1; done<br />
2.4. Leave the loop running and proceed to the next steps.<br />
   Return to the Kiali web console and click the <em>Graph</em> option in the sidebar.<br />
2.5. Next, select <em>bookinfo</em> from the Namespace list, and App graph from the Graph Type list.</p>

<p>2.6. Next, click on the <em>Display idle nodes</em> button.</p>

<p>2.7. Next, view the graph and change the display settings to add or remove information from the graph.</p>

<p>2.8. Next, click the <em>Workload</em> tab and select the <em>details-v1</em> workload.<br />
2.9. In your terminal window stop the traffic generation by pressing CTRL+c.</p>

<p>Conclusion  and next step<br />
Now you have completed all the modules for the ROSA hands-on experience. We hope you found it valuable, saw the value of ROSA as an application platform, and learned something new!<br />
If you have suggestions for how we could make this experience better, please <a href="https://console.redhat.com/openshift/overview/rosa/hands-on?intercom_survey_id=36682628">let us know</a>.<br />
Take the next step and <a href="https://console.redhat.com/openshift/create/rosa/getstarted?source=rhhe6">get started</a> with ROSA in your AWS account.<br />
Our onboarding specialists are here to help. If you have any questions or need help getting started with ROSA, send us a chat in the console at any time by clicking the blue hat icon in the bottom right corner.<br />
Additional resources to help you get started:</p>

<ul>
  <li>ROSA <a href="https://youtu.be/roiCLvcR8fE">install video</a></li>
  <li>ROSA <a href="https://www.redhat.com/en/technologies/cloud-computing/openshift/aws/learn">Learning Hub</a></li>
  <li>ROSA <a href="https://docs.aws.amazon.com/ROSA/latest/userguide/getting-started.html">user guide</a></li>
</ul>

<p>Thank you for taking the time to explore ROSA!</p>

<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[1.List all deployed ROSA clusters in the AWS account:]]></summary></entry><entry><title type="html">The B.A.R.N. Framework</title><link href="https://gbaniaki.github.io//article/2023/07/14/BARN.html" rel="alternate" type="text/html" title="The B.A.R.N. Framework" /><published>2023-07-14T21:13:27+00:00</published><updated>2023-07-14T21:13:27+00:00</updated><id>https://gbaniaki.github.io//article/2023/07/14/BARN</id><content type="html" xml:base="https://gbaniaki.github.io//article/2023/07/14/BARN.html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>Writing about your projects is crucial to giving context for the work. Writing an impactful article requires a structured approach that captures readers’ attention and delivers valuable insights. I use my BARN framework to achieve this goal: Background, Approach, Results, and Next Steps. In this article, we will delve into each element of the BARN framework and explore how it can enhance your writing skills.</p>

<h2 id="background">Background:</h2>
<p>The Background section of an article serves as the foundation, providing context and establishing the relevance of the topic. It sets the stage for readers to understand the problem or subject matter being addressed. To effectively craft this section, consider the following:</p>

<p><strong>1. Hook the readers:</strong> Begin with an engaging hook or anecdote that grabs readers’ attention and piques their curiosity.</p>

<p><strong>2. Problem statement:</strong> Clearly define the problem or questions that your project aims to address. Explain why it is significant and how it relates to the readers’ interests or concerns.</p>

<h2 id="approach">Approach:</h2>
<p>The Approach section outlines the methodology or approach used to investigate the problem or answer the problem statement. It is essential to provide readers with a clear understanding of how the research or analysis was conducted. Consider the following when constructing this section:</p>

<p><strong>1. Methodology:</strong> Describe the research design, data collection methods, and any tools or techniques employed. Ensure your explanation is concise yet comprehensive enough to allow readers to undestand your process.</p>

<p><strong>2. Data analysis:</strong> If applicable, detail the analysis techniques used to interpret the gathered data. This could include statistical methods, qualitative analysis, or any other relevant procedures.</p>

<p><strong>3. Assumptions and limitations:</strong> Acknowledge any assumptions made during the process and highlight the potential limitations. Call out any challenges you faced. This demonstrates transparency and helps readers evaluate the validity of the results.</p>

<h2 id="results">Results:</h2>
<p>The Results section presents the key findings and outcomes of your research or analysis. It is crucial to present this information in a clear and organized manner to facilitate readers’ understanding. Consider the following tips:</p>

<p><strong>1. Summarize findings:</strong> Provide a concise summary of the main findings, focusing on the most important and impactful results.</p>

<p><strong>2. Visual aids:</strong> Utilize charts, graphs, tables, or screenshots to present complex data in a visually appealing and accessible format. This enhances reader comprehension and engagement.</p>

<p><strong>3. Interpretation:</strong> Offer a thoughtful interpretation of the results, highlighting their significance in relation to the problem statement and the existing body of knowledge. Consider addressing unexpected or conflicting findings and proposing potential explanations.</p>

<h2 id="next-steps">Next Steps:</h2>
<p>The Next Steps section outlines potential future directions, implications, or recommendations based on the findings of your article. This section demonstrates your forward-thinking approach and encourages further exploration of the topic. Consider the following aspects:</p>

<p><strong>1. Implications:</strong> Discuss the broader implications of your findings and how they contribute to the field of study or the problem at hand. Consider societal, economic, or practical implications.</p>

<p><strong>2. Recommendations:</strong> Offer recommendations for further research or actions that can be taken based on your results. This could include areas that require additional investigation, potential applications, or suggested policy changes.</p>

<p><strong>3. Conclusion:</strong> Summarize the key points discussed in your article, emphasizing the value and impact of your project.</p>

<h2 id="conclusion">Conclusion</h2>
<p>Mastering the art of writing about your project requires a systematic and well-structured approach. The BARN framework, encompassing Background, Approach, Results, and Next Steps, provides a roadmap for creating engaging and informative articles. By leveraging this framework, you can effectively convey the context, methodology, findings, and future implications of your work, capturing readers’ attention and leaving a lasting impact in your field of expertise. So, pick up your pen or open your word processor, and let the BARN framework guide you on your journey to becoming a skilled and influential article writer.</p>]]></content><author><name>Leigh Stewardson</name></author><category term="article" /><category term="Writing" /><summary type="html"><![CDATA[This article explains the BARN method, a framework for showcasing your projects.]]></summary></entry><entry><title type="html">LinkedIn Learning Courses</title><link href="https://gbaniaki.github.io//work/2023/07/01/linkedin.html" rel="alternate" type="text/html" title="LinkedIn Learning Courses" /><published>2023-07-01T21:13:27+00:00</published><updated>2023-07-01T21:13:27+00:00</updated><id>https://gbaniaki.github.io//work/2023/07/01/linkedin</id><content type="html" xml:base="https://gbaniaki.github.io//work/2023/07/01/linkedin.html"><![CDATA[<h1 id="background">Background</h1>
<p>Since 2017, I have had the opportunity to build an tutorials for LinkedIn Learning. My projects aim to teach  concepts of JavaScript to beginner and intermediate developers, using narrative and project-based learning.</p>

<p>For each project, I developed (2-3 months) and the recorded the course (1 week).</p>

<h2 id="approach">Approach</h2>
<p>In all my courses, I strive to create a narrative that complements the learning objectives. By leveraging analogies, I am able to elucidate complex JavaScript concepts in a simplified and easily understandable format for learners.</p>

<h2 id="results">Results</h2>
<p>Upon publication, my courses have attracted many learners and have the following results:
<img src="/assets/images/LinkedIn_stats.png" alt="LinkedIn Stats" /></p>

<h2 id="next-steps">Next Steps</h2>]]></content><author><name>Leigh Stewardson</name></author><category term="work" /><category term="Tutorials" /><summary type="html"><![CDATA[This article showcases a tutorial that teaches learners how to code.]]></summary></entry><entry><title type="html">How to win at a hackathon</title><link href="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon.html" rel="alternate" type="text/html" title="How to win at a hackathon" /><published>2023-06-22T00:15:27+00:00</published><updated>2023-06-22T00:15:27+00:00</updated><id>https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon</id><content type="html" xml:base="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon.html"><![CDATA[<p>This article is written in three parts:</p>
<ul>
  <li><a href="/article/2023/06/22/how-to-win-at-a-hackathon1.html">Part 1: Investing in the “Dots”</a></li>
  <li><a href="/article/2023/06/22/how-to-win-at-a-hackathon-2.html">Part 2: Connecting the “Dots”</a></li>
  <li><a href="/article/2023/06/22/how-to-win-at-a-hackathon-3.html">Part 3: Casting the “Dots,” wide and far</a></li>
</ul>]]></content><author><name>Leigh Stewardson</name></author><category term="article" /><category term="Career" /><summary type="html"><![CDATA[This series of articles explores how to win at a hackathon even if you don't win the hackathon itself. The first post explores why you should invest in hackathons.]]></summary></entry><entry><title type="html">Part 1: How to win at a hackathon</title><link href="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon1.html" rel="alternate" type="text/html" title="Part 1: How to win at a hackathon" /><published>2023-06-22T00:15:27+00:00</published><updated>2023-06-22T00:15:27+00:00</updated><id>https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon1</id><content type="html" xml:base="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon1.html"><![CDATA[<blockquote>
  <p>Time  and pressure can change almost anything from what it was into what it has become. Time will change,  “Caterpillar into butterflies, sand into pearls,” and pressure will change “coal into diamonds,” both elements work on us too. 
— (paraphrased from Rick Warren)</p>
</blockquote>

<p>I recently participated in the <a href="https://www.a.team/">A.team</a>’s <a href="https://www.a.team/mission/ai-prototype-hackathon">Generative AI Hackathon</a> over the weekend. If you’re unfamiliar with hackathons, they bring together a passionate group of individuals, predominantly developers, who collaborate for a weekend to tackle challenges, present code demos and pitch decks of slides, and compete for prizes. Although hackathons require a lot of hard work, the sense of accomplishment on each team members’ face by the end of the competition, makes the sleepless nights worthwhile. More importantly, they are powerful, dense little dots waiting to be connected.</p>

<p>If you have ever connected numbered dots to complete a picture, it is plain to see that following the next dot builds upon the one before, thus revealing a recognizable object.</p>

<p>Dots to me, represent meaningful moments and/or experiences in life that help to reveal the next step and/or define my purpose. Hackathons, in particular, have been a reliable source of these “dots” in my life.  They often involve a combination of hard work, learning, camaraderie, and a sense of profound pride in my abilities and pride in my accomplishments.</p>

<p>I approach hackathons as “dot” moments.  I see these “dots” as powerful, dense moments  in time that have meaning and significance and upon further inspection, are just waiting to be connected.</p>

<p>There are three parts to this process of examination and they are:</p>
<ul>
  <li><a href="/article/2023/06/22/how-to-win-at-a-hackathon1.html">Part 1: Investing in the “Dots”</a></li>
  <li><a href="/article/2023/06/22/how-to-win-at-a-hackathon-2.html">Part 2: Connecting the “Dots”</a></li>
  <li><a href="/article/2023/06/22/how-to-win-at-a-hackathon-3.html">Part 3: Casting the “Dots,” wide and far</a></li>
</ul>

<h1 id="part-1-investing-in-the-dots">Part 1: Investing in the “Dots”</h1>
<p>Participating in hackathons is akin to the process of forming a pearl, or what I like to call a “dot.” While hackathons can be challenging and uncomfortable, they have the potential to yield something truly remarkable. By approaching a hackathon with a mindset geared towards learning, establishing connections with fellow competitors, and creating something truly noteworthy, you are guaranteed to emerge victorious every single time.
Amidst the process of developing my new course for LinkedIn Learning <a href="">insert link</a>, I made a spontaneous decision to participate in a hackathon. Despite the time constraints, I recognized the importance of this opportunity. Having just completed a course on Product Management for Machine Learning at UC Berkeley, I yearned to put my newly acquired skills into practice, even though my current role didn’t involve AI. Determined, I embraced the challenge with full dedication.</p>

<p>During the hackathon, I had the pleasure of meeting exceptional individuals, including Henry Duong and Armagan Amcalar, who were also finalists in the <a href="ttps://www.a.team/">A.Team</a>) Generative AI Hackathon. It became evident that we shared a common objective: to exercise our respective skill sets, be it new in my case or well-seasoned in Armagan and Henry’s.
Reflecting on the experience, Henry stated, “The work we accomplished provided valuable insights into enhancing existing enterprise data pipelines in both the pre-processing and post-processing stages. The knowledge gained from this endeavor can be applied across various industries, enabling me to deliver improved solutions to the companies I collaborate with.”</p>

<p>Armagan shared his sentiment about using a hackathon as a proving ground, saying, “Although I possess a master’s degree in machine learning from 15 years ago, I haven’t had many opportunities to apply it effectively. The resurgence of interest in AI, along with technological advancements, has made me feel right at home. DreamKiddo has been an idea I’ve long desired to develop. I toyed with it a decade ago, but the technology landscape was vastly different back then. I have a genuine passion for creating AI-powered experiences, and the genAI hackathon provided the perfect opportunity to revisit this concept.”</p>

<p>If you’re considering learning a new skill or technology, I highly recommend participating in hackathons as a means of practice. When I aimed to transition into a management role, hackathons served as a valuable platform to hone my team leadership abilities. Similarly, after completing a course in Product Management for Machine Learning, I put my skills to the test in a generative AI hackathon. Whether you’re seeking entry into a new industry or aiming to switch roles, hackathons offer a condensed microcosm in which you can explore and learn. Furthermore, they provide an excellent avenue for establishing connections and networking. To delve deeper into winning strategies at hackathons, be sure to read Part 2: How to win at a hackathon <a href="">insert link</a>.</p>

<h2 id="meet-new-people">Meet New People</h2>
<p>By meeting and staying in touch with other participants, opportunities to exchange knowledge, share resources, and learn from each other’s experiences, continues well after the hackathon is over. Engaging  in discussions, attending future workshops and/or conferences together, and participating in future hackathons together, as a team, will only increase the significance  of the moment or “Dot”.</p>

<p>These ongoing interactions provide a supportive environment for continuous learning, momentum  to improve technical skills, opportunities to expand knowledge, and the ability to explore new domains.</p>

<h2 id="build-your-portfolio">Build Your Portfolio</h2>
<p>Regardless, if I win or lose, I work very hard during a hackathon and  I show that off. 
Why not use hackathon work as a means to build my portfolio! Should I have a portfolio as a dev? Yes! Should I include it if it’s only a prototype? Yes! (Making sure to give appropriate credit to the appropriate source.) 
Is there a course on how to build a portfolio? Yes! Check out my new course here: [link to course] (See how I connected some dots there.)</p>

<p>Going back to what Henry said when I asked him why he liked hackathons, Henry said that he likes hackathons because, “Tight deadlines and a competitive atmosphere can foster creativity.” Hackathons also allow you  to focus purely on the technology aspects that can drive innovative functionality, with the added benefit of open experimentation. If I can deliver a polished product, even better.”</p>

<p>When I asked Armagan why he liked hackathons, he said, “The thrill of building something in a short, fixed timeframe. It’s all about pushing yourself to the limit, testing your limits, seeing what you can and can’t do. Seeing what other people come up with. I’m still suffering from imposter syndrome, so the validation feels great.”
I personally like hackathons because the time crunch forces me to boil a product down to its essence in order to beat the clock. There is little time to decide. I have to go with my gut and whatever tools I have in my toolbelt to get the job done.</p>

<h2 id="conclusion">Conclusion</h2>
<p>If building a portfolio is what you are interested in doing and it’s light on content, attend a hackathon. If you are trying something new, attend a hackathon. If you are looking for a job or need to network…you know the answer. In <a href="/article/2023/06/22/how-to-win-at-a-hackathon-2.html">Part 2</a> we’ll look at how to connect the dots.</p>

<h2 id="your-next-steps">Your Next Steps</h2>
<ul>
  <li>Find a hackathon that either works with your strengths or involves an area you want to improve.</li>
  <li>Talk to participants outside of your group and get their contact information.</li>
  <li>Use your hackathon pieces to build your portfolio.</li>
</ul>]]></content><author><name>Leigh Stewardson</name></author><category term="article" /><category term="Part" /><summary type="html"><![CDATA[This series of articles explores how to win at a hackathon even if you don't win the hackathon itself. The first post explores why you should invest in hackathons.]]></summary></entry><entry><title type="html">Part 2: How to win at a hackathon</title><link href="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon-2.html" rel="alternate" type="text/html" title="Part 2: How to win at a hackathon" /><published>2023-06-22T00:14:27+00:00</published><updated>2023-06-22T00:14:27+00:00</updated><id>https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon%202</id><content type="html" xml:base="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon-2.html"><![CDATA[<blockquote>
  <p>“You can’t connect the dots looking forward; you can only connect them looking backwards. So you have to trust that the dots will somehow connect in your future. You have to trust in something—your gut, destiny, life, karma, whatever. This approach has never let me down, and it has made all the difference in my life.”
—Steve Jobs, 
Aug 10, 2018</p>
</blockquote>

<p>In <a href="/article/2023/06/22/how-to-win-at-a-hackathon1.html">Part 1</a> of How to win at a hackathon, we looked at what to do in a hackathon. In this article, we’ll look at setting your dots up for the future.</p>

<h1 id="part-2-connecting-the-dots">Part 2: Connecting the “Dots”</h1>
<p>Dots need people. They are seeds waiting to grow (I know I said they were pearls, but imagine what would grow if a pearl were a seed!). People are the fertilizer and water that help a dot strengthen, bloom and connect to other dots.</p>

<h2 id="network">Network</h2>
<p>There are a ton of amazing people at hackathons. At the beginning of the hackathon that I recently attended, we, the participants, did a few breakout sessions to meet people on other teams. As I worked on my individual projects there is next to no time to talk to other teams. Additionally, as these teams are the competition, there is some natural (hopefully, light-hearted) animosity between teams.</p>

<p>Don’t fall into this. I realized by competing in a hackathon, I was in a unique environment with kindred spirits. Why miss out on the opportunity to connect. Making connections is crucial for the next step in <a href="/article/2023/06/22/how-to-win-at-a-hackathon-3.html">Part 3</a>. The more people that I connect with, the farther my dots go, meaning more opportunities for me in the future. (Trust Steve Jobs on this.)</p>

<h2 id="connect-matching-dots">Connect matching dots</h2>
<p>I met Henry Duong, a medical professional turned serial founder and CTO, during the round robin ice breaker. It occurred to me that I knew another medical professional turned tech, Bryan Gersham, MD. I had been mentoring Bryan on how to get his idea funded using the SBIR.gov program. When this happens, take a note or jump on  <a href="https://www.linkedin.com/">LinkedIn</a> and connect the dots. Do I get anything out of it? Good karma maybe, but my goal is to connect like-minded people. Who knows what will come of it?</p>

<h2 id="dont-be-afraid-to-reach-out">Don’t be afraid to reach out</h2>
<p>How do I know Bryan?</p>

<p>He reached out to me after watching one of my LinkedIn Learning videos. Not enough people do this. I never know who will respond. Some people won’t. Some people will.</p>

<p>During the hackathon I reached out to motor.com, based on a recommendation from my mentor, Rusty Patel. Motor.com had the type of data we needed to integrate into our product. As the Product Manager and team lead, I jumped right in and sent an inquiry to motor.com and as it turns out, they had an API Sandbox ready to go! Their brilliant sales rep, Jennie Davis helped my team quickly get access to this information. A hackathon is a great way to make business connections.</p>

<p>The second connection I made was with Armagan Amcalar, founder of coyotiv.com and fractional CTO. Armagan and his team built a story telling app for kids in hospital. Armagan said about the hackathon “I felt like it would allow me to get deeper into the <a href="ttps://www.a.team/">A.Team </a> (a freelance site) community. And any interesting conversations or connections I could get would be an icing on the cake.”</p>

<p>I knew immediately that I had to connect with him. I had another project (a dot) Alika’s Treehouse for which I won a hackathon in 2016 that was similar, as well as a Generative AI project for people with reading difficulty, that I wanted his feedback on.</p>

<p>Now, I could have thought “that guy has the same ideas, I need to beat him to the punch!” but rather than looking at him as a competitor, I got on a call with him and found we had similar ambitions and ideas. In the foreseeable future, Armagan and I will be working on an SBIR grant, potentially teaming up to continue my hackathon project, and possibly working to expand his business to the US (he is in Berlin). Additionally, I am connecting Armagan up with my content producer at LinkedIn Learning, as he happened to have a workshop ready to go that would make a great tutorial. See? Many dots connected by people.</p>

<p>At a hackathon, remember that ultimately, people who are there are like-minded people. Take time to step away from the competition and look around. Try and observe the dots waiting to be connected with.</p>

<h2 id="conclusion">Conclusion</h2>
<p>While the intensity and excitement of a hackathon may subside once the event concludes, the connections formed during this time hold immense potential. By nurturing these relationships, you can amplify collaboration, unlock professional opportunities, foster personal growth, and actively engage in the tech community. The connections made during and after a hackathon have the power to shape careers, fuel innovation, and forge lifelong friendships. So, embrace the discomfort as an opportunity to connect, learn, and create a network that will support future endeavors.</p>

<h2 id="your-next-steps">Your Next Steps</h2>
<ul>
  <li>Connect with your competition. You are like-minded.</li>
  <li>Connect with the leadership of the competition. What can you thank them for? What feedback can you add for the next hackathon?</li>
  <li>Connect those you meet with your broader network.</li>
</ul>]]></content><author><name>Leigh Stewardson</name></author><category term="article" /><category term="hackathon" /><summary type="html"><![CDATA[This series of articles explores how to win at a hackathon even if you don't win the hackathon itself. The second post explores how to make connections at a hackathon.]]></summary></entry><entry><title type="html">Part 3: How to win at a hackathon</title><link href="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon-3.html" rel="alternate" type="text/html" title="Part 3: How to win at a hackathon" /><published>2023-06-22T00:13:27+00:00</published><updated>2023-06-22T00:13:27+00:00</updated><id>https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon%203</id><content type="html" xml:base="https://gbaniaki.github.io//article/2023/06/22/how-to-win-at-a-hackathon-3.html"><![CDATA[<blockquote>
  <p>“No struggle, no success! The strongest thunder strikes often bring the heaviest rainfall! The weight of your fulfillment depends on how wide you cast your nets! If you are trying to look clean, neat and avoid casting your nets in troubled waters, you will catch no fish.” 
― Israelmore Ayivor, Daily Drive 365</p>
</blockquote>

<p>In <a href="/article/2023/06/22/how-to-win-at-a-hackathon-2.html">Part 2</a> of How to win at a hackathon, we looked at why it’s important to connect the dots through networking. In this article, we’ll look at what steps you can take after the weeknd is over.</p>

<h1 id="part-3-casting-the-dots-wide-and-far">Part 3: Casting the “Dots” wide and far</h1>
<p>So what am I doing now that the hackathon is over?</p>

<p>Well first I slept, but then it was time to get to work. Preparing an article, creating videos I could use socially and with investors and users, getting on the phone to get additional feedback, applying to incubators for startups and pitch competitions. Why? It’s easier than winning the lottery.</p>

<p>Armanga says he wants to “Take it to the next level. After we published our work on social media, a lot of my friends wanted access to a beta to try it out with their kids. I conferred with a couple of investor friends, they were very interested in the idea. So I think there’s a lot of potential here, for me, for the team, for the children of the world. We are now conferring within our team about how we would continue.”</p>

<p>Henry agrees saying, “I’ve met many talented individuals through the hackathon and I plan to continue working with these individuals in the future.”</p>

<p>One thing I‘ve done  was write an article about the hackathon. I wrote the article because:</p>
<ul>
  <li>I had a great time and want more people to try hackathons,</li>
  <li>It had been awhile since I’d written or posted socially,</li>
  <li>And, remember that course I was writing, it just so happened that I needed an article for it and this was perfect</li>
</ul>

<p>An article is a great way to connect and cast dots.</p>

<h2 id="conclusion">Conclusion</h2>
<p>Sharing my work from a hackathon on social media allows me to extend the impact of my  project beyond the event itself. By defining my story, capturing engaging visuals, crafting compelling captions, utilizing hashtags, engaging with the community, and seeking collaborative opportunities, I can effectively promote my hackathon work to a wider audience. So can you.</p>

<p>Embrace the power of social media as a tool to inspire, connect, and showcase your achievements, and watch as your hackathon endeavors become dots.</p>

<h2 id="your-next-steps">Your Next Steps</h2>
<ul>
  <li>Create a shareable article about your experience and publish it in as many places as you can.</li>
  <li>Reach out to businesses and influencers about your work</li>
  <li>Apply to incubators and additional pitch competitions</li>
  <li>Spend some time polishing it up and write an article, using the BARN framework. Learn more about that here <a href="/article/2023/07/14/BARN.html">BARN</a></li>
</ul>

<p>Ask your connections to share your article</p>]]></content><author><name>Leigh Stewardson</name></author><category term="article" /><category term="Part" /><summary type="html"><![CDATA[This series of articles explores how to win at a hackathon even if you don't win the hackathon itself. The third post explores how to build on your momentum and push your hackathon ideas out into the world.]]></summary></entry><entry><title type="html">Accelerating your Career</title><link href="https://gbaniaki.github.io//article/2023/06/22/professional-services.html" rel="alternate" type="text/html" title="Accelerating your Career" /><published>2023-06-22T00:13:27+00:00</published><updated>2023-06-22T00:13:27+00:00</updated><id>https://gbaniaki.github.io//article/2023/06/22/professional-services</id><content type="html" xml:base="https://gbaniaki.github.io//article/2023/06/22/professional-services.html"><![CDATA[<p>Looking back on my career, there are a few things I wish I had done earlier to boost my career progression and enhance my marketability. In this article, I will share my experience and highlight four professional services that have significantly accelerated my career and improved my standing in the job market.</p>

<h2 id="1-get-a-mentor-andor-start-mentoring">1. Get a Mentor and/or Start Mentoring</h2>
<p>I’ve been mentoring and have been a mentee for years and I have learned so much from the experience. Securing a mentor and becoming a mentor yourself are invaluable steps towards professional growth.  These two practices are not mutually exclusive but complement each other. A mentor offers guidance, wisdom, and support, helping you navigate challenges and make informed decisions. Simultaneously, mentoring others allows you to share your knowledge, expand your leadership skills, and develop a sense of fulfillment. The mentor-mentee relationship fosters personal and professional development, building a strong foundation for success.</p>

<h1 id="2-get-your-resume-professionally-written">2. Get Your Resume Professionally Written</h1>
<p>For a long time, I believed I could adequately write my own resume. However, I soon realized the significance of professional resume writing services, especially when dealing with complex career trajectories or employment gaps. Companies like <a href="http://topresume.com">TopResume.com</a> offer expert assistance in transforming your experiences into a cohesive, compelling narrative. Their resume writers possess the expertise to structure your diverse background effectively. They can highlight relevant skills, consolidate related experiences, and maximize the impact of your achievements. A professionally written resume enhances your chances of making a positive impression and securing desired opportunities and is well worth the investment.</p>

<h1 id="3-create-a-portfolio">3. Create a Portfolio</h1>
<p>Portfolios are not exclusive to designers; they are relevant for professionals across various industries, including developers. As I transitioned into a developer role, I recognized the importance of showcasing my work through a portfolio. Whether you’re a designer, developer, writer, or any other professional, having a portfolio provides tangible evidence of your skills and accomplishments. It offers potential employers a comprehensive view of your capabilities and serves as a testament to your expertise. Check out my video one LinkedIn Learning: <a href="">GitHub Portfolios for Developers</a>, to learn how to build an impressive portfolio that highlights your best work effectively.</p>

<h1 id="4-get-a-career-coach">4. Get a Career Coach</h1>
<p>I waited on this one for a while, but engaging the services of a career coach can be a game-changer in propelling your career forward. I recently enlisted the expertise of <a href="http://www.vfcoaching.com">Virtual Freedom Coaching</a>, led by <a href="https://www.linkedin.com/in/vfcoaching/">Dr. Priya Bains</a>, and it has been a transformative experience. A career coach helps you gain clarity, identify patterns, and unlock your potential. They offer personalized guidance, support, and strategies tailored to your unique circumstances. Whether you’re an innovator entrepreneur or a creative professional, a career coach can help you navigate challenges, optimize your strengths, and make meaningful progress towards your goals.</p>

<h2 id="three-reasons-why-you-should-look-for-a-career-coach">Three Reasons Why You Should Look for a Career Coach:</h2>
<p>I recommend thoroughly vetting a career coach to make sure they are the right fit for your style. It took me some time to find Priya, who specifically works with creatives and innovative entrepreneurs. Priya is helping me:</p>

<ul>
  <li>Find focus and remove my entrepreneurial ADHD.</li>
  <li>Get out of overwhelm and overwork and transform productive work and long hours into efficient work.</li>
  <li>Organize my ideas and communicate with clarity to impact stakeholders.</li>
  <li>Transform problems into innovative solutions.</li>
</ul>

<p>In general, career coaches can help you:</p>

<p><strong>1. Gain Insight and Perspective:</strong> A career coach provides an objective viewpoint, helping you identify blind spots, uncover untapped potential, and explore new possibilities. They bring a fresh perspective and offer insights that can propel your career to new heights.</p>

<p><strong>2. Enhance Efficiency and Effectiveness:</strong> A career coach helps you streamline your approach, refine your strategies, and optimize your workflows. They assist in identifying areas of improvement, developing new skills, and implementing systems that make you more efficient and effective in your professional endeavors.</p>

<p><strong>3. Overcome Challenges and Setbacks:</strong> Career coaches provide invaluable support during challenging times. They offer guidance, motivation, and resilience-building techniques to help you navigate setbacks, overcome obstacles, and stay focused on your long-term goals.</p>

<h1 id="conclusion">Conclusion</h1>
<p>Looking back on our careers, it’s natural to reflect on the things we wish we had done earlier. The professional services I have mentioned - getting a mentor, having a professionally written resume, creating a portfolio, and engaging a career coach - have undoubtedly accelerated my career trajectory and increased my marketability. Consider incorporating these services into your professional journey and unlock new opportunities and possibilities in your chosen field. Remember, investing in your career development is an investment in your own success.</p>]]></content><author><name>Leigh Stewardson</name></author><category term="article" /><category term="leadership" /><summary type="html"><![CDATA[Looking back on my career, there are a few things I wish I had done earlier to boost my career progression and enhance my marketability. In this article, I will share my experience and highlight four professional services that have significantly accelerated my career and improved my standing in the job market.]]></summary></entry></feed>