{"id":50076,"date":"2026-06-23T06:48:21","date_gmt":"2026-06-23T06:48:21","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=50076"},"modified":"2026-06-23T06:48:23","modified_gmt":"2026-06-23T06:48:23","slug":"openshift-lab-9-work-with-databases-in-the-openshift-web-console","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/openshift-lab-9-work-with-databases-in-the-openshift-web-console\/","title":{"rendered":"OpenShift Lab 9: Work with Databases in the OpenShift Web Console"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Lab Goal<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this lab, you will deploy a PostgreSQL database on OpenShift Local using the OpenShift web console. You will create the database using modern OpenShift resources such as Deployment, Service, Secret, ConfigMap, and PersistentVolumeClaim.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This lab replaces the older MongoDB web-console lab that used an outdated MongoDB image, an ephemeral database template, hard-coded credentials, and DeploymentConfig. The new lab uses current OpenShift-friendly practices.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By the end of this lab, you will understand how an application or client pod connects to a database inside OpenShift using internal service discovery.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">What You Will Learn<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You will learn how to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Start OpenShift Local.<\/li>\n\n\n\n<li>Log in to the OpenShift web console.<\/li>\n\n\n\n<li>Create a new project.<\/li>\n\n\n\n<li>Create a PostgreSQL database using the web console.<\/li>\n\n\n\n<li>Store database credentials in a Secret.<\/li>\n\n\n\n<li>Store non-sensitive database configuration in a ConfigMap.<\/li>\n\n\n\n<li>Create persistent storage using a PersistentVolumeClaim.<\/li>\n\n\n\n<li>Expose the database internally using a Service.<\/li>\n\n\n\n<li>Deploy a database client pod.<\/li>\n\n\n\n<li>Connect to PostgreSQL from inside the OpenShift cluster.<\/li>\n\n\n\n<li>Create a table and insert test data.<\/li>\n\n\n\n<li>Verify that data survives a database pod restart.<\/li>\n\n\n\n<li>Validate everything using optional <code>oc<\/code> commands.<\/li>\n\n\n\n<li>Clean up the lab environment.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Lab Architecture<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this lab, you will create the following OpenShift resources:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Resource<\/th><th>Name<\/th><th>Purpose<\/th><\/tr><\/thead><tbody><tr><td>Project<\/td><td><code>lab9-db-web-console<\/code><\/td><td>Isolated namespace for this lab<\/td><\/tr><tr><td>Secret<\/td><td><code>postgresql-secret<\/code><\/td><td>Stores database username, password, and database name<\/td><\/tr><tr><td>ConfigMap<\/td><td><code>postgresql-config<\/code><\/td><td>Stores non-sensitive PostgreSQL settings<\/td><\/tr><tr><td>PersistentVolumeClaim<\/td><td><code>postgresql-data<\/code><\/td><td>Provides persistent database storage<\/td><\/tr><tr><td>Deployment<\/td><td><code>postgresql<\/code><\/td><td>Runs the PostgreSQL database pod<\/td><\/tr><tr><td>Service<\/td><td><code>postgresql<\/code><\/td><td>Provides stable internal DNS name for the database<\/td><\/tr><tr><td>Deployment<\/td><td><code>db-client<\/code><\/td><td>Runs a client pod used to test database connectivity<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Why This Lab Uses PostgreSQL Instead of the Old MongoDB Template<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The older lab used an old MongoDB 3.6 template and an ephemeral database. That approach is not ideal for a current OpenShift student lab.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This replacement lab uses PostgreSQL because:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>PostgreSQL is commonly used in enterprise application environments.<\/li>\n\n\n\n<li>The database runs as a standard Kubernetes Deployment.<\/li>\n\n\n\n<li>Credentials are stored in a Secret.<\/li>\n\n\n\n<li>Non-sensitive settings are stored in a ConfigMap.<\/li>\n\n\n\n<li>Data is stored on a PersistentVolumeClaim.<\/li>\n\n\n\n<li>Students can clearly understand how applications connect to databases through internal Services.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Important Concept<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A database should usually not be exposed publicly through an OpenShift Route.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In OpenShift:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Resource<\/th><th>Used For<\/th><\/tr><\/thead><tbody><tr><td>Service<\/td><td>Internal communication inside the cluster<\/td><\/tr><tr><td>Route<\/td><td>External HTTP\/HTTPS access to web applications<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In this lab, PostgreSQL will only be available inside the OpenShift cluster through the internal service name:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The database will not be exposed using a Route.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 1: Prerequisites<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Required Tools<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You need the following tools installed on your machine:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>OpenShift Local<\/li>\n\n\n\n<li><code>crc<\/code> command<\/li>\n\n\n\n<li><code>oc<\/code> command<\/li>\n\n\n\n<li>A browser<\/li>\n\n\n\n<li>At least 4 CPUs and enough memory available for OpenShift Local<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Recommended OpenShift Local Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OpenShift Local with the OpenShift preset requires a local single-node OpenShift cluster. For smooth lab work, use at least:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Resource<\/th><th>Recommended<\/th><\/tr><\/thead><tbody><tr><td>CPU<\/td><td>4 or more<\/td><\/tr><tr><td>Memory<\/td><td>12 GB or more<\/td><\/tr><tr><td>Disk<\/td><td>35 GB or more<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 2: Start OpenShift Local<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Open a terminal on your machine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check your OpenShift Local version:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">crc version\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Set the OpenShift preset:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">crc config <span class=\"hljs-keyword\">set<\/span> preset openshift\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Run the setup command:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">crc setup\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Start OpenShift Local:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">crc start\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The start command may take several minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When the cluster starts successfully, OpenShift Local prints login information for the web console and command line.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To view the credentials again, run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">crc <span class=\"hljs-built_in\">console<\/span> --credentials\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">To open the web console, run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">crc <span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 3: Configure the <code>oc<\/code> CLI<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">OpenShift Local provides the <code>oc<\/code> CLI environment command.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">crc oc-env\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">On Linux or macOS, apply the environment using:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">eval<\/span> $(crc oc-env)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Now log in as the developer user.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use the password shown by:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">crc <span class=\"hljs-built_in\">console<\/span> --credentials\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Login command:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc login -u developer https:<span class=\"hljs-comment\">\/\/api.crc.testing:6443<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify login:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc whoami\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">developer\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check the cluster:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> nodes\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected result:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">NAME                 STATUS   ROLES                         AGE   VERSION\ncrc-xxxxx-master-0   Ready    control-plane,master,worker    ...\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The exact node name and version may be different.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 4: Create a New Project from the Web Console<\/h1>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the OpenShift web console.<\/li>\n\n\n\n<li>Log in as:<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">Username: developer\n<span class=\"hljs-attr\">Password<\/span>: Use the password <span class=\"hljs-keyword\">from<\/span> crc <span class=\"hljs-built_in\">console<\/span> --credentials\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>Switch to the <strong>Developer<\/strong> perspective.<\/li>\n\n\n\n<li>Click <strong>Project<\/strong> dropdown.<\/li>\n\n\n\n<li>Click <strong>Create Project<\/strong>.<\/li>\n\n\n\n<li>Enter the following project name:<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"7\" class=\"wp-block-list\">\n<li>Click <strong>Create<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">You now have a separate OpenShift project for this lab.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 5: Create Database Resources Using Import YAML<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">In the OpenShift web console:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Make sure you are in the project:<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>Go to <strong>+Add<\/strong>.<\/li>\n\n\n\n<li>Choose <strong>Import YAML<\/strong>.<\/li>\n\n\n\n<li>Paste the full YAML below.<\/li>\n\n\n\n<li>Click <strong>Create<\/strong>.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">YAML: PostgreSQL Database, Secret, ConfigMap, PVC, Service, and Client Pod<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">apiVersion: v1\n<span class=\"hljs-attr\">kind<\/span>: Secret\n<span class=\"hljs-attr\">metadata<\/span>:\n  name: postgresql-secret\n  <span class=\"hljs-attr\">labels<\/span>:\n    app.kubernetes.io\/name: postgresql\n    app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n<span class=\"hljs-attr\">type<\/span>: Opaque\n<span class=\"hljs-attr\">stringData<\/span>:\n  POSTGRESQL_USER: appuser\n  <span class=\"hljs-attr\">POSTGRESQL_PASSWORD<\/span>: ChangeMeLab9!\n  POSTGRESQL_DATABASE: appdb\n---\napiVersion: v1\n<span class=\"hljs-attr\">kind<\/span>: ConfigMap\n<span class=\"hljs-attr\">metadata<\/span>:\n  name: postgresql-config\n  <span class=\"hljs-attr\">labels<\/span>:\n    app.kubernetes.io\/name: postgresql\n    app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n<span class=\"hljs-attr\">data<\/span>:\n  POSTGRESQL_MAX_CONNECTIONS: <span class=\"hljs-string\">\"50\"<\/span>\n  <span class=\"hljs-attr\">POSTGRESQL_SHARED_BUFFERS<\/span>: <span class=\"hljs-string\">\"64MB\"<\/span>\n---\napiVersion: v1\n<span class=\"hljs-attr\">kind<\/span>: PersistentVolumeClaim\n<span class=\"hljs-attr\">metadata<\/span>:\n  name: postgresql-data\n  <span class=\"hljs-attr\">labels<\/span>:\n    app.kubernetes.io\/name: postgresql\n    app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n<span class=\"hljs-attr\">spec<\/span>:\n  accessModes:\n    - ReadWriteOnce\n  <span class=\"hljs-attr\">resources<\/span>:\n    requests:\n      storage: <span class=\"hljs-number\">1<\/span>Gi\n---\napiVersion: apps\/v1\n<span class=\"hljs-attr\">kind<\/span>: Deployment\n<span class=\"hljs-attr\">metadata<\/span>:\n  name: postgresql\n  <span class=\"hljs-attr\">labels<\/span>:\n    app: postgresql\n    app.kubernetes.io\/name: postgresql\n    app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n<span class=\"hljs-attr\">spec<\/span>:\n  replicas: <span class=\"hljs-number\">1<\/span>\n  <span class=\"hljs-attr\">selector<\/span>:\n    matchLabels:\n      app: postgresql\n  <span class=\"hljs-attr\">strategy<\/span>:\n    type: Recreate\n  <span class=\"hljs-attr\">template<\/span>:\n    metadata:\n      labels:\n        app: postgresql\n        app.kubernetes.io\/name: postgresql\n        app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n    <span class=\"hljs-attr\">spec<\/span>:\n      terminationGracePeriodSeconds: <span class=\"hljs-number\">30<\/span>\n      <span class=\"hljs-attr\">containers<\/span>:\n        - name: postgresql\n          <span class=\"hljs-attr\">image<\/span>: registry.redhat.io\/rhel9\/postgresql<span class=\"hljs-number\">-15<\/span>:latest\n          <span class=\"hljs-attr\">imagePullPolicy<\/span>: IfNotPresent\n          <span class=\"hljs-attr\">ports<\/span>:\n            - name: postgresql\n              <span class=\"hljs-attr\">containerPort<\/span>: <span class=\"hljs-number\">5432<\/span>\n              <span class=\"hljs-attr\">protocol<\/span>: TCP\n          <span class=\"hljs-attr\">env<\/span>:\n            - name: POSTGRESQL_USER\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                secretKeyRef:\n                  name: postgresql-secret\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_USER\n            - name: POSTGRESQL_PASSWORD\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                secretKeyRef:\n                  name: postgresql-secret\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_PASSWORD\n            - name: POSTGRESQL_DATABASE\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                secretKeyRef:\n                  name: postgresql-secret\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_DATABASE\n            - name: POSTGRESQL_MAX_CONNECTIONS\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                configMapKeyRef:\n                  name: postgresql-config\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_MAX_CONNECTIONS\n            - name: POSTGRESQL_SHARED_BUFFERS\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                configMapKeyRef:\n                  name: postgresql-config\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_SHARED_BUFFERS\n            - name: POSTGRESQL_LOG_DESTINATION\n              <span class=\"hljs-attr\">value<\/span>: <span class=\"hljs-regexp\">\/dev\/<\/span>stderr\n          <span class=\"hljs-attr\">resources<\/span>:\n            requests:\n              cpu: <span class=\"hljs-number\">100<\/span>m\n              <span class=\"hljs-attr\">memory<\/span>: <span class=\"hljs-number\">256<\/span>Mi\n            <span class=\"hljs-attr\">limits<\/span>:\n              cpu: <span class=\"hljs-number\">500<\/span>m\n              <span class=\"hljs-attr\">memory<\/span>: <span class=\"hljs-number\">768<\/span>Mi\n          <span class=\"hljs-attr\">readinessProbe<\/span>:\n            tcpSocket:\n              port: <span class=\"hljs-number\">5432<\/span>\n            <span class=\"hljs-attr\">initialDelaySeconds<\/span>: <span class=\"hljs-number\">10<\/span>\n            <span class=\"hljs-attr\">periodSeconds<\/span>: <span class=\"hljs-number\">10<\/span>\n            <span class=\"hljs-attr\">timeoutSeconds<\/span>: <span class=\"hljs-number\">2<\/span>\n          <span class=\"hljs-attr\">livenessProbe<\/span>:\n            tcpSocket:\n              port: <span class=\"hljs-number\">5432<\/span>\n            <span class=\"hljs-attr\">initialDelaySeconds<\/span>: <span class=\"hljs-number\">30<\/span>\n            <span class=\"hljs-attr\">periodSeconds<\/span>: <span class=\"hljs-number\">20<\/span>\n            <span class=\"hljs-attr\">timeoutSeconds<\/span>: <span class=\"hljs-number\">2<\/span>\n          <span class=\"hljs-attr\">securityContext<\/span>:\n            allowPrivilegeEscalation: <span class=\"hljs-literal\">false<\/span>\n            <span class=\"hljs-attr\">capabilities<\/span>:\n              drop:\n                - ALL\n          <span class=\"hljs-attr\">volumeMounts<\/span>:\n            - name: postgresql-data\n              <span class=\"hljs-attr\">mountPath<\/span>: <span class=\"hljs-regexp\">\/var\/<\/span>lib\/pgsql\/data\n      <span class=\"hljs-attr\">volumes<\/span>:\n        - name: postgresql-data\n          <span class=\"hljs-attr\">persistentVolumeClaim<\/span>:\n            claimName: postgresql-data\n---\napiVersion: v1\n<span class=\"hljs-attr\">kind<\/span>: Service\n<span class=\"hljs-attr\">metadata<\/span>:\n  name: postgresql\n  <span class=\"hljs-attr\">labels<\/span>:\n    app: postgresql\n    app.kubernetes.io\/name: postgresql\n    app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n<span class=\"hljs-attr\">spec<\/span>:\n  type: ClusterIP\n  <span class=\"hljs-attr\">selector<\/span>:\n    app: postgresql\n  <span class=\"hljs-attr\">ports<\/span>:\n    - name: postgresql\n      <span class=\"hljs-attr\">protocol<\/span>: TCP\n      <span class=\"hljs-attr\">port<\/span>: <span class=\"hljs-number\">5432<\/span>\n      <span class=\"hljs-attr\">targetPort<\/span>: <span class=\"hljs-number\">5432<\/span>\n---\napiVersion: apps\/v1\n<span class=\"hljs-attr\">kind<\/span>: Deployment\n<span class=\"hljs-attr\">metadata<\/span>:\n  name: db-client\n  <span class=\"hljs-attr\">labels<\/span>:\n    app: db-client\n    app.kubernetes.io\/name: db-client\n    app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n<span class=\"hljs-attr\">spec<\/span>:\n  replicas: <span class=\"hljs-number\">1<\/span>\n  <span class=\"hljs-attr\">selector<\/span>:\n    matchLabels:\n      app: db-client\n  <span class=\"hljs-attr\">template<\/span>:\n    metadata:\n      labels:\n        app: db-client\n        app.kubernetes.io\/name: db-client\n        app.kubernetes.io\/part-<span class=\"hljs-keyword\">of<\/span>: lab9-database-demo\n    <span class=\"hljs-attr\">spec<\/span>:\n      containers:\n        - name: db-client\n          <span class=\"hljs-attr\">image<\/span>: registry.redhat.io\/rhel9\/postgresql<span class=\"hljs-number\">-15<\/span>:latest\n          <span class=\"hljs-attr\">imagePullPolicy<\/span>: IfNotPresent\n          <span class=\"hljs-attr\">command<\/span>:\n            - <span class=\"hljs-regexp\">\/bin\/<\/span>bash\n            - -c\n          <span class=\"hljs-attr\">args<\/span>:\n            - echo <span class=\"hljs-string\">\"db-client is ready\"<\/span>; <span class=\"hljs-keyword\">while<\/span> <span class=\"hljs-literal\">true<\/span>; <span class=\"hljs-keyword\">do<\/span> sleep <span class=\"hljs-number\">3600<\/span>; done\n          <span class=\"hljs-attr\">env<\/span>:\n            - name: PGHOST\n              <span class=\"hljs-attr\">value<\/span>: postgresql\n            - name: PGPORT\n              <span class=\"hljs-attr\">value<\/span>: <span class=\"hljs-string\">\"5432\"<\/span>\n            - name: PGDATABASE\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                secretKeyRef:\n                  name: postgresql-secret\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_DATABASE\n            - name: PGUSER\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                secretKeyRef:\n                  name: postgresql-secret\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_USER\n            - name: PGPASSWORD\n              <span class=\"hljs-attr\">valueFrom<\/span>:\n                secretKeyRef:\n                  name: postgresql-secret\n                  <span class=\"hljs-attr\">key<\/span>: POSTGRESQL_PASSWORD\n          <span class=\"hljs-attr\">resources<\/span>:\n            requests:\n              cpu: <span class=\"hljs-number\">50<\/span>m\n              <span class=\"hljs-attr\">memory<\/span>: <span class=\"hljs-number\">128<\/span>Mi\n            <span class=\"hljs-attr\">limits<\/span>:\n              cpu: <span class=\"hljs-number\">250<\/span>m\n              <span class=\"hljs-attr\">memory<\/span>: <span class=\"hljs-number\">256<\/span>Mi\n          <span class=\"hljs-attr\">securityContext<\/span>:\n            allowPrivilegeEscalation: <span class=\"hljs-literal\">false<\/span>\n            <span class=\"hljs-attr\">capabilities<\/span>:\n              drop:\n                - ALL\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 6: Understand the YAML<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">1. Secret<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">kind: Secret\nmetadata:\n  name: postgresql-secret\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The Secret stores sensitive database values:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">POSTGRESQL_USER\nPOSTGRESQL_PASSWORD\nPOSTGRESQL_DATABASE\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The PostgreSQL pod uses these values when the database is initialized.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The client pod also uses these values to connect to the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In real projects, never hard-code production passwords in YAML files committed to Git.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For production, use a secret management approach such as:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>External Secrets Operator<\/li>\n\n\n\n<li>HashiCorp Vault<\/li>\n\n\n\n<li>AWS Secrets Manager<\/li>\n\n\n\n<li>Azure Key Vault<\/li>\n\n\n\n<li>Google Secret Manager<\/li>\n\n\n\n<li>Sealed Secrets<\/li>\n\n\n\n<li>GitOps secret encryption tools<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">For this beginner lab, the password is visible so students can understand the workflow.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2. ConfigMap<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">kind: ConfigMap\nmetadata:\n  name: postgresql-config\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The ConfigMap stores non-sensitive settings:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">POSTGRESQL_MAX_CONNECTIONS\nPOSTGRESQL_SHARED_BUFFERS\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Use ConfigMaps for application configuration that is not secret.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Examples:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">APP_MODE=dev\nLOG_LEVEL=debug\nDATABASE_HOST=postgresql\nDATABASE_PORT=5432\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Do not store passwords, tokens, or private keys in ConfigMaps.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. PersistentVolumeClaim<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">kind: PersistentVolumeClaim\nmetadata:\n  name: postgresql-data\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The PersistentVolumeClaim requests storage for the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The PostgreSQL database writes its data to:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">\/<span class=\"hljs-keyword\">var<\/span>\/lib\/pgsql\/data\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">That directory is backed by the PVC.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This means the data can survive a pod restart or pod recreation.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4. PostgreSQL Deployment<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">kind: Deployment\nmetadata:\n  name: postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The Deployment creates and manages the PostgreSQL pod.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The lab uses:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">strategy:\n  type: Recreate\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is useful for a single-instance database because the old pod is stopped before a new pod is started.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5. PostgreSQL Service<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">kind: Service\nmetadata:\n  name: postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The Service provides a stable internal name for the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Other pods in the same project can connect to PostgreSQL using:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">postgresql<\/span><span class=\"hljs-selector-pseudo\">:5432<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The client pod uses:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PGHOST=postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is OpenShift\/Kubernetes service discovery.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6. DB Client Deployment<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">kind: Deployment\nmetadata:\n  name: db-client\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The db-client pod is a test pod. It is not the database. It is used to test database connectivity from inside the cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The client pod has PostgreSQL client tools available, including:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">psql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You will use this pod to connect to the PostgreSQL Service.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 7: Verify Resources in the Web Console<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">After clicking <strong>Create<\/strong>, go to:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Developer perspective &gt; Topology\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You should see two workloads:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">postgresql\ndb-client\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Click the <code>postgresql<\/code> workload.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Pod status<\/li>\n\n\n\n<li>Deployment status<\/li>\n\n\n\n<li>Service<\/li>\n\n\n\n<li>Logs<\/li>\n\n\n\n<li>Events<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The PostgreSQL pod should eventually show as running.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Click the <code>db-client<\/code> workload.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check that its pod is also running.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 8: Verify Resources Using CLI<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc project lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">List all major resources:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> deploy,po,svc,pvc,secret,cm\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected resources:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">deployment.apps\/postgresql\ndeployment.apps\/db-client\n\npod\/postgresql-xxxxx\npod\/db-client-xxxxx\n\nservice\/postgresql\n\npersistentvolumeclaim\/postgresql-data\n\nsecret\/postgresql-secret\n\nconfigmap\/postgresql-config\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check rollout status:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc rollout status deployment\/postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">deployment <span class=\"hljs-string\">\"postgresql\"<\/span> successfully rolled out\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check client rollout:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc rollout status deployment\/db-client\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">deployment <span class=\"hljs-string\">\"db-client\"<\/span> successfully rolled out\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check the PVC:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> pvc postgresql-data\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS\npostgresql-data   Bound    pvc-xxxxxx                                  1Gi        RWO            ...\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The <code>STATUS<\/code> should be:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Bound\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 9: Check PostgreSQL Logs<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">From the web console:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to <strong>Developer<\/strong> perspective.<\/li>\n\n\n\n<li>Open <strong>Topology<\/strong>.<\/li>\n\n\n\n<li>Click <code>postgresql<\/code>.<\/li>\n\n\n\n<li>Click the pod.<\/li>\n\n\n\n<li>Open the <strong>Logs<\/strong> tab.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Or use CLI:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc logs deployment\/postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You should see PostgreSQL initialization and startup messages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The exact log output may vary, but it should indicate that PostgreSQL started successfully.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 10: Connect to PostgreSQL from the Web Console Terminal<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Now connect to the database from inside the OpenShift cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the web console:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to <strong>Developer<\/strong> perspective.<\/li>\n\n\n\n<li>Open <strong>Topology<\/strong>.<\/li>\n\n\n\n<li>Click <code>db-client<\/code>.<\/li>\n\n\n\n<li>Open the running pod.<\/li>\n\n\n\n<li>Click the <strong>Terminal<\/strong> tab.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Inside the terminal, run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">psql -h <span class=\"hljs-string\">\"$PGHOST\"<\/span> -U <span class=\"hljs-string\">\"$PGUSER\"<\/span> -d <span class=\"hljs-string\">\"$PGDATABASE\"<\/span> -c <span class=\"hljs-string\">\"SELECT version();\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output should include PostgreSQL version information.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">PostgreSQL<\/span> 15<span class=\"hljs-selector-class\">.x<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Now check the current database and current user:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">psql -h <span class=\"hljs-string\">\"$PGHOST\"<\/span> -U <span class=\"hljs-string\">\"$PGUSER\"<\/span> -d <span class=\"hljs-string\">\"$PGDATABASE\"<\/span> -c <span class=\"hljs-string\">\"SELECT current_database(), current_user;\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\"> current_database | current_user\n------------------+--------------\n appdb            | appuser\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This confirms that the client pod can connect to the PostgreSQL database using the internal service name.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 11: Create a Table and Insert Data<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">From the <code>db-client<\/code> pod terminal, run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">psql -h <span class=\"hljs-string\">\"$PGHOST\"<\/span> -U <span class=\"hljs-string\">\"$PGUSER\"<\/span> -d <span class=\"hljs-string\">\"$PGDATABASE\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You should now be inside the PostgreSQL shell.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You will see a prompt similar to:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">appdb=&gt;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Create a table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">CREATE TABLE <span class=\"hljs-keyword\">IF<\/span> NOT EXISTS lab9_messages (\n  id SERIAL PRIMARY KEY,\n  student_name TEXT NOT <span class=\"hljs-keyword\">NULL<\/span>,\n  message TEXT NOT <span class=\"hljs-keyword\">NULL<\/span>,\n  created_at TIMESTAMP <span class=\"hljs-keyword\">DEFAULT<\/span> CURRENT_TIMESTAMP\n);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Insert a row:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">INSERT INTO lab9_messages(student_name, message)\nVALUES (<span class=\"hljs-string\">'student01'<\/span>, <span class=\"hljs-string\">'Hello from OpenShift Local Lab 9'<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Query the table:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">SELECT id, student_name, message, created_at\nFROM lab9_messages\nORDER BY id DESC\nLIMIT 5;\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"> id | student_name |              message               |         created_at\n----+--------------+------------------------------------+----------------------------\n  <span class=\"hljs-number\">1<\/span> | student01    | Hello <span class=\"hljs-keyword\">from<\/span> OpenShift Local Lab <span class=\"hljs-number\">9<\/span>   | ...\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Exit PostgreSQL:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\\q\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 12: One-Line SQL Test Alternative<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If copy-paste into the PostgreSQL shell is difficult, run the following one-line commands from the <code>db-client<\/code> pod terminal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create the table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">psql -h <span class=\"hljs-string\">\"$PGHOST\"<\/span> -U <span class=\"hljs-string\">\"$PGUSER\"<\/span> -d <span class=\"hljs-string\">\"$PGDATABASE\"<\/span> -c <span class=\"hljs-string\">\"CREATE TABLE IF NOT EXISTS lab9_messages (id SERIAL PRIMARY KEY, student_name TEXT NOT NULL, message TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Insert a row:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">psql -h <span class=\"hljs-string\">\"$PGHOST\"<\/span> -U <span class=\"hljs-string\">\"$PGUSER\"<\/span> -d <span class=\"hljs-string\">\"$PGDATABASE\"<\/span> -c <span class=\"hljs-string\">\"INSERT INTO lab9_messages(student_name, message) VALUES ('student01', 'Hello from OpenShift Local Lab 9');\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Query rows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">psql -h <span class=\"hljs-string\">\"$PGHOST\"<\/span> -U <span class=\"hljs-string\">\"$PGUSER\"<\/span> -d <span class=\"hljs-string\">\"$PGDATABASE\"<\/span> -c <span class=\"hljs-string\">\"SELECT id, student_name, message, created_at FROM lab9_messages ORDER BY id DESC LIMIT 5;\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 13: Verify Database Connectivity Using CLI<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">You can also run the SQL test from your local terminal using <code>oc exec<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, find the db-client pod:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> pods -l app=db-client\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Store the pod name in a variable:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">DB_CLIENT_POD=$(oc get pod -l app=db-client -o jsonpath=<span class=\"hljs-string\">'{.items&#91;0].metadata.name}'<\/span>)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Run a database query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"SELECT current_database(), current_user;\"'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\"> current_database | current_user\n------------------+--------------\n appdb            | appuser\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Create the table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"CREATE TABLE IF NOT EXISTS lab9_messages (id SERIAL PRIMARY KEY, student_name TEXT NOT NULL, message TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);\"'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Insert a row:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"INSERT INTO lab9_messages(student_name, message) VALUES ('<\/span>cli-user<span class=\"hljs-string\">', '<\/span>Inserted using oc exec <span class=\"hljs-keyword\">from<\/span> local terminal<span class=\"hljs-string\">');\"'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Query the table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"SELECT id, student_name, message, created_at FROM lab9_messages ORDER BY id DESC LIMIT 5;\"'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 14: Prove That the Service Name Works<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The database client connects to:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This name comes from the OpenShift Service:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">kind: Service\nmetadata:\n  name: postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Inside the same OpenShift project, pods can reach the database using:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">postgresql<\/span><span class=\"hljs-selector-pseudo\">:5432<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">To inspect the service, run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc describe service postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You should see:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"HTTP\" data-shcb-language-slug=\"http\"><span><code class=\"hljs language-http\"><span class=\"hljs-attribute\">Name<\/span>:              postgresql\n<span class=\"hljs-attribute\">Type<\/span>:              ClusterIP\n<span class=\"hljs-attribute\">Port<\/span>:              postgresql  5432\/TCP\n<span class=\"hljs-attribute\">Endpoints<\/span>:         ...\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTTP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">http<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The <code>Endpoints<\/code> field should point to the PostgreSQL pod IP and port.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 15: Prove That Data Persists After Pod Restart<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A database should not lose data just because the pod restarts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this lab, data is stored on the PersistentVolumeClaim named:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">postgresql-data\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Option A: Restart from Web Console<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to <strong>Developer<\/strong> perspective.<\/li>\n\n\n\n<li>Open <strong>Topology<\/strong>.<\/li>\n\n\n\n<li>Click the <code>postgresql<\/code> workload.<\/li>\n\n\n\n<li>Open the Deployment.<\/li>\n\n\n\n<li>Scale the Deployment to <code>0<\/code>.<\/li>\n\n\n\n<li>Wait until the PostgreSQL pod disappears.<\/li>\n\n\n\n<li>Scale the Deployment back to <code>1<\/code>.<\/li>\n\n\n\n<li>Wait until the new pod is running.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Now go back to the <code>db-client<\/code> pod terminal and run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">psql -h <span class=\"hljs-string\">\"$PGHOST\"<\/span> -U <span class=\"hljs-string\">\"$PGUSER\"<\/span> -d <span class=\"hljs-string\">\"$PGDATABASE\"<\/span> -c <span class=\"hljs-string\">\"SELECT id, student_name, message, created_at FROM lab9_messages ORDER BY id DESC LIMIT 5;\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Your previously inserted row should still exist.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Option B: Restart from CLI<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Scale PostgreSQL down:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc scale deployment\/postgresql --replicas=0\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Wait:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-39\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> pods -l app=postgresql\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-39\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Scale PostgreSQL back up:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc scale deployment\/postgresql --replicas=1\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Wait for rollout:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc rollout status deployment\/postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Query the data again:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-40\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"SELECT id, student_name, message, created_at FROM lab9_messages ORDER BY id DESC LIMIT 5;\"'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-40\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If the data is still visible, persistence is working.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 16: Check That No Route Was Created<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A PostgreSQL database should usually remain internal to the cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check routes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-41\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> route\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-41\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-42\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">No resources found <span class=\"hljs-keyword\">in<\/span> lab9-db-web-<span class=\"hljs-built_in\">console<\/span> namespace.\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-42\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is correct.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The database is reachable inside OpenShift using the Service:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-43\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">postgresql<\/span><span class=\"hljs-selector-pseudo\">:5432<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-43\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">It is not exposed outside the cluster.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 17: Student Checkpoint<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, students should be able to answer:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Question<\/th><th>Expected Answer<\/th><\/tr><\/thead><tbody><tr><td>What stores the database password?<\/td><td>Secret<\/td><\/tr><tr><td>What stores non-sensitive database settings?<\/td><td>ConfigMap<\/td><\/tr><tr><td>What gives the database a stable internal name?<\/td><td>Service<\/td><\/tr><tr><td>What stores database files?<\/td><td>PersistentVolumeClaim<\/td><\/tr><tr><td>What runs the PostgreSQL container?<\/td><td>Deployment<\/td><\/tr><tr><td>What is the internal database hostname?<\/td><td><code>postgresql<\/code><\/td><\/tr><tr><td>What is the PostgreSQL port?<\/td><td><code>5432<\/code><\/td><\/tr><tr><td>Should the database have an external Route?<\/td><td>No<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 18: Full CLI Validation Script<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Run the following commands from your local terminal after logging in with <code>oc<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-44\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">oc project lab9-db-web-console\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking deployments...\"<\/span>\noc get deployment\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking pods...\"<\/span>\noc get pods -o wide\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking service...\"<\/span>\noc get svc postgresql\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking PVC...\"<\/span>\noc get pvc postgresql-data\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking Secret and ConfigMap...\"<\/span>\noc get secret postgresql-secret\noc get configmap postgresql-config\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking PostgreSQL rollout...\"<\/span>\noc rollout status deployment\/postgresql\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking db-client rollout...\"<\/span>\noc rollout status deployment\/db-client\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Finding db-client pod...\"<\/span>\nDB_CLIENT_POD=$(oc get pod -l app=db-client -o jsonpath=<span class=\"hljs-string\">'{.items&#91;0].metadata.name}'<\/span>)\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"DB client pod: $DB_CLIENT_POD\"<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Running PostgreSQL connectivity test...\"<\/span>\noc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"SELECT current_database(), current_user;\"'<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking existing lab table...\"<\/span>\noc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"SELECT COUNT(*) FROM lab9_messages;\"'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-44\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected result:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Both Deployments should be available.<\/li>\n\n\n\n<li>Both pods should be running.<\/li>\n\n\n\n<li>The Service should exist.<\/li>\n\n\n\n<li>The PVC should be Bound.<\/li>\n\n\n\n<li>The PostgreSQL query should return <code>appdb<\/code> and <code>appuser<\/code>.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 19: Troubleshooting<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Problem 1: PostgreSQL Pod Shows ImagePullBackOff<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the pod:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-45\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> pods\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-45\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Describe the pod:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc describe pod -l app=postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check events:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-46\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> events --sort-by=.lastTimestamp\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-46\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Possible causes:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Red Hat registry pull secret issue.<\/li>\n\n\n\n<li>Network issue.<\/li>\n\n\n\n<li>Image name or tag not available in your environment.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Possible fix for a classroom lab:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Edit the Deployment image from:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">registry.redhat.io\/rhel9\/postgresql-15:latest\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">to:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">registry.access.redhat.com\/rhel9\/postgresql-15:latest\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then save and wait for the pod to restart.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Problem 2: PVC Is Pending<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the PVC:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-47\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> pvc\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-47\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Describe the PVC:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc describe pvc postgresql-data\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check storage classes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-48\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> storageclass\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-48\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Possible causes:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>No default StorageClass.<\/li>\n\n\n\n<li>OpenShift Local storage is not ready.<\/li>\n\n\n\n<li>Cluster is still starting.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">In OpenShift Local, wait a few minutes and check again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If there is no default StorageClass, ask the instructor to verify the OpenShift Local setup.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Problem 3: PostgreSQL Pod Is CrashLoopBackOff<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check logs:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc logs deployment\/postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check previous logs:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc logs deployment\/postgresql --previous\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Common causes:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Wrong environment variable names.<\/li>\n\n\n\n<li>Invalid database initialization.<\/li>\n\n\n\n<li>PVC already contains old incompatible data.<\/li>\n\n\n\n<li>Password changed after the database was already initialized.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">For a lab reset, delete and recreate the project:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-49\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">delete<\/span> project lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-49\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then create the project again and reapply the YAML.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Problem 4: Password Authentication Failed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you changed the Secret after PostgreSQL was already initialized, the database password inside the persistent data directory may not change automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For this beginner lab, the simplest reset is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-50\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">delete<\/span> project lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-50\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then recreate the project and apply the YAML again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In production, password rotation requires a planned database credential rotation process.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Problem 5: <code>psql<\/code> Command Not Found<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Make sure you are running the command inside the <code>db-client<\/code> pod, not your laptop terminal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From CLI:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-51\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">DB_CLIENT_POD=$(oc get pod -l app=db-client -o jsonpath=<span class=\"hljs-string\">'{.items&#91;0].metadata.name}'<\/span>)\noc exec -it <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-51\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">psql --version\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Problem 6: No Route Found<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is expected.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-52\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> route\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-52\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">No resources found\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">PostgreSQL is not an HTTP web application. It should normally be accessed internally through a Service, not exposed externally through a Route.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 20: Cleanup<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">To delete all resources created in this lab, delete the project.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From the web console:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Switch to <strong>Administrator<\/strong> perspective.<\/li>\n\n\n\n<li>Go to <strong>Home > Projects<\/strong>.<\/li>\n\n\n\n<li>Find:<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-53\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-53\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li>Delete the project.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Or use CLI:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-54\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">delete<\/span> project lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-54\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-55\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> project lab9-db-web-console\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-55\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The project should no longer exist.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 21: Lab Summary<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">In this lab, you created a database-backed OpenShift environment using the web console.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You created:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Resource<\/th><th>Purpose<\/th><\/tr><\/thead><tbody><tr><td>Secret<\/td><td>Stored database credentials<\/td><\/tr><tr><td>ConfigMap<\/td><td>Stored non-sensitive database configuration<\/td><\/tr><tr><td>PersistentVolumeClaim<\/td><td>Stored database data persistently<\/td><\/tr><tr><td>Deployment<\/td><td>Ran the PostgreSQL database<\/td><\/tr><tr><td>Service<\/td><td>Provided internal DNS name for PostgreSQL<\/td><\/tr><tr><td>Client Deployment<\/td><td>Tested database connectivity<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">You verified that:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>PostgreSQL runs inside OpenShift.<\/li>\n\n\n\n<li>The database is reachable by service name.<\/li>\n\n\n\n<li>Credentials can be injected from a Secret.<\/li>\n\n\n\n<li>Non-sensitive settings can be injected from a ConfigMap.<\/li>\n\n\n\n<li>Database data persists after pod restart.<\/li>\n\n\n\n<li>The database does not need an external Route.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 22: Lab Review Questions<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Question 1<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What is the purpose of a Secret in this lab?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A Secret stores sensitive data such as the database username, password, and database name.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 2<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What is the purpose of a ConfigMap in this lab?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A ConfigMap stores non-sensitive configuration such as database tuning values or application settings.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 3<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Why do we use a PersistentVolumeClaim?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A PersistentVolumeClaim provides persistent storage so database data is not lost when the pod restarts.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 4<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Why does PostgreSQL use a Service?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Service provides a stable internal DNS name and port for other pods to connect to PostgreSQL.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 5<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Why did we not create a Route for PostgreSQL?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A Route is mainly used to expose HTTP or HTTPS applications outside the cluster. PostgreSQL is a database service and should normally remain internal to the cluster.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 6<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What hostname does the client pod use to connect to PostgreSQL?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">postgresql\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 7<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What port does PostgreSQL listen on?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">5432\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 8<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Which resource runs the PostgreSQL container?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Deployment.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 9<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Which resource stores the PostgreSQL data files?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">PersistentVolumeClaim.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Question 10<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What command can you use to verify the PostgreSQL pod logs?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Answer<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc logs deployment\/postgresql\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 23: Instructor Notes<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This lab is designed as a replacement for older OpenShift database labs that used deprecated or outdated patterns.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The lab intentionally avoids:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>MongoDB 3.6<\/li>\n\n\n\n<li>DeploymentConfig<\/li>\n\n\n\n<li>Ephemeral-only database storage<\/li>\n\n\n\n<li>Hard-coded database URLs in application configuration<\/li>\n\n\n\n<li>Exposing a database using a Route<\/li>\n\n\n\n<li>Old OpenShift template-based database provisioning<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The lab teaches current OpenShift concepts:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Deployment<\/li>\n\n\n\n<li>Service<\/li>\n\n\n\n<li>Secret<\/li>\n\n\n\n<li>ConfigMap<\/li>\n\n\n\n<li>PersistentVolumeClaim<\/li>\n\n\n\n<li>Internal service discovery<\/li>\n\n\n\n<li>Pod terminal access<\/li>\n\n\n\n<li>CLI validation with <code>oc exec<\/code><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">For production environments, students should also learn:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>StatefulSet for production-grade stateful workloads<\/li>\n\n\n\n<li>Database Operators<\/li>\n\n\n\n<li>Automated backup and restore<\/li>\n\n\n\n<li>Monitoring and alerting<\/li>\n\n\n\n<li>Secret rotation<\/li>\n\n\n\n<li>TLS for database connections<\/li>\n\n\n\n<li>NetworkPolicy<\/li>\n\n\n\n<li>Resource sizing<\/li>\n\n\n\n<li>High availability<\/li>\n\n\n\n<li>Disaster recovery<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This lab is intentionally simple because it is focused on beginner-level OpenShift database fundamentals using the web console.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Part 24: Instructor Validation Checklist<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Before giving this lab to students, the instructor should run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-56\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">crc version\ncrc status\noc version\noc whoami\noc <span class=\"hljs-keyword\">get<\/span> nodes\noc <span class=\"hljs-keyword\">get<\/span> storageclass\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-56\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then apply the lab and validate:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-57\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc project lab9-db-web-<span class=\"hljs-built_in\">console<\/span>\noc <span class=\"hljs-keyword\">get<\/span> deploy,po,svc,pvc,secret,cm\noc rollout status deployment\/postgresql\noc rollout status deployment\/db-client\noc logs deployment\/postgresql\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-57\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-58\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">DB_CLIENT_POD=$(oc get pod -l app=db-client -o jsonpath=<span class=\"hljs-string\">'{.items&#91;0].metadata.name}'<\/span>)\n\noc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"SELECT version();\"'<\/span>\n\noc exec <span class=\"hljs-string\">\"$DB_CLIENT_POD\"<\/span> -- bash -lc <span class=\"hljs-string\">'psql -h \"$PGHOST\" -U \"$PGUSER\" -d \"$PGDATABASE\" -c \"SELECT current_database(), current_user;\"'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-58\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If these commands pass, the lab is ready for students.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Final Outcome<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">You have successfully completed the updated OpenShift Lab 9.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You deployed a PostgreSQL database using the OpenShift web console, configured it using Secret and ConfigMap, stored its data on a PersistentVolumeClaim, exposed it internally using a Service, and tested database connectivity from another pod inside the cluster.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lab Goal In this lab, you will deploy a PostgreSQL database on OpenShift Local using the OpenShift web console. You will create the database using modern OpenShift&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[5153],"tags":[],"class_list":["post-50076","post","type-post","status-publish","format-standard","hentry","category-openshift"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/50076","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=50076"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/50076\/revisions"}],"predecessor-version":[{"id":77154,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/50076\/revisions\/77154"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=50076"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=50076"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=50076"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}