{"id":50074,"date":"2026-06-23T06:35:27","date_gmt":"2026-06-23T06:35:27","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=50074"},"modified":"2026-06-23T06:35:30","modified_gmt":"2026-06-23T06:35:30","slug":"openshift-lab-8-work-with-databases-in-openshift-using-the-oc-cli-tool","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/openshift-lab-8-work-with-databases-in-openshift-using-the-oc-cli-tool\/","title":{"rendered":"OpenShift Lab 8: Work with Databases in OpenShift Using the oc CLI Tool"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Lab Objective<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this lab, you will deploy a PostgreSQL database in OpenShift using the <code>oc<\/code> CLI tool. You will learn how to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create a new OpenShift project.<\/li>\n\n\n\n<li>Store database credentials in a Kubernetes Secret.<\/li>\n\n\n\n<li>Create persistent storage for database data.<\/li>\n\n\n\n<li>Deploy PostgreSQL using a Deployment.<\/li>\n\n\n\n<li>Expose PostgreSQL internally using a Service.<\/li>\n\n\n\n<li>Connect to the database from another pod inside the same project.<\/li>\n\n\n\n<li>Create a table, insert data, and query data.<\/li>\n\n\n\n<li>Troubleshoot common database deployment issues.<\/li>\n\n\n\n<li>Clean up all lab resources.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Important Concept<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A database should normally <strong>not<\/strong> be exposed to the public internet using an OpenShift Route.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this lab:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PostgreSQL runs inside the OpenShift cluster.<\/li>\n\n\n\n<li>Other pods connect to PostgreSQL using the internal Service name.<\/li>\n\n\n\n<li>The database Service is called <code>postgresql<\/code>.<\/li>\n\n\n\n<li>Applications inside the same project can connect to it using:<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" 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-1\"><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<h2 class=\"wp-block-heading\">Lab Architecture<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Student Terminal\n      |\n      | oc CLI\n      v\nOpenShift Project: lab8-database-cli\n      |\n      +-- Secret: postgresql-secret\n      |\n      +-- PVC: postgresql-data\n      |\n      +-- Deployment: postgresql\n      |       |\n      |       +-- Pod: PostgreSQL database\n      |\n      +-- Service: postgresql\n      |\n      +-- Pod: pg-client\n              |\n              +-- connects to postgresql:5432\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before starting this lab, students should have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Access to an OpenShift cluster.<\/li>\n\n\n\n<li>The <code>oc<\/code> CLI installed.<\/li>\n\n\n\n<li>Permission to create a project.<\/li>\n\n\n\n<li>Permission to create pods, deployments, services, secrets, and PVCs.<\/li>\n\n\n\n<li>A working internet connection from the cluster to pull the container image.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This lab works best on:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>OpenShift Local \/ CRC<\/li>\n\n\n\n<li>OpenShift Developer Sandbox<\/li>\n\n\n\n<li>OpenShift Container Platform 4.x<\/li>\n\n\n\n<li>OKD 4.x<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Database Used in This Lab<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Item<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>Database<\/td><td>PostgreSQL<\/td><\/tr><tr><td>Version<\/td><td>PostgreSQL 15<\/td><\/tr><tr><td>Database image<\/td><td><code>quay.io\/sclorg\/postgresql-15-c9s:latest<\/code><\/td><\/tr><tr><td>Database service name<\/td><td><code>postgresql<\/code><\/td><\/tr><tr><td>Database port<\/td><td><code>5432<\/code><\/td><\/tr><tr><td>Database user<\/td><td><code>student<\/code><\/td><\/tr><tr><td>Database password<\/td><td><code>studentpass123<\/code><\/td><\/tr><tr><td>Database name<\/td><td><code>studentdb<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Verify <code>oc<\/code> CLI<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc version\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\">Client Version: ...\nServer Version: ...\nKubernetes Version: ...\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If you only see the client version and no server version, you are not logged in yet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Log in to OpenShift<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For OpenShift Local \/ CRC, first get credentials:<\/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\">Then log in using the command shown by CRC, for example:<\/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\">oc login https:<span class=\"hljs-comment\">\/\/api.crc.testing:6443 -u developer -p developer<\/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<p class=\"wp-block-paragraph\">For OpenShift Developer Sandbox, copy the login command from the web console and paste it into your terminal. It usually looks like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">oc login --token=<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">your-token<\/span>&gt;<\/span> --server=<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">your-api-server<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/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\">or your OpenShift username.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Create a New Project<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new project for this lab:<\/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\">oc <span class=\"hljs-keyword\">new<\/span>-project lab8-database-cli\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\">Expected output:<\/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\">Now using project <span class=\"hljs-string\">\"lab8-database-cli\"<\/span> on server ...\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 the current project:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc project\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-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">Using project <span class=\"hljs-string\">\"lab8-database-cli\"<\/span> on server ...\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<h2 class=\"wp-block-heading\">Step 4: Create a Secret for Database Credentials<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a Secret to store the database username, password, and database name.<\/p>\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\">oc create secret generic postgresql-secret \\\n  --<span class=\"hljs-keyword\">from<\/span>-literal=POSTGRESQL_USER=student \\\n  --<span class=\"hljs-keyword\">from<\/span>-literal=POSTGRESQL_PASSWORD=studentpass123 \\\n  --<span class=\"hljs-keyword\">from<\/span>-literal=POSTGRESQL_DATABASE=studentdb\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<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">secret\/postgresql-secret created\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify the Secret exists:<\/p>\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\">oc <span class=\"hljs-keyword\">get<\/span> secret postgresql-secret\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<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">NAME                TYPE     DATA   AGE\npostgresql-secret   Opaque   3      ...\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Do not print secret values in a real production environment. This is a training lab, so we are using simple demo credentials.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Create Persistent Storage for PostgreSQL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a PersistentVolumeClaim for database storage:<\/p>\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\">oc apply -f - &lt;&lt;<span class=\"hljs-string\">'EOF'<\/span>\n<span class=\"hljs-attr\">apiVersion<\/span>: 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\">spec<\/span>:\n  accessModes:\n    - ReadWriteOnce\n  <span class=\"hljs-attr\">resources<\/span>:\n    requests:\n      storage: <span class=\"hljs-number\">1<\/span>Gi\nEOF\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<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">persistentvolumeclaim\/postgresql-data created\n<\/code><\/span><\/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-11\" 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-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<p class=\"wp-block-paragraph\">Expected output when storage is available:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">NAME              STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE\npostgresql-data   Bound    ...      1Gi        RWO            ...            ...\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If the status is <code>Pending<\/code>, your cluster may not have a default StorageClass or you may not have storage quota. Continue to the troubleshooting section and use the ephemeral fallback.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6: Deploy PostgreSQL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create the PostgreSQL Deployment:<\/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\">oc apply -f - &lt;&lt;<span class=\"hljs-string\">'EOF'<\/span>\n<span class=\"hljs-attr\">apiVersion<\/span>: 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<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\">template<\/span>:\n    metadata:\n      labels:\n        app: postgresql\n    <span class=\"hljs-attr\">spec<\/span>:\n      containers:\n        - name: postgresql\n          <span class=\"hljs-attr\">image<\/span>: quay.io\/sclorg\/postgresql<span class=\"hljs-number\">-15<\/span>-c9s: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\">envFrom<\/span>:\n            - secretRef:\n                name: postgresql-secret\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\nEOF\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\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">deployment.apps\/postgresql created\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Wait for the deployment to become ready:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc rollout status deployment\/postgresql --timeout=180s\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-13\" 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-13\"><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 the pod:<\/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 <span class=\"hljs-keyword\">get<\/span> pods -l app=postgresql\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\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">NAME                          READY   STATUS    RESTARTS   AGE\npostgresql-xxxxxxxxxx-xxxxx   1\/1     Running   0          ...\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 7: Create an Internal Service for PostgreSQL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a Service so other pods can connect to PostgreSQL using a stable DNS name.<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc expose deployment\/postgresql \\\n  --port=5432 \\\n  --target-port=5432 \\\n  --name=postgresql\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\">service\/postgresql exposed\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify the Service:<\/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> svc postgresql\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 output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE\npostgresql   ClusterIP   ...             <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">none<\/span>&gt;<\/span>        5432\/TCP   ...\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Important: This Service is internal to the cluster. That is correct for a database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8: Check Database Logs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">View PostgreSQL logs:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc logs deployment\/postgresql --tail=50\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output should include PostgreSQL startup messages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PostgreSQL init process complete; ready for start up.\ndatabase system is ready to accept connections\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Exact log text can vary, but the important idea is that PostgreSQL should be ready to accept connections.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 9: Create a Temporary PostgreSQL Client Pod<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a temporary client pod that includes the <code>psql<\/code> command-line tool.<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc run pg-client \\\n  --image=quay.io\/sclorg\/postgresql-15-c9s:latest \\\n  --restart=Never \\\n  -- sleep 3600\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\">pod\/pg-client created\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Wait until the client pod is ready:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc wait --for=condition=Ready pod\/pg-client --timeout=120s\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\">pod\/pg-client condition met\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify both pods:<\/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\">oc <span class=\"hljs-keyword\">get<\/span> pods\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\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">NAME                          READY   STATUS    RESTARTS   AGE\npg-client                     1\/1     Running   0          ...\npostgresql-xxxxxxxxxx-xxxxx   1\/1     Running   0          ...\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 10: Test Database Connectivity<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">From the client pod, connect to PostgreSQL through the Service name.<\/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 exec pg-client -- sh -lc \\\n  <span class=\"hljs-string\">'PGPASSWORD=studentpass123 psql -h postgresql -U student -d studentdb -c \"SELECT version();\"'<\/span>\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\">version\n----------------------------------------------------------------------------------------------------\nPostgreSQL 15 ...\n(1 row)\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This proves:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The PostgreSQL pod is running.<\/li>\n\n\n\n<li>The Service name <code>postgresql<\/code> resolves inside the project.<\/li>\n\n\n\n<li>The username and password work.<\/li>\n\n\n\n<li>The database <code>studentdb<\/code> exists.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 11: Create a Table<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a table named <code>students<\/code>.<\/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\">oc exec pg-client -- sh -lc \\\n  <span class=\"hljs-string\">'PGPASSWORD=studentpass123 psql -h postgresql -U student -d studentdb -c \"CREATE TABLE IF NOT EXISTS students (id SERIAL PRIMARY KEY, name TEXT NOT NULL, city TEXT NOT NULL);\"'<\/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:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">CREATE TABLE\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 12: Insert Sample Data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Insert three records:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc exec pg-client -- sh -lc \\\n  <span class=\"hljs-string\">'PGPASSWORD=studentpass123 psql -h postgresql -U student -d studentdb -c \"INSERT INTO students (name, city) VALUES ('<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'Rajesh'<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">', '<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'Tokyo'<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'), ('<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'Asha'<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">', '<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'Bengaluru'<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'), ('<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'Miguel'<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">', '<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">'Madrid'<\/span><span class=\"hljs-string\">\"'\"<\/span><span class=\"hljs-string\">');\"'<\/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\">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\">INSERT 0 3\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 13: Query the Data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Query the table:<\/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\">oc exec pg-client -- sh -lc \\\n  <span class=\"hljs-string\">'PGPASSWORD=studentpass123 psql -h postgresql -U student -d studentdb -c \"SELECT * FROM students;\"'<\/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\"> id |  name  |   city\n----+--------+-----------\n  1 | Rajesh | Tokyo\n  2 | Asha   | Bengaluru\n  3 | Miguel | Madrid\n(3 rows)\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 14: Open an Interactive SQL Session<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can also open an interactive <code>psql<\/code> session:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc exec -it pg-client -- sh\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Inside the client pod, 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\"><span class=\"hljs-keyword\">export<\/span> PGPASSWORD=studentpass123\npsql -h postgresql -U student -d studentdb\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\">Inside <code>psql<\/code>, try:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\\dt\nSELECT * FROM students;\n\\q\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Exit the pod shell:<\/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\"><span class=\"hljs-keyword\">exit<\/span>\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<h2 class=\"wp-block-heading\">Step 15: Inspect the Running Resources<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Show all major resources in the project:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> all\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><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 include:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pod\/pg-client\npod\/postgresql-...\nservice\/postgresql\ndeployment.apps\/postgresql\nreplicaset.apps\/postgresql-...\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Show only database-related resources:<\/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\">oc <span class=\"hljs-keyword\">get<\/span> deployment,svc,pvc,secret,pod -l app=postgresql\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\">Note: The Secret and PVC may not show with this label because we did not label them. You can list them directly:<\/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\">oc <span class=\"hljs-keyword\">get<\/span> secret postgresql-secret\noc <span class=\"hljs-keyword\">get<\/span> pvc postgresql-data\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\">Describe the PostgreSQL Deployment:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc describe deployment postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Describe the PostgreSQL Service:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc describe service postgresql\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 16: Optional Local Port Forwarding<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your local machine has the <code>psql<\/code> client installed, you can forward PostgreSQL to your local machine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Start port forwarding:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc port-forward svc\/postgresql 5432:5432\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-27\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">Forwarding<\/span> <span class=\"hljs-selector-tag\">from<\/span> 127<span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.1<\/span><span class=\"hljs-selector-pseudo\">:5432<\/span> <span class=\"hljs-selector-tag\">-<\/span>&gt; 5432\n<span class=\"hljs-selector-tag\">Forwarding<\/span> <span class=\"hljs-selector-tag\">from<\/span> <span class=\"hljs-selector-attr\">&#91;::1]<\/span><span class=\"hljs-selector-pseudo\">:5432<\/span> <span class=\"hljs-selector-tag\">-<\/span>&gt; 5432\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><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\">Keep this terminal open.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In another terminal, connect locally:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">PGPASSWORD=studentpass123 psql -h 127.0.0.1 -U student -d studentdb\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Exit <code>psql<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\\q\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Stop port forwarding with:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Ctrl+C\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 17: Why We Do Not Create a Route for PostgreSQL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not run this for the database:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc expose service\/postgresql\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">A Route is normally used for HTTP\/HTTPS web applications. PostgreSQL is a database service and should usually stay private inside the cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Correct database access pattern:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Application Pod -&gt; Service postgresql -&gt; PostgreSQL Pod\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Incorrect beginner pattern:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Internet -&gt; Route -&gt; PostgreSQL\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 18: Do Not Scale This Database Deployment<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not scale this PostgreSQL Deployment to multiple replicas:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc scale deployment\/postgresql --replicas=2\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">A single PostgreSQL database using one <code>ReadWriteOnce<\/code> volume should not be scaled like a stateless web application. For real high availability, use a database Operator or managed database service.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For this lab, keep:<\/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\">Expected output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">deployment.apps\/postgresql scaled\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 1: PVC Stays Pending<\/h3>\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-28\" 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-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\">If it shows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"HTTP\" data-shcb-language-slug=\"http\"><span><code class=\"hljs language-http\"><span class=\"hljs-attribute\">STATUS<\/span>: Pending\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><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\">Possible reasons:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>No default StorageClass.<\/li>\n\n\n\n<li>No available persistent volumes.<\/li>\n\n\n\n<li>Storage quota exceeded.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Check storage classes:<\/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> storageclass\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\">If your training cluster does not support persistent storage, use the ephemeral fallback below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 2: Pod Shows ImagePullBackOff<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check pod status:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" 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-31\"><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\">Possible reasons:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Cluster cannot pull from the image registry.<\/li>\n\n\n\n<li>Network egress is blocked.<\/li>\n\n\n\n<li>Registry is temporarily unavailable.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 3: Pod Shows CrashLoopBackOff<\/h3>\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 --tail=100\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Common causes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Secret name is wrong.<\/li>\n\n\n\n<li>Required environment variables are missing.<\/li>\n\n\n\n<li>Storage mount has permission problems.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Problem 4: Client Cannot Resolve Hostname<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If this command fails:<\/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 pg-client -- sh -lc \\\n  <span class=\"hljs-string\">'PGPASSWORD=studentpass123 psql -h postgresql -U student -d studentdb -c \"SELECT version();\"'<\/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\">Check that the Service exists:<\/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 <span class=\"hljs-keyword\">get<\/span> svc postgresql\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\">Check that both pods are in the same project:<\/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 project\noc <span class=\"hljs-keyword\">get<\/span> pods\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<h2 class=\"wp-block-heading\">Ephemeral Fallback: Use This Only If PVC Is Not Available<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your cluster does not provide persistent storage, delete the existing deployment and PVC:<\/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 <span class=\"hljs-keyword\">delete<\/span> deployment postgresql --ignore-not-found=<span class=\"hljs-literal\">true<\/span>\noc <span class=\"hljs-keyword\">delete<\/span> pvc postgresql-data --ignore-not-found=<span class=\"hljs-literal\">true<\/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<p class=\"wp-block-paragraph\">Create an ephemeral PostgreSQL deployment using <code>emptyDir<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc apply -f - &lt;&lt;<span class=\"hljs-string\">'EOF'<\/span>\n<span class=\"hljs-attr\">apiVersion<\/span>: 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<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\">template<\/span>:\n    metadata:\n      labels:\n        app: postgresql\n    <span class=\"hljs-attr\">spec<\/span>:\n      containers:\n        - name: postgresql\n          <span class=\"hljs-attr\">image<\/span>: quay.io\/sclorg\/postgresql<span class=\"hljs-number\">-15<\/span>-c9s: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\">envFrom<\/span>:\n            - secretRef:\n                name: postgresql-secret\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\">emptyDir<\/span>: {}\nEOF\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><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\">Wait for rollout:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">oc rollout status deployment\/postgresql --timeout=180s\n<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If the Service already exists, keep it. If not, create it:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> svc postgresql || oc expose deployment\/postgresql --port=5432 --target-port=5432 --name=postgresql\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><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\">Warning: With <code>emptyDir<\/code>, database data is lost when the pod is deleted or recreated. Use this only for temporary training labs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cleanup Option 1: Delete Only Lab Resources<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Delete the client pod:<\/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\">oc <span class=\"hljs-keyword\">delete<\/span> pod pg-client --ignore-not-found=<span class=\"hljs-literal\">true<\/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\">Delete the PostgreSQL Service:<\/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\">delete<\/span> service postgresql --ignore-not-found=<span class=\"hljs-literal\">true<\/span>\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\">Delete the PostgreSQL Deployment:<\/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 <span class=\"hljs-keyword\">delete<\/span> deployment postgresql --ignore-not-found=<span class=\"hljs-literal\">true<\/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\">Delete the PVC:<\/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\">delete<\/span> pvc postgresql-data --ignore-not-found=<span class=\"hljs-literal\">true<\/span>\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\">Delete the Secret:<\/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\">oc <span class=\"hljs-keyword\">delete<\/span> secret postgresql-secret --ignore-not-found=<span class=\"hljs-literal\">true<\/span>\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\">Verify cleanup:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-43\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">get<\/span> all\noc <span class=\"hljs-keyword\">get<\/span> pvc\noc <span class=\"hljs-keyword\">get<\/span> secret postgresql-secret\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-43\"><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<h2 class=\"wp-block-heading\">Cleanup Option 2: Delete the Whole Project<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If this project was created only for the lab, delete the whole project:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-44\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">oc <span class=\"hljs-keyword\">delete<\/span> project lab8-database-cli\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-44\"><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-45\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">project<\/span><span class=\"hljs-selector-class\">.project<\/span><span class=\"hljs-selector-class\">.openshift<\/span><span class=\"hljs-selector-class\">.io<\/span> \"<span class=\"hljs-selector-tag\">lab8-database-cli<\/span>\" <span class=\"hljs-selector-tag\">deleted<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-45\"><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<h2 class=\"wp-block-heading\">Lab Review Questions<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Why did we store database credentials in a Secret instead of directly writing them in the Deployment?<\/li>\n\n\n\n<li>Why did we create a Service for PostgreSQL?<\/li>\n\n\n\n<li>Why did we not create an OpenShift Route for PostgreSQL?<\/li>\n\n\n\n<li>What is the difference between persistent storage and <code>emptyDir<\/code>?<\/li>\n\n\n\n<li>Why should this PostgreSQL Deployment not be scaled to multiple replicas?<\/li>\n\n\n\n<li>How would an application in the same project connect to this database?<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Key Takeaways<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Databases in OpenShift should normally be exposed internally with Services, not public Routes.<\/li>\n\n\n\n<li>Secrets are used to store sensitive configuration such as database usernames and passwords.<\/li>\n\n\n\n<li>PersistentVolumeClaims are used to request durable storage.<\/li>\n\n\n\n<li>Pods should connect to databases using Service DNS names.<\/li>\n\n\n\n<li>PostgreSQL listens on port <code>5432<\/code>.<\/li>\n\n\n\n<li>Stateful databases require different scaling and availability patterns than stateless web applications.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lab Objective In this lab, you will deploy a PostgreSQL database in OpenShift using the oc CLI tool. You will learn how to: Important Concept A database&#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-50074","post","type-post","status-publish","format-standard","hentry","category-openshift"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/50074","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=50074"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/50074\/revisions"}],"predecessor-version":[{"id":77151,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/50074\/revisions\/77151"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=50074"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=50074"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=50074"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}